refactor: debugging extension loading (#156)
* refactor: debugging extension loading * revert: header svg
|
Before Width: | Height: | Size: 622 KiB After Width: | Height: | Size: 622 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "cose-extension",
|
||||
"version": "1.2.2",
|
||||
"description": "Create Once, Sync Everywhere. 一键将文章同步到多个平台",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "mkdir -p /tmp/chrome-debug-profile && web-ext run --source-dir ./dist --target=chromium --chromium-binary \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\" --chromium-profile /tmp/chrome-debug-profile --keep-profile-changes",
|
||||
"dev:chrome": "mkdir -p /tmp/chrome-debug-profile && '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-profile --load-extension=$(pwd)/dist",
|
||||
"dev:watch": "node scripts/reload-extension.mjs",
|
||||
"build": "tsx scripts/cli.ts build",
|
||||
"build:firefox": "tsx scripts/cli.ts build --target firefox",
|
||||
"build:safari": "tsx scripts/cli.ts build --target safari",
|
||||
"build:release": "tsx scripts/cli.ts build --release",
|
||||
"watch": "tsx scripts/cli.ts build --watch",
|
||||
"lint": "web-ext lint --source-dir ./dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cose/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cac": "^6.7.14",
|
||||
"execa": "^9.6.1",
|
||||
"rimraf": "^5.0.5",
|
||||
"tsx": "^4.21.0",
|
||||
"vite": "^5.0.12",
|
||||
"vite-plugin-static-copy": "^1.0.1",
|
||||
"web-ext": "^7.11.0",
|
||||
"ws": "^8.19.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
import { cac } from 'cac'
|
||||
import { execa } from 'execa'
|
||||
import { build as viteBuild } from 'vite'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const dirname = fileURLToPath(new URL('./', import.meta.url))
|
||||
const rootDir = path.join(dirname, '..')
|
||||
|
||||
// Read package.json for version
|
||||
const packageJsonPath = path.join(rootDir, 'package.json')
|
||||
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'))
|
||||
|
||||
// Firefox background uses scripts array, Chrome uses service_worker
|
||||
interface FirefoxBackgroundOptions {
|
||||
scripts: string[]
|
||||
type: 'module'
|
||||
}
|
||||
|
||||
interface ChromeBackgroundOptions {
|
||||
service_worker: string
|
||||
type: 'module'
|
||||
}
|
||||
|
||||
// Full manifest type for COSE extension
|
||||
interface Manifest {
|
||||
manifest_version: number
|
||||
name: string
|
||||
version: string
|
||||
description: string
|
||||
permissions: string[]
|
||||
host_permissions: string[]
|
||||
action: {
|
||||
default_icon: Record<string, string>
|
||||
default_title: string
|
||||
}
|
||||
background: FirefoxBackgroundOptions | ChromeBackgroundOptions
|
||||
content_scripts: Array<{
|
||||
matches: string[]
|
||||
js: string[]
|
||||
run_at: string
|
||||
}>
|
||||
icons: Record<string, string>
|
||||
web_accessible_resources: Array<{
|
||||
resources: string[]
|
||||
matches: string[]
|
||||
}>
|
||||
browser_specific_settings?: {
|
||||
gecko: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const readManifest = async (manifestPath: string): Promise<Manifest | undefined> => {
|
||||
try {
|
||||
const fileContent = await fs.readFile(manifestPath, 'utf8')
|
||||
const json = JSON.parse(fileContent) as Manifest
|
||||
return json
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
interface BuildOptions {
|
||||
watch: boolean
|
||||
release: boolean
|
||||
target: 'chromium' | 'firefox' | 'safari'
|
||||
bundleId?: string
|
||||
}
|
||||
|
||||
const buildWithVite = async (options: BuildOptions) => {
|
||||
console.log('Building with Vite...')
|
||||
|
||||
await viteBuild({
|
||||
root: rootDir,
|
||||
mode: options.release ? 'production' : 'development',
|
||||
build: {
|
||||
minify: options.release,
|
||||
watch: options.watch ? {} : null,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const copyResources = async () => {
|
||||
console.log('Copying resources...')
|
||||
|
||||
interface CopyEntry {
|
||||
from: string
|
||||
to: string
|
||||
}
|
||||
|
||||
const copyEntries: CopyEntry[] = [
|
||||
{
|
||||
from: path.join(rootDir, 'icons'),
|
||||
to: path.join(rootDir, 'dist/icons'),
|
||||
},
|
||||
{
|
||||
from: path.join(rootDir, 'assets'),
|
||||
to: path.join(rootDir, 'dist/assets'),
|
||||
},
|
||||
{
|
||||
// Copy platform scripts from core package
|
||||
from: path.resolve(rootDir, '../../packages/core/src/platforms'),
|
||||
to: path.join(rootDir, 'dist/src/platforms'),
|
||||
},
|
||||
]
|
||||
|
||||
for (const entry of copyEntries) {
|
||||
try {
|
||||
// Check if source exists
|
||||
await fs.access(entry.from)
|
||||
// Remove destination if exists
|
||||
await fs.rm(entry.to, { recursive: true, force: true })
|
||||
// Copy
|
||||
await fs.cp(entry.from, entry.to, { recursive: true })
|
||||
console.log(` ✓ Copied ${path.basename(entry.from)}`)
|
||||
} catch (error) {
|
||||
// Source doesn't exist, skip
|
||||
console.log(` ⚠ Skipped ${path.basename(entry.from)} (not found)`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const genManifest = async (options: BuildOptions) => {
|
||||
console.log('Generating manifest.json...')
|
||||
|
||||
const manifest = await readManifest(path.join(rootDir, 'manifest.json'))
|
||||
|
||||
if (!manifest) {
|
||||
throw new Error('manifest.json not found')
|
||||
}
|
||||
|
||||
if (!manifest.background) {
|
||||
throw new Error('manifest.background not found')
|
||||
}
|
||||
|
||||
// Firefox-specific adjustments
|
||||
if (options.target === 'firefox' && 'service_worker' in manifest.background) {
|
||||
// Convert service_worker to scripts array for Firefox
|
||||
manifest.background = {
|
||||
scripts: [manifest.background.service_worker],
|
||||
type: 'module',
|
||||
}
|
||||
|
||||
// Add Firefox-specific settings
|
||||
manifest.browser_specific_settings = {
|
||||
gecko: {
|
||||
id: 'cose@doocs.org',
|
||||
},
|
||||
}
|
||||
|
||||
console.log(' ✓ Converted to Firefox manifest format')
|
||||
}
|
||||
|
||||
// Sync version from package.json
|
||||
manifest.version = packageJson.version
|
||||
|
||||
// Write manifest to dist
|
||||
const outputPath = path.join(rootDir, 'dist/manifest.json')
|
||||
await fs.writeFile(
|
||||
outputPath,
|
||||
JSON.stringify(manifest, null, options.release ? undefined : 2)
|
||||
)
|
||||
|
||||
console.log(` ✓ Generated manifest.json (version: ${manifest.version})`)
|
||||
}
|
||||
|
||||
const buildSafariExtension = async (options: BuildOptions) => {
|
||||
console.log('\nConverting to Safari extension...')
|
||||
|
||||
// Check if xcrun is available (macOS only)
|
||||
try {
|
||||
await execa('xcrun', ['--version'])
|
||||
} catch {
|
||||
throw new Error(
|
||||
'xcrun not found. Safari extension conversion requires:\n' +
|
||||
' 1. macOS\n' +
|
||||
' 2. Xcode installed (with Command Line Tools)\n' +
|
||||
' 3. Run: xcode-select --install'
|
||||
)
|
||||
}
|
||||
|
||||
const safariProjectDir = path.join(rootDir, 'safari-extension')
|
||||
const bundleId = options.bundleId || 'org.doocs.cose'
|
||||
|
||||
// Remove existing Safari project
|
||||
await fs.rm(safariProjectDir, { recursive: true, force: true })
|
||||
|
||||
console.log(` Bundle ID: ${bundleId}`)
|
||||
console.log(` Project location: ${safariProjectDir}`)
|
||||
|
||||
try {
|
||||
const result = await execa('xcrun', [
|
||||
'safari-web-extension-converter',
|
||||
path.join(rootDir, 'dist'),
|
||||
'--project-location', safariProjectDir,
|
||||
'--app-name', 'COSE',
|
||||
'--bundle-identifier', bundleId,
|
||||
'--swift',
|
||||
'--no-prompt',
|
||||
'--no-open'
|
||||
])
|
||||
console.log(result.stdout)
|
||||
console.log('\n ✓ Safari extension project created!')
|
||||
console.log(` ✓ Open in Xcode: open ${safariProjectDir}/COSE/COSE.xcodeproj`)
|
||||
} catch (error: unknown) {
|
||||
const err = error as { stderr?: string; message?: string }
|
||||
console.error('Safari conversion failed:', err.stderr || err.message)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// CLI setup
|
||||
const cli = cac('cose-build')
|
||||
cli.help().version(packageJson.version)
|
||||
|
||||
cli
|
||||
.command('build', 'Build the COSE browser extension')
|
||||
.option('-w, --watch', 'Watch mode', { default: false })
|
||||
.option('-r, --release', 'Build in release mode with optimizations', { default: false })
|
||||
.option('--target <target>', 'Browser target: "chromium", "firefox", or "safari"', { default: 'chromium' })
|
||||
.option('--bundle-id <bundleId>', 'Bundle ID for Safari (default: org.doocs.cose)')
|
||||
.action(async (options: BuildOptions) => {
|
||||
const validTargets = ['chromium', 'firefox', 'safari']
|
||||
if (!validTargets.includes(options.target)) {
|
||||
throw new Error(`Invalid target: ${options.target}. Use "chromium", "firefox", or "safari".`)
|
||||
}
|
||||
|
||||
console.log(`\n=== COSE Build (target: ${options.target}, release: ${options.release}) ===\n`)
|
||||
|
||||
// Step 1: Build with Vite
|
||||
await buildWithVite(options)
|
||||
|
||||
// Step 2: Copy resources
|
||||
await copyResources()
|
||||
|
||||
// Step 3: Generate manifest
|
||||
await genManifest(options)
|
||||
|
||||
// Step 4: Target-specific post-processing
|
||||
if (options.target === 'firefox') {
|
||||
console.log('\nRunning web-ext lint...')
|
||||
try {
|
||||
const result = await execa('pnpm', ['exec', 'web-ext', 'lint', '--source-dir', 'dist'])
|
||||
console.log(result.stdout)
|
||||
} catch (error) {
|
||||
console.error('web-ext lint failed:', error)
|
||||
}
|
||||
} else if (options.target === 'safari') {
|
||||
await buildSafariExtension(options)
|
||||
}
|
||||
|
||||
console.log(`\n=== Build complete! ===\n`)
|
||||
})
|
||||
|
||||
cli.parse(process.argv, { run: false })
|
||||
await cli.runMatchedCommand()
|
||||
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* 监听 dist 目录变化,自动刷新 Chrome 扩展
|
||||
*/
|
||||
|
||||
import { watch } from 'fs'
|
||||
import { join, dirname } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const distDir = join(__dirname, '..', 'dist')
|
||||
const CDP_URL = 'http://127.0.0.1:9222'
|
||||
|
||||
let reloadTimeout = null
|
||||
|
||||
async function reloadExtension() {
|
||||
try {
|
||||
const res = await fetch(`${CDP_URL}/json/list`)
|
||||
const pages = await res.json()
|
||||
|
||||
const extPage = pages.find(p => p.url.includes('chrome://extensions'))
|
||||
if (!extPage) {
|
||||
console.log('[reload] 未找到 chrome://extensions 页面,请打开该页面')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[reload] 正在重新加载扩展...')
|
||||
|
||||
const ws = new WebSocket(extPage.webSocketDebuggerUrl)
|
||||
|
||||
await new Promise((resolve) => {
|
||||
ws.on('open', () => {
|
||||
// 在 extensions 页面中找到 COSE 扩展并点击刷新按钮
|
||||
ws.send(JSON.stringify({
|
||||
id: 1,
|
||||
method: 'Runtime.evaluate',
|
||||
params: {
|
||||
expression: `
|
||||
(async () => {
|
||||
// 获取 extensions-manager
|
||||
const manager = document.querySelector('extensions-manager');
|
||||
if (!manager) return 'no-manager';
|
||||
|
||||
// 获取 extensions-item-list
|
||||
const itemList = manager.shadowRoot.querySelector('extensions-item-list');
|
||||
if (!itemList) return 'no-item-list';
|
||||
|
||||
// 获取所有扩展卡片
|
||||
const items = itemList.shadowRoot.querySelectorAll('extensions-item');
|
||||
|
||||
for (const item of items) {
|
||||
const name = item.shadowRoot.querySelector('#name')?.textContent || '';
|
||||
if (name.includes('COSE') || name.includes('多平台')) {
|
||||
// 找到刷新按钮并点击
|
||||
const reloadBtn = item.shadowRoot.querySelector('#dev-reload-button');
|
||||
if (reloadBtn) {
|
||||
reloadBtn.click();
|
||||
return 'ok';
|
||||
}
|
||||
return 'no-reload-btn';
|
||||
}
|
||||
}
|
||||
return 'not-found';
|
||||
})()
|
||||
`,
|
||||
awaitPromise: true
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
ws.on('message', (data) => {
|
||||
const msg = JSON.parse(data.toString())
|
||||
if (msg.id === 1) {
|
||||
const result = msg.result?.result?.value
|
||||
if (result === 'ok') {
|
||||
console.log('[reload] ✓ 扩展已重新加载')
|
||||
} else if (result === 'no-reload-btn') {
|
||||
console.log('[reload] ⚠ 未找到刷新按钮,请开启 Developer mode')
|
||||
} else if (result === 'not-found') {
|
||||
console.log('[reload] ⚠ 未找到 COSE 扩展')
|
||||
} else {
|
||||
console.log('[reload] ⚠ 刷新失败:', result)
|
||||
}
|
||||
ws.close()
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
|
||||
ws.on('error', (e) => {
|
||||
console.log('[reload] 连接错误:', e.message)
|
||||
resolve()
|
||||
})
|
||||
|
||||
setTimeout(() => { ws.close(); resolve() }, 3000)
|
||||
})
|
||||
} catch (e) {
|
||||
console.log('[reload] 失败:', e.message)
|
||||
}
|
||||
}
|
||||
|
||||
function debounceReload() {
|
||||
if (reloadTimeout) clearTimeout(reloadTimeout)
|
||||
reloadTimeout = setTimeout(reloadExtension, 800)
|
||||
}
|
||||
|
||||
console.log(`[reload] 监听 ${distDir} 目录变化...`)
|
||||
console.log('[reload] 确保:')
|
||||
console.log(' 1. Chrome 已用 --remote-debugging-port=9222 启动')
|
||||
console.log(' 2. chrome://extensions 页面已打开')
|
||||
console.log(' 3. Developer mode 已开启')
|
||||
|
||||
watch(distDir, { recursive: true }, (eventType, filename) => {
|
||||
if (filename && !filename.includes('.DS_Store')) {
|
||||
console.log(`[reload] 检测到变化: ${filename}`)
|
||||
debounceReload()
|
||||
}
|
||||
})
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n[reload] 已停止')
|
||||
process.exit(0)
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": [
|
||||
"scripts/**/*.ts"
|
||||
]
|
||||
}
|
||||
@@ -4,6 +4,12 @@ import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
|
||||
export default defineConfig({
|
||||
root: '.', // 项目根目录
|
||||
resolve: {
|
||||
alias: {
|
||||
'@cose/core': resolve(__dirname, '../../packages/core'),
|
||||
'@cose/detection': resolve(__dirname, '../../packages/detection')
|
||||
}
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
emptyOutDir: true,
|
||||
@@ -1,19 +1,16 @@
|
||||
{
|
||||
"name": "cose-extension",
|
||||
"version": "1.2.2",
|
||||
"description": "Create Once, Sync Everywhere. 一键将文章同步到多个平台",
|
||||
"type": "module",
|
||||
"name": "cose-monorepo",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "web-ext run --source-dir ./dist --target=chromium --chromium-profile \"/tmp/chrome-debug-profile\" --keep-profile-changes --args=\"--remote-debugging-port=9222\"",
|
||||
"build": "vite build",
|
||||
"watch": "vite build --watch",
|
||||
"lint": "web-ext lint --source-dir ./dist"
|
||||
"build": "pnpm -C apps/extension build",
|
||||
"build:firefox": "pnpm -C apps/extension build:firefox",
|
||||
"build:safari": "pnpm -C apps/extension build:safari",
|
||||
"dev": "pnpm -C apps/extension dev",
|
||||
"dev:chrome": "pnpm -C apps/extension dev:chrome",
|
||||
"dev:watch": "pnpm -C apps/extension dev:watch",
|
||||
"lint": "pnpm -r lint"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.12",
|
||||
"web-ext": "^7.11.0",
|
||||
"vite-plugin-static-copy": "^1.0.1",
|
||||
"rimraf": "^5.0.5"
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './src/utils.js';
|
||||
// Re-export login detection from @cose/detection
|
||||
export * from '@cose/detection';
|
||||
// Platform exports will be handled dynamically or imported directly
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@cose/core",
|
||||
"version": "1.0.0",
|
||||
"description": "Core publishing logic for COSE",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./platforms/*": "./src/platforms/*.js",
|
||||
"./utils": "./src/utils.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cose/detection": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,6 @@ const AlipayOpenPlatform = {
|
||||
type: 'alipayopen',
|
||||
}
|
||||
|
||||
// 支付宝开放平台登录检测配置
|
||||
const AlipayOpenLoginConfig = {
|
||||
api: 'https://developerportal.alipay.com/account/getOpenAccount.json',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.stat === 'ok' && !!response?.data,
|
||||
getUserInfo: (response) => {
|
||||
const data = response?.data
|
||||
return {
|
||||
username: data?.name || data?.logonId,
|
||||
avatar: data?.avatar,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝开放平台内容填充函数
|
||||
* 注意:此函数会被序列化后通过 chrome.scripting.executeScript 注入页面执行
|
||||
@@ -117,4 +103,4 @@ function fillAlipayOpenContent(title, markdown) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { AlipayOpenPlatform, AlipayOpenLoginConfig, fillAlipayOpenContent }
|
||||
export { AlipayOpenPlatform, fillAlipayOpenContent }
|
||||
@@ -9,14 +9,6 @@ const AliyunPlatform = {
|
||||
type: 'aliyun',
|
||||
}
|
||||
|
||||
// 阿里云开发者社区登录检测配置
|
||||
const AliyunLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://developer.aliyun.com',
|
||||
cookieNames: ['login_aliyunid_ticket', 'login_aliyunid_csrf'],
|
||||
// 通过 API 获取用户信息
|
||||
}
|
||||
|
||||
// 阿里云开发者社区内容填充函数
|
||||
async function fillAliyunContent(content) {
|
||||
const { title, markdown } = content
|
||||
@@ -57,4 +49,4 @@ async function fillAliyunContent(content) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { AliyunPlatform, AliyunLoginConfig, fillAliyunContent }
|
||||
export { AliyunPlatform, fillAliyunContent }
|
||||
@@ -9,14 +9,6 @@ const BaijiahaoPlat = {
|
||||
type: 'baijiahao',
|
||||
}
|
||||
|
||||
// 百家号登录检测配置
|
||||
const BaijiahaoLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://baijiahao.baidu.com',
|
||||
cookieNames: ['BDUSS'],
|
||||
// 百家号需要特殊处理,在 background.js 中单独实现
|
||||
}
|
||||
|
||||
// 百家号内容填充函数
|
||||
async function fillBaijiahaoContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -98,4 +90,4 @@ async function fillBaijiahaoContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { BaijiahaoPlat as BaijiahaoPlatform, BaijiahaoLoginConfig, fillBaijiahaoContent }
|
||||
export { BaijiahaoPlat as BaijiahaoPlatform, fillBaijiahaoContent }
|
||||
@@ -10,17 +10,6 @@ const BilibiliPlatform = {
|
||||
type: 'bilibili',
|
||||
}
|
||||
|
||||
// B站专栏登录检测配置
|
||||
const BilibiliLoginConfig = {
|
||||
api: 'https://api.bilibili.com/x/web-interface/nav',
|
||||
method: 'GET',
|
||||
checkLogin: (data) => data?.code === 0 && data?.data?.isLogin === true,
|
||||
getUserInfo: (data) => ({
|
||||
username: data?.data?.uname || '',
|
||||
avatar: data?.data?.face || '',
|
||||
}),
|
||||
}
|
||||
|
||||
// B站专栏内容填充函数(由 background.js 处理)
|
||||
// 使用 UEditor 的 execCommand('inserthtml') 方法插入 HTML 内容
|
||||
async function fillBilibiliContent(content, waitFor, setInputValue) {
|
||||
@@ -28,4 +17,4 @@ async function fillBilibiliContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { BilibiliPlatform, BilibiliLoginConfig, fillBilibiliContent }
|
||||
export { BilibiliPlatform, fillBilibiliContent }
|
||||
@@ -9,17 +9,6 @@ const CnblogsPlatform = {
|
||||
type: 'cnblogs',
|
||||
}
|
||||
|
||||
// 博客园登录检测配置
|
||||
const CnblogsLoginConfig = {
|
||||
api: 'https://i.cnblogs.com/api/user',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.loginName,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.displayName || response?.loginName,
|
||||
avatar: response?.avatarName ? `https:${response.avatarName}` : '',
|
||||
}),
|
||||
}
|
||||
|
||||
// 博客园内容填充函数
|
||||
async function fillCnblogsContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -67,4 +56,4 @@ async function fillCnblogsContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { CnblogsPlatform, CnblogsLoginConfig, fillCnblogsContent }
|
||||
export { CnblogsPlatform, fillCnblogsContent }
|
||||
@@ -0,0 +1,3 @@
|
||||
// Re-export from utils.js for backward compatibility
|
||||
export * from '../utils.js'
|
||||
export { injectUtils } from '../utils.js'
|
||||
@@ -9,36 +9,6 @@ const CSDNPlatform = {
|
||||
type: 'csdn',
|
||||
}
|
||||
|
||||
// CSDN 登录检测配置
|
||||
const CSDNLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://blog.csdn.net',
|
||||
cookieNames: ['UserName', 'UserNick'],
|
||||
getUsernameFromCookie: true,
|
||||
usernameCookie: 'UserNick',
|
||||
usernameCookieForApi: 'UserName',
|
||||
// 头像获取函数 - 从用户页面抓取
|
||||
fetchAvatar: async (cookieMap) => {
|
||||
const apiUsername = cookieMap['UserName']
|
||||
if (!apiUsername) return null
|
||||
try {
|
||||
const response = await fetch(`https://blog.csdn.net/${apiUsername}`, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
})
|
||||
const html = await response.text()
|
||||
const avatarMatch = html.match(/https:\/\/i-avatar\.csdnimg\.cn\/[^"'\s!]+/i)
|
||||
if (avatarMatch) {
|
||||
const originalUrl = avatarMatch[0] + '!1'
|
||||
return `https://wsrv.nl/?url=${encodeURIComponent(originalUrl)}&w=64&h=64`
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[COSE] CSDN 获取头像失败:', e.message)
|
||||
}
|
||||
return null
|
||||
},
|
||||
}
|
||||
|
||||
import { injectUtils } from './common.js'
|
||||
|
||||
// CSDN 内容填充函数(在页面主世界中执行)
|
||||
@@ -122,5 +92,5 @@ async function syncCSDNContent(tab, content, helpers) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { CSDNPlatform, CSDNLoginConfig, fillCSDNContent, syncCSDNContent }
|
||||
export { CSDNPlatform, fillCSDNContent, syncCSDNContent }
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// 51CTO 平台配置
|
||||
const CTO51Platform = {
|
||||
id: 'cto51',
|
||||
name: '51CTO',
|
||||
icon: 'https://blog.51cto.com/favicon.ico',
|
||||
url: 'https://blog.51cto.com',
|
||||
loginUrl: 'https://home.51cto.com/index/login',
|
||||
publishUrl: 'https://blog.51cto.com/blogger/publish',
|
||||
title: '51CTO',
|
||||
type: 'cto51',
|
||||
}
|
||||
|
||||
// 51CTO 内容填充函数
|
||||
async function fillCTO51Content(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
const contentToFill = markdown || body || ''
|
||||
|
||||
// 1. 填充标题
|
||||
// 51CTO 标题输入框通常是 input#title 或 placeholder="请输入标题"
|
||||
const titleInput = await waitFor('#title, input[placeholder*="标题"]')
|
||||
if (titleInput) {
|
||||
setInputValue(titleInput, title)
|
||||
console.log('[COSE] 51CTO 标题填充成功')
|
||||
}
|
||||
|
||||
// 2. 等待编辑器加载
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
|
||||
// 3. 填充内容
|
||||
// 51CTO 有 Markdown 编辑器和富文本编辑器,通常默认 Markdown
|
||||
// 尝试寻找 Markdown 编辑器的 textarea 或 CodeMirror
|
||||
const editor = document.querySelector('.editormd-markdown-textarea') || // Editor.md
|
||||
document.querySelector('#my-editormd-markdown-doc') || // 常见 ID
|
||||
document.querySelector('.CodeMirror textarea') || // CodeMirror 核心
|
||||
document.querySelector('textarea[name="content"]') // 通用 fallback
|
||||
|
||||
if (editor) {
|
||||
// 如果是 CodeMirror,通常需要操作 DOM 或使用 setValue
|
||||
// 尝试直接设置 value 并触发事件
|
||||
editor.focus()
|
||||
editor.value = contentToFill
|
||||
editor.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
editor.dispatchEvent(new Event('change', { bubbles: true }))
|
||||
|
||||
// 如果页面上有 editor.md 的全局实例,尝试调用
|
||||
// 这需要在 page context 执行,目前 fillContentOnPage 是在 Main world 执行的,所以可以访问 window
|
||||
if (window.editor) {
|
||||
try {
|
||||
window.editor.setMarkdown(contentToFill)
|
||||
console.log('[COSE] 51CTO 通过 window.editor 设置成功')
|
||||
return
|
||||
} catch (e) {
|
||||
console.log('[COSE] 51CTO window.editor 调用失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[COSE] 51CTO textarea 填充尝试完成')
|
||||
} else {
|
||||
console.log('[COSE] 51CTO 未找到编辑器元素,尝试降级 contenteditable')
|
||||
|
||||
// 可能是富文本模式的 contenteditable
|
||||
const contentEditable = document.querySelector('[contenteditable="true"]')
|
||||
if (contentEditable) {
|
||||
contentEditable.innerHTML = contentToFill.replace(/\n/g, '<br>')
|
||||
console.log('[COSE] 51CTO contenteditable 填充成功')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { CTO51Platform, fillCTO51Content }
|
||||
@@ -9,17 +9,7 @@ const DouyinPlatform = {
|
||||
type: 'douyin',
|
||||
}
|
||||
|
||||
// 抖音登录检测配置
|
||||
// 使用 API 检测登录状态
|
||||
const DouyinLoginConfig = {
|
||||
api: 'https://creator.douyin.com/web/api/media/user/info/',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.status_code === 0 && response?.user,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.user?.nickname || '',
|
||||
avatar: response?.user?.avatar_thumb?.url_list?.[0] || '',
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
// 导出
|
||||
export { DouyinPlatform, DouyinLoginConfig }
|
||||
export { DouyinPlatform }
|
||||
@@ -0,0 +1,9 @@
|
||||
// 电子发烧友平台配置
|
||||
|
||||
export const ElecfansPlatform = {
|
||||
id: 'elecfans',
|
||||
name: '电子发烧友',
|
||||
icon: 'https://www.elecfans.com/favicon.ico',
|
||||
publishUrl: 'https://www.elecfans.com/d/article/md/',
|
||||
loginUrl: 'https://bbs.elecfans.com/member.php?mod=logging&action=login',
|
||||
}
|
||||
@@ -9,13 +9,7 @@ const HuaweiDevPlatform = {
|
||||
type: 'huaweidev',
|
||||
}
|
||||
|
||||
// 华为开发者文章登录检测配置
|
||||
// 使用 cookie 检测登录状态
|
||||
const HuaweiDevLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://developer.huawei.com',
|
||||
cookieNames: ['developer_userinfo', 'developer_userdata'],
|
||||
}
|
||||
|
||||
|
||||
// 导出
|
||||
export { HuaweiDevPlatform, HuaweiDevLoginConfig }
|
||||
export { HuaweiDevPlatform }
|
||||
@@ -0,0 +1,114 @@
|
||||
// 平台配置汇总
|
||||
// 从 @cose/detection 导入登录检测配置
|
||||
import { LOGIN_CHECK_CONFIG } from '@cose/detection'
|
||||
|
||||
// 平台元数据和同步函数从各平台文件导入
|
||||
import { CSDNPlatform, syncCSDNContent } from './csdn.js'
|
||||
import { JuejinPlatform, syncJuejinContent } from './juejin.js'
|
||||
import { WechatPlatform, syncWechatContent } from './wechat.js'
|
||||
import { ZhihuPlatform, syncZhihuContent } from './zhihu.js'
|
||||
import { ToutiaoPlatform } from './toutiao.js'
|
||||
import { SegmentFaultPlatform } from './segmentfault.js'
|
||||
import { CnblogsPlatform } from './cnblogs.js'
|
||||
import { OSChinaPlatform } from './oschina.js'
|
||||
import { CTO51Platform } from './cto51.js'
|
||||
import { InfoQPlatform } from './infoq.js'
|
||||
import { JianshuPlatform } from './jianshu.js'
|
||||
import { BaijiahaoPlatform } from './baijiahao.js'
|
||||
import { WangyihaoPlatform } from './wangyihao.js'
|
||||
import { TencentCloudPlatform } from './tencentcloud.js'
|
||||
import { MediumPlatform } from './medium.js'
|
||||
import { SspaiPlatform } from './sspai.js'
|
||||
import { SohuPlatform } from './sohu.js'
|
||||
import { BilibiliPlatform } from './bilibili.js'
|
||||
import { WeiboPlatform } from './weibo.js'
|
||||
import { AliyunPlatform } from './aliyun.js'
|
||||
import { HuaweiDevPlatform } from './huaweidev.js'
|
||||
import { TwitterPlatform } from './twitter.js'
|
||||
import { QianfanPlatform } from './qianfan.js'
|
||||
import { AlipayOpenPlatform } from './alipayopen.js'
|
||||
import { ModelScopePlatform } from './modelscope.js'
|
||||
import { VolcenginePlatform } from './volcengine.js'
|
||||
import { DouyinPlatform } from './douyin.js'
|
||||
import { XiaohongshuPlatform } from './xiaohongshu.js'
|
||||
import { ElecfansPlatform } from './elecfans.js'
|
||||
|
||||
// 合并平台配置
|
||||
const PLATFORMS = [
|
||||
CSDNPlatform,
|
||||
JuejinPlatform,
|
||||
WechatPlatform,
|
||||
ZhihuPlatform,
|
||||
ToutiaoPlatform,
|
||||
SegmentFaultPlatform,
|
||||
CnblogsPlatform,
|
||||
OSChinaPlatform,
|
||||
CTO51Platform,
|
||||
InfoQPlatform,
|
||||
JianshuPlatform,
|
||||
BaijiahaoPlatform,
|
||||
WangyihaoPlatform,
|
||||
TencentCloudPlatform,
|
||||
MediumPlatform,
|
||||
SspaiPlatform,
|
||||
SohuPlatform,
|
||||
BilibiliPlatform,
|
||||
WeiboPlatform,
|
||||
AliyunPlatform,
|
||||
HuaweiDevPlatform,
|
||||
TwitterPlatform,
|
||||
QianfanPlatform,
|
||||
AlipayOpenPlatform,
|
||||
ModelScopePlatform,
|
||||
VolcenginePlatform,
|
||||
DouyinPlatform,
|
||||
XiaohongshuPlatform,
|
||||
ElecfansPlatform,
|
||||
]
|
||||
|
||||
// 根据 hostname 获取平台填充函数
|
||||
function getPlatformFiller(hostname) {
|
||||
if (hostname.includes('csdn.net')) return 'csdn'
|
||||
if (hostname.includes('juejin.cn')) return 'juejin'
|
||||
if (hostname.includes('mp.weixin.qq.com')) return 'wechat'
|
||||
if (hostname.includes('zhihu.com')) return 'zhihu'
|
||||
if (hostname.includes('toutiao.com')) return 'toutiao'
|
||||
if (hostname.includes('segmentfault.com')) return 'segmentfault'
|
||||
if (hostname.includes('cnblogs.com')) return 'cnblogs'
|
||||
if (hostname.includes('oschina.net')) return 'oschina'
|
||||
if (hostname.includes('51cto.com')) return 'cto51'
|
||||
if (hostname.includes('infoq.cn')) return 'infoq'
|
||||
if (hostname.includes('jianshu.com')) return 'jianshu'
|
||||
if (hostname.includes('baijiahao.baidu.com')) return 'baijiahao'
|
||||
if (hostname.includes('mp.163.com')) return 'wangyihao'
|
||||
if (hostname.includes('cloud.tencent.com')) return 'tencentcloud'
|
||||
if (hostname.includes('medium.com')) return 'medium'
|
||||
if (hostname.includes('sspai.com')) return 'sspai'
|
||||
if (hostname.includes('mp.sohu.com')) return 'sohu'
|
||||
if (hostname.includes('member.bilibili.com')) return 'bilibili'
|
||||
if (hostname.includes('card.weibo.com')) return 'weibo'
|
||||
if (hostname.includes('developer.aliyun.com')) return 'aliyun'
|
||||
if (hostname.includes('developer.huawei.com')) return 'huaweidev'
|
||||
if (hostname.includes('x.com') || hostname.includes('twitter.com')) return 'twitter'
|
||||
if (hostname.includes('qianfan.cloud.baidu.com')) return 'qianfan'
|
||||
if (hostname.includes('open.alipay.com')) return 'alipayopen'
|
||||
if (hostname.includes('modelscope.cn')) return 'modelscope'
|
||||
if (hostname.includes('developer.volcengine.com')) return 'volcengine'
|
||||
if (hostname.includes('creator.douyin.com')) return 'douyin'
|
||||
if (hostname.includes('creator.xiaohongshu.com')) return 'xiaohongshu'
|
||||
if (hostname.includes('elecfans.com')) return 'elecfans'
|
||||
return 'generic'
|
||||
}
|
||||
|
||||
// 同步处理器映射
|
||||
// 如果平台有自定义同步逻辑,在此注册处理器
|
||||
// 未注册的平台将使用 background.js 中的通用填充逻辑
|
||||
const SYNC_HANDLERS = {
|
||||
csdn: syncCSDNContent,
|
||||
juejin: syncJuejinContent,
|
||||
wechat: syncWechatContent,
|
||||
zhihu: syncZhihuContent,
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { PLATFORMS, LOGIN_CHECK_CONFIG, SYNC_HANDLERS, getPlatformFiller }
|
||||
@@ -11,24 +11,6 @@ const InfoQPlatform = {
|
||||
type: 'infoq',
|
||||
}
|
||||
|
||||
// InfoQ 登录检测配置 - 使用 API 获取用户信息
|
||||
const InfoQLoginConfig = {
|
||||
api: 'https://xie.infoq.cn/public/v1/user/get_user',
|
||||
method: 'POST',
|
||||
checkLogin: (data) => {
|
||||
// API 返回 code: 0 且有用户数据表示已登录
|
||||
return data && data.code === 0 && data.data && data.data.nickname
|
||||
},
|
||||
getUserInfo: (data) => {
|
||||
const user = data.data
|
||||
return {
|
||||
username: user.nickname || 'InfoQ用户',
|
||||
avatar: user.avatar || '',
|
||||
userId: user.uid || user.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// InfoQ 内容填充函数
|
||||
async function fillInfoQContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -71,4 +53,4 @@ async function fillInfoQContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { InfoQPlatform, InfoQLoginConfig, fillInfoQContent }
|
||||
export { InfoQPlatform, fillInfoQContent }
|
||||
@@ -9,17 +9,6 @@ const JianshuPlatform = {
|
||||
type: 'jianshu',
|
||||
}
|
||||
|
||||
// 简书登录检测配置
|
||||
const JianshuLoginConfig = {
|
||||
api: 'https://www.jianshu.com/author/current_user',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.nickname,
|
||||
avatar: response?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 简书内容填充函数
|
||||
async function fillJianshuContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -58,7 +47,7 @@ async function fillJianshuContent(content, waitFor, setInputValue) {
|
||||
|
||||
// 导出
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = { JianshuPlatform, JianshuLoginConfig, fillJianshuContent }
|
||||
module.exports = { JianshuPlatform, fillJianshuContent }
|
||||
}
|
||||
|
||||
export { JianshuPlatform, JianshuLoginConfig, fillJianshuContent }
|
||||
export { JianshuPlatform, fillJianshuContent }
|
||||
@@ -9,17 +9,6 @@ const JuejinPlatform = {
|
||||
type: 'juejin',
|
||||
}
|
||||
|
||||
// 掘金登录检测配置
|
||||
const JuejinLoginConfig = {
|
||||
api: 'https://api.juejin.cn/user_api/v1/user/get',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.err_no === 0 && response?.data?.user_id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.user_name,
|
||||
avatar: response?.data?.avatar_large,
|
||||
}),
|
||||
}
|
||||
|
||||
import { injectUtils } from './common.js'
|
||||
|
||||
// 掘金内容填充函数(在页面主世界中执行)
|
||||
@@ -97,5 +86,5 @@ async function syncJuejinContent(tab, content, helpers) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { JuejinPlatform, JuejinLoginConfig, fillJuejinContent, syncJuejinContent }
|
||||
export { JuejinPlatform, fillJuejinContent, syncJuejinContent }
|
||||
|
||||
@@ -11,13 +11,6 @@ const MediumPlatform = {
|
||||
|
||||
// Medium 登录检测配置
|
||||
// Medium 使用 sid 和 uid HttpOnly cookies 进行身份验证
|
||||
// 登录检测流程:先检查 cookies,然后访问 /me/stats 获取用户名
|
||||
const MediumLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://medium.com',
|
||||
cookieNames: ['sid', 'uid'],
|
||||
}
|
||||
|
||||
/**
|
||||
* Medium 内容填充函数
|
||||
* 流程:
|
||||
@@ -65,4 +58,4 @@ async function fillMediumContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { MediumPlatform, MediumLoginConfig, fillMediumContent }
|
||||
export { MediumPlatform, fillMediumContent }
|
||||
@@ -11,17 +11,7 @@ const ModelScopePlatform = {
|
||||
type: 'modelscope',
|
||||
}
|
||||
|
||||
// ModelScope 登录检测配置
|
||||
// 使用 API 检测登录状态
|
||||
const ModelScopeLoginConfig = {
|
||||
api: 'https://modelscope.cn/api/v1/users/login/info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.Success && response?.Data?.Name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.Data?.NickName || response?.Data?.Name,
|
||||
avatar: response?.Data?.Avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
// 导出
|
||||
export { ModelScopePlatform, ModelScopeLoginConfig }
|
||||
export { ModelScopePlatform }
|
||||
@@ -9,54 +9,6 @@ const OSChinaPlatform = {
|
||||
type: 'oschina',
|
||||
}
|
||||
|
||||
// OSChina 登录检测配置
|
||||
const OSChinaLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://www.oschina.net',
|
||||
cookieNames: ['oscid', 'osc_id'],
|
||||
fetchUserInfoFromPage: true,
|
||||
userInfoUrl: 'https://www.oschina.net/', // 使用首页获取更全的信息(包括个人主页链接)
|
||||
|
||||
// 解析用户信息逻辑 (供参考/未来集成)
|
||||
parseUserInfo: (html) => {
|
||||
let username = ''
|
||||
let avatar = ''
|
||||
let userId = null
|
||||
|
||||
// 提取用户 ID
|
||||
const uidMatch = html.match(/href=["']https:\/\/my\.oschina\.net\/u\/(\d+)["']/i) ||
|
||||
html.match(/space\.oschina\.net\/u\/(\d+)/i) ||
|
||||
html.match(/data-user-id=["'](\d+)["']/i)
|
||||
if (uidMatch) {
|
||||
userId = uidMatch[1]
|
||||
}
|
||||
|
||||
// 提取用户名
|
||||
const nameMatch = html.match(/<a[^>]*class="[^"]*user-name[^"]*"[^>]*>([^<]+)<\/a>/i) ||
|
||||
html.match(/<span[^>]*class="[^"]*nick[^"]*"[^>]*>([^<]+)<\/span>/i) ||
|
||||
html.match(/title="([^"]+)"[^>]*class="[^"]*avatar/i) ||
|
||||
html.match(/class="[^"]*avatar[^"]*"[^>]*title="([^"]+)"/i) ||
|
||||
html.match(/alt="([^"]+)"[^>]*class="[^"]*avatar/i)
|
||||
if (nameMatch) {
|
||||
username = nameMatch[1].trim()
|
||||
}
|
||||
|
||||
// 提取头像
|
||||
const avatarMatch = html.match(/<img[^>]*src="([^"]+)"[^>]*class="[^"]*avatar/i) ||
|
||||
html.match(/<img[^>]*class="[^"]*avatar[^"]*"[^>]*src="([^"]+)"/i)
|
||||
if (avatarMatch) {
|
||||
avatar = avatarMatch[1]
|
||||
}
|
||||
|
||||
// 只有 userId 的情况
|
||||
if (!username && userId) {
|
||||
username = userId
|
||||
}
|
||||
|
||||
return { username, avatar, userId }
|
||||
}
|
||||
}
|
||||
|
||||
// OSChina 内容填充函数
|
||||
async function fillOSChinaContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -108,4 +60,4 @@ async function fillOSChinaContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { OSChinaPlatform, OSChinaLoginConfig, fillOSChinaContent }
|
||||
export { OSChinaPlatform, fillOSChinaContent }
|
||||
@@ -11,13 +11,7 @@ const QianfanPlatform = {
|
||||
type: 'qianfan',
|
||||
}
|
||||
|
||||
// 百度千帆登录检测配置
|
||||
// 使用百度云的登录 cookie
|
||||
const QianfanLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://qianfan.cloud.baidu.com',
|
||||
cookieNames: ['BDUSS', 'BAIDUID'],
|
||||
}
|
||||
|
||||
|
||||
// 导出
|
||||
export { QianfanPlatform, QianfanLoginConfig }
|
||||
export { QianfanPlatform }
|
||||
@@ -9,15 +9,6 @@ const SegmentFaultPlatform = {
|
||||
type: 'segmentfault',
|
||||
}
|
||||
|
||||
// 思否登录检测配置
|
||||
const SegmentFaultLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://segmentfault.com',
|
||||
cookieNames: ['PHPSESSID'],
|
||||
fetchUserInfoFromPage: true,
|
||||
userInfoUrl: 'https://segmentfault.com/write',
|
||||
}
|
||||
|
||||
// 思否内容填充函数
|
||||
async function fillSegmentFaultContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -56,4 +47,4 @@ async function fillSegmentFaultContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { SegmentFaultPlatform, SegmentFaultLoginConfig, fillSegmentFaultContent }
|
||||
export { SegmentFaultPlatform, fillSegmentFaultContent }
|
||||
@@ -9,14 +9,6 @@ const SohuPlatform = {
|
||||
type: 'sohu',
|
||||
}
|
||||
|
||||
// 搜狐号登录检测配置
|
||||
const SohuLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://mp.sohu.com',
|
||||
cookieNames: ['ppinf'],
|
||||
// 搜狐号登录检测和内容填充在 background.js 中处理
|
||||
}
|
||||
|
||||
// 搜狐号内容填充函数
|
||||
// 注意:搜狐号由 syncToPlatform 单独处理,此函数作为备用
|
||||
async function fillSohuContent(content, waitFor) {
|
||||
@@ -24,4 +16,4 @@ async function fillSohuContent(content, waitFor) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { SohuPlatform, SohuLoginConfig, fillSohuContent }
|
||||
export { SohuPlatform, fillSohuContent }
|
||||
@@ -9,15 +9,6 @@ const SspaiPlatform = {
|
||||
type: 'sspai',
|
||||
}
|
||||
|
||||
// 少数派登录检测配置
|
||||
const SspaiLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://sspai.com',
|
||||
cookieNames: ['sspai_jwt_token'],
|
||||
// 少数派需要特殊处理,在 background.js 中单独实现
|
||||
// 使用 /api/v1/user/info/get API 获取用户信息
|
||||
}
|
||||
|
||||
// 少数派内容填充函数(备用,主要使用剪贴板方式)
|
||||
async function fillSspaiContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -63,4 +54,4 @@ async function fillSspaiContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { SspaiPlatform, SspaiLoginConfig, fillSspaiContent }
|
||||
export { SspaiPlatform, fillSspaiContent }
|
||||
@@ -9,13 +9,6 @@ const TencentCloudPlatform = {
|
||||
type: 'tencentcloud',
|
||||
}
|
||||
|
||||
// 腾讯云登录检测配置
|
||||
const TencentCloudLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://cloud.tencent.com',
|
||||
cookieNames: ['qcloud_uid', 'uin'],
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前是否需要切换到 MD 编辑器
|
||||
* 判断依据:页面中是否存在"切换 MD 编辑器"的按钮
|
||||
@@ -151,4 +144,4 @@ async function fillTencentCloudContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { TencentCloudPlatform, TencentCloudLoginConfig, fillTencentCloudContent, ensureMarkdownEditor, getCodeMirror }
|
||||
export { TencentCloudPlatform, fillTencentCloudContent, ensureMarkdownEditor, getCodeMirror }
|
||||
@@ -9,17 +9,6 @@ const ToutiaoPlatform = {
|
||||
type: 'toutiao',
|
||||
}
|
||||
|
||||
// 今日头条登录检测配置
|
||||
const ToutiaoLoginConfig = {
|
||||
api: 'https://mp.toutiao.com/mp/agw/media/get_media_info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.err_no === 0 && response?.data?.media?.display_name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.media?.display_name,
|
||||
avatar: response?.data?.media?.https_avatar_url,
|
||||
}),
|
||||
}
|
||||
|
||||
// 今日头条内容填充函数
|
||||
async function fillToutiaoContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -56,4 +45,4 @@ async function fillToutiaoContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { ToutiaoPlatform, ToutiaoLoginConfig, fillToutiaoContent }
|
||||
export { ToutiaoPlatform, fillToutiaoContent }
|
||||
@@ -11,13 +11,7 @@ const TwitterPlatform = {
|
||||
type: 'twitter',
|
||||
}
|
||||
|
||||
// Twitter Articles 登录检测配置
|
||||
// Twitter 使用 auth_token 和 ct0 cookies 进行身份验证
|
||||
const TwitterLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://x.com',
|
||||
cookieNames: ['auth_token', 'ct0'],
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自定义 Markdown 渲染器
|
||||
@@ -270,4 +264,4 @@ async function fillTwitterContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { TwitterPlatform, TwitterLoginConfig, fillTwitterContent, convertMarkdownToTwitterHtml }
|
||||
export { TwitterPlatform, fillTwitterContent, convertMarkdownToTwitterHtml }
|
||||
@@ -0,0 +1,15 @@
|
||||
// 火山引擎开发者社区平台配置
|
||||
const VolcenginePlatform = {
|
||||
id: 'volcengine',
|
||||
name: 'Volcengine',
|
||||
icon: 'https://lf1-cdn-tos.bytegoofy.com/goofy/tech-fe/fav.png',
|
||||
url: 'https://developer.volcengine.com/',
|
||||
publishUrl: 'https://developer.volcengine.com/articles/draft',
|
||||
title: '火山引擎开发者社区',
|
||||
type: 'volcengine',
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 导出
|
||||
export { VolcenginePlatform }
|
||||
@@ -9,15 +9,6 @@ const WangyihaoPlatform = {
|
||||
type: 'wangyihao',
|
||||
}
|
||||
|
||||
// 网易号登录检测配置
|
||||
const WangyihaoLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://mp.163.com',
|
||||
cookieNames: ['P_INFO', 'S_INFO', 'NTES_SESS'],
|
||||
// 网易号需要特殊处理,在 background.js 中单独实现
|
||||
// 使用 navinfo.do API 获取用户信息
|
||||
}
|
||||
|
||||
// 网易号内容填充函数(备用,主要使用剪贴板方式)
|
||||
async function fillWangyihaoContent(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
@@ -63,4 +54,4 @@ async function fillWangyihaoContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { WangyihaoPlatform, WangyihaoLoginConfig, fillWangyihaoContent }
|
||||
export { WangyihaoPlatform, fillWangyihaoContent }
|
||||
@@ -12,16 +12,6 @@ const WechatPlatform = {
|
||||
type: 'wechat',
|
||||
}
|
||||
|
||||
// 微信公众号登录检测配置
|
||||
const WechatLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://mp.weixin.qq.com',
|
||||
cookieNames: ['slave_user', 'slave_sid'],
|
||||
// 获取用户信息需要从页面抓取
|
||||
fetchUserInfoFromPage: true,
|
||||
userInfoUrl: 'https://mp.weixin.qq.com/',
|
||||
}
|
||||
|
||||
// 微信公众号内容填充函数(在页面主世界中执行)
|
||||
// 注意:需要先调用 injectUtils 注入 window.waitFor
|
||||
function fillWechatContent(title, htmlBody) {
|
||||
@@ -274,5 +264,5 @@ async function syncWechatContent(tab, content, helpers) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { WechatPlatform, WechatLoginConfig, fillWechatContent, syncWechatContent }
|
||||
export { WechatPlatform, fillWechatContent, syncWechatContent }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// 微博头条文章平台配置
|
||||
const WeiboPlatform = {
|
||||
id: 'weibo',
|
||||
name: 'Weibo',
|
||||
icon: 'https://weibo.com/favicon.ico',
|
||||
url: 'https://weibo.com',
|
||||
publishUrl: 'https://card.weibo.com/article/v5/editor#/draft',
|
||||
title: '微博头条',
|
||||
type: 'weibo',
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { WeiboPlatform }
|
||||
@@ -10,17 +10,6 @@ const XiaohongshuPlatform = {
|
||||
type: 'xiaohongshu',
|
||||
}
|
||||
|
||||
// 小红书登录检测配置 - 使用 API 检测
|
||||
const XiaohongshuLoginConfig = {
|
||||
api: 'https://creator.xiaohongshu.com/api/galaxy/user/info',
|
||||
method: 'GET',
|
||||
checkLogin: (data) => data?.success === true && data?.code === 0 && data?.data?.userId,
|
||||
getUserInfo: (data) => ({
|
||||
username: data?.data?.userName || data?.data?.redId || '',
|
||||
avatar: data?.data?.userAvatar || '',
|
||||
}),
|
||||
}
|
||||
|
||||
// 小红书内容填充函数(由 background.js 处理)
|
||||
// 使用剪贴板粘贴方式填充内容
|
||||
async function fillXiaohongshuContent(content, waitFor, setInputValue) {
|
||||
@@ -28,4 +17,4 @@ async function fillXiaohongshuContent(content, waitFor, setInputValue) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { XiaohongshuPlatform, XiaohongshuLoginConfig, fillXiaohongshuContent }
|
||||
export { XiaohongshuPlatform, fillXiaohongshuContent }
|
||||
@@ -9,17 +9,6 @@ const ZhihuPlatform = {
|
||||
type: 'zhihu',
|
||||
}
|
||||
|
||||
// 知乎登录检测配置
|
||||
const ZhihuLoginConfig = {
|
||||
api: 'https://www.zhihu.com/api/v4/me',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.name,
|
||||
avatar: response?.avatar_url,
|
||||
}),
|
||||
}
|
||||
|
||||
import { injectUtils } from './common.js'
|
||||
|
||||
// 知乎内容填充函数(在页面主世界中执行)
|
||||
@@ -156,4 +145,4 @@ async function syncZhihuContent(tab, content, helpers) {
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { ZhihuPlatform, ZhihuLoginConfig, fillZhihuContent, syncZhihuContent }
|
||||
export { ZhihuPlatform, fillZhihuContent, syncZhihuContent }
|
||||
@@ -0,0 +1,368 @@
|
||||
/**
|
||||
* @cose/detection - Platform login detection module
|
||||
*
|
||||
* This package provides login detection configurations for all supported platforms.
|
||||
* Each config includes:
|
||||
* - api: The API endpoint to check login status
|
||||
* - method: HTTP method (GET/POST)
|
||||
* - checkLogin: Function to determine if user is logged in from response
|
||||
* - getUserInfo: Function to extract username and avatar from response
|
||||
*/
|
||||
|
||||
// CSDN
|
||||
export const CSDNLoginConfig = {
|
||||
api: 'https://passport.csdn.net/v1/api/info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.data?.userId,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickName,
|
||||
avatar: response?.data?.avatarUrl,
|
||||
}),
|
||||
}
|
||||
|
||||
// 掘金
|
||||
export const JuejinLoginConfig = {
|
||||
api: 'https://api.juejin.cn/user_api/v1/user/get',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.err_no === 0 && response?.data?.user_id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.user_name,
|
||||
avatar: response?.data?.avatar_large,
|
||||
}),
|
||||
}
|
||||
|
||||
// 微信公众号
|
||||
export const WechatLoginConfig = {
|
||||
api: 'https://mp.weixin.qq.com/',
|
||||
method: 'GET',
|
||||
isHtml: true,
|
||||
checkLogin: (html) => !html.includes('请使用微信扫描'),
|
||||
getUserInfo: (html) => {
|
||||
const nickMatch = html.match(/nick_name\s*:\s*["']([^"']+)["']/)
|
||||
const avatarMatch = html.match(/head_img\s*:\s*["']([^"']+)["']/)
|
||||
return {
|
||||
username: nickMatch?.[1]?.replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))),
|
||||
avatar: avatarMatch?.[1],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// 知乎
|
||||
export const ZhihuLoginConfig = {
|
||||
api: 'https://www.zhihu.com/api/v4/me',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.name,
|
||||
avatar: response?.avatar_url,
|
||||
}),
|
||||
}
|
||||
|
||||
// 头条号
|
||||
export const ToutiaoLoginConfig = {
|
||||
api: 'https://mp.toutiao.com/auth/article/is_login/',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.data?.is_login,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.name,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// SegmentFault
|
||||
export const SegmentFaultLoginConfig = {
|
||||
api: 'https://segmentfault.com/gateway/user/me',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.status === 0 && response?.data?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.name,
|
||||
avatar: response?.data?.avatar_url,
|
||||
}),
|
||||
}
|
||||
|
||||
// 博客园
|
||||
export const CnblogsLoginConfig = {
|
||||
api: 'https://www.cnblogs.com/api/users/current',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.UserId,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.DisplayName,
|
||||
avatar: response?.Avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 开源中国
|
||||
export const OSChinaLoginConfig = {
|
||||
api: 'https://www.oschina.net/action/user/detail?format=json',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.name,
|
||||
avatar: response?.portrait,
|
||||
}),
|
||||
}
|
||||
|
||||
// 51CTO
|
||||
export const CTO51LoginConfig = {
|
||||
api: 'https://home.51cto.com/api/user/info/getUserBasicInfo',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 200 && response?.data?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.headpic,
|
||||
}),
|
||||
}
|
||||
|
||||
// InfoQ
|
||||
export const InfoQLoginConfig = {
|
||||
api: 'https://www.infoq.cn/public/v1/my/menu',
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
checkLogin: (response) => response?.code === 0 && response?.data?.username,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 简书
|
||||
export const JianshuLoginConfig = {
|
||||
api: 'https://www.jianshu.com/settings/basic',
|
||||
method: 'GET',
|
||||
isHtml: true,
|
||||
checkLogin: (html) => !html.includes('登录'),
|
||||
getUserInfo: () => ({ username: null, avatar: null }),
|
||||
}
|
||||
|
||||
// 百家号
|
||||
export const BaijiahaoLoginConfig = {
|
||||
api: 'https://baijiahao.baidu.com/pcui/profile/headerinfo',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.errno === 0 && response?.data?.name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.name,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 网易号
|
||||
export const WangyihaoLoginConfig = {
|
||||
api: 'https://mp.163.com/api/account/info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 1000 && response?.data?.nickname,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.headImg,
|
||||
}),
|
||||
}
|
||||
|
||||
// 腾讯云开发者社区
|
||||
export const TencentCloudLoginConfig = {
|
||||
api: 'https://cloud.tencent.com/developer/api/user/session',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 0 && response?.data?.uin,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// Medium
|
||||
export const MediumLoginConfig = {
|
||||
api: 'https://medium.com/me/stats?format=json',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.success,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.payload?.user?.name,
|
||||
avatar: response?.payload?.user?.imageId ? `https://miro.medium.com/v2/resize:fill:64:64/${response.payload.user.imageId}` : null,
|
||||
}),
|
||||
}
|
||||
|
||||
// 少数派
|
||||
export const SspaiLoginConfig = {
|
||||
api: 'https://sspai.com/api/v1/user/info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.error === 0 && response?.data?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 搜狐号
|
||||
export const SohuLoginConfig = {
|
||||
api: 'https://mp.sohu.com/main/home/mp/getLoginUserInfo',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 0 && response?.data?.nick,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nick,
|
||||
avatar: response?.data?.logoUrl,
|
||||
}),
|
||||
}
|
||||
|
||||
// B站
|
||||
export const BilibiliLoginConfig = {
|
||||
api: 'https://member.bilibili.com/x/web/kv/list?type=5',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 0,
|
||||
getUserInfo: () => ({ username: null, avatar: null }),
|
||||
}
|
||||
|
||||
// 微博
|
||||
export const WeiboLoginConfig = {
|
||||
api: 'https://card.weibo.com/article/v3/aj/editor/draft/list?page=1&pagesize=1',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 100000,
|
||||
getUserInfo: () => ({ username: null, avatar: null }),
|
||||
}
|
||||
|
||||
// 阿里云开发者社区
|
||||
export const AliyunLoginConfig = {
|
||||
api: 'https://developer.aliyun.com/developer/api/my/user/getUser',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.success && response?.data?.accountId,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nick,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 华为云开发者博客
|
||||
export const HuaweiCloudLoginConfig = {
|
||||
api: 'https://bbs.huaweicloud.com/uucenter/user/getUserInfoByUserNos',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.result === 'success',
|
||||
getUserInfo: () => ({ username: null, avatar: null }),
|
||||
}
|
||||
|
||||
// 华为开发者联盟
|
||||
export const HuaweiDevLoginConfig = {
|
||||
api: 'https://developer.huawei.com/consumer/cn/doc/distribution/dev-web/overview-web-0000001049579028',
|
||||
method: 'GET',
|
||||
isHtml: true,
|
||||
checkLogin: (html) => html.includes('logout'),
|
||||
getUserInfo: () => ({ username: null, avatar: null }),
|
||||
}
|
||||
|
||||
// Twitter/X
|
||||
export const TwitterLoginConfig = {
|
||||
api: 'https://api.x.com/1.1/account/settings.json',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.screen_name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.screen_name,
|
||||
avatar: null,
|
||||
}),
|
||||
}
|
||||
|
||||
// 百度千帆
|
||||
export const QianfanLoginConfig = {
|
||||
api: 'https://qianfan.cloud.baidu.com/api/developer/common/userInfo',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 200 && response?.data?.userName,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.userName,
|
||||
avatar: null,
|
||||
}),
|
||||
}
|
||||
|
||||
// 支付宝开放平台
|
||||
export const AlipayOpenLoginConfig = {
|
||||
api: 'https://open.alipay.com/api/user/getUserInfo',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.data?.loginId,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.loginId,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// ModelScope
|
||||
export const ModelScopeLoginConfig = {
|
||||
api: 'https://modelscope.cn/api/v1/user/current',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.Success && response?.Data?.Name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.Data?.Name,
|
||||
avatar: response?.Data?.Avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 火山引擎
|
||||
export const VolcengineLoginConfig = {
|
||||
api: 'https://developer.volcengine.com/api/console/user/info',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.code === 0 && response?.data?.display_name,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.display_name,
|
||||
avatar: null,
|
||||
}),
|
||||
}
|
||||
|
||||
// 抖音
|
||||
export const DouyinLoginConfig = {
|
||||
api: 'https://creator.douyin.com/web/api/media/user/info/',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.status_code === 0 && response?.user_info?.uid,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.user_info?.nickname,
|
||||
avatar: response?.user_info?.avatar_url,
|
||||
}),
|
||||
}
|
||||
|
||||
// 小红书
|
||||
export const XiaohongshuLoginConfig = {
|
||||
api: 'https://creator.xiaohongshu.com/api/galaxy/user/index',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.success && response?.data?.id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.nickname,
|
||||
avatar: response?.data?.portrait,
|
||||
}),
|
||||
}
|
||||
|
||||
// 电子发烧友
|
||||
export const ElecfansLoginConfig = {
|
||||
api: 'https://bbs.elecfans.com/api/login/check',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.status === 1,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.username,
|
||||
avatar: response?.data?.avatar,
|
||||
}),
|
||||
}
|
||||
|
||||
// 统一的 LOGIN_CHECK_CONFIG 对象(按平台 ID 索引)
|
||||
export const LOGIN_CHECK_CONFIG = {
|
||||
csdn: CSDNLoginConfig,
|
||||
juejin: JuejinLoginConfig,
|
||||
wechat: WechatLoginConfig,
|
||||
zhihu: ZhihuLoginConfig,
|
||||
toutiao: ToutiaoLoginConfig,
|
||||
segmentfault: SegmentFaultLoginConfig,
|
||||
cnblogs: CnblogsLoginConfig,
|
||||
oschina: OSChinaLoginConfig,
|
||||
cto51: CTO51LoginConfig,
|
||||
infoq: InfoQLoginConfig,
|
||||
jianshu: JianshuLoginConfig,
|
||||
baijiahao: BaijiahaoLoginConfig,
|
||||
wangyihao: WangyihaoLoginConfig,
|
||||
tencentcloud: TencentCloudLoginConfig,
|
||||
medium: MediumLoginConfig,
|
||||
sspai: SspaiLoginConfig,
|
||||
sohu: SohuLoginConfig,
|
||||
bilibili: BilibiliLoginConfig,
|
||||
weibo: WeiboLoginConfig,
|
||||
aliyun: AliyunLoginConfig,
|
||||
huaweicloud: HuaweiCloudLoginConfig,
|
||||
huaweidev: HuaweiDevLoginConfig,
|
||||
twitter: TwitterLoginConfig,
|
||||
qianfan: QianfanLoginConfig,
|
||||
alipayopen: AlipayOpenLoginConfig,
|
||||
modelscope: ModelScopeLoginConfig,
|
||||
volcengine: VolcengineLoginConfig,
|
||||
douyin: DouyinLoginConfig,
|
||||
xiaohongshu: XiaohongshuLoginConfig,
|
||||
elecfans: ElecfansLoginConfig,
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@cose/detection",
|
||||
"version": "1.0.0",
|
||||
"description": "Platform login detection for COSE",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./platforms/*": "./src/platforms/*.js"
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,28 @@ importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
typescript:
|
||||
specifier: ^5.0.0
|
||||
version: 5.9.3
|
||||
|
||||
apps/extension:
|
||||
dependencies:
|
||||
'@cose/core':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
devDependencies:
|
||||
cac:
|
||||
specifier: ^6.7.14
|
||||
version: 6.7.14
|
||||
execa:
|
||||
specifier: ^9.6.1
|
||||
version: 9.6.1
|
||||
rimraf:
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.10
|
||||
tsx:
|
||||
specifier: ^4.21.0
|
||||
version: 4.21.0
|
||||
vite:
|
||||
specifier: ^5.0.12
|
||||
version: 5.4.21(@types/node@25.2.0)
|
||||
@@ -20,6 +39,17 @@ importers:
|
||||
web-ext:
|
||||
specifier: ^7.11.0
|
||||
version: 7.12.0
|
||||
ws:
|
||||
specifier: ^8.19.0
|
||||
version: 8.19.0
|
||||
|
||||
packages/core:
|
||||
dependencies:
|
||||
'@cose/detection':
|
||||
specifier: workspace:*
|
||||
version: link:../detection
|
||||
|
||||
packages/detection: {}
|
||||
|
||||
packages:
|
||||
|
||||
@@ -54,138 +84,294 @@ packages:
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.2':
|
||||
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.21.5':
|
||||
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.21.5':
|
||||
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.27.2':
|
||||
resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.21.5':
|
||||
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.27.2':
|
||||
resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.21.5':
|
||||
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.21.5':
|
||||
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.27.2':
|
||||
resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.21.5':
|
||||
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.21.5':
|
||||
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.2':
|
||||
resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.21.5':
|
||||
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.21.5':
|
||||
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.27.2':
|
||||
resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.21.5':
|
||||
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.27.2':
|
||||
resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.21.5':
|
||||
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.27.2':
|
||||
resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.21.5':
|
||||
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.2':
|
||||
resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.21.5':
|
||||
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.2':
|
||||
resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.21.5':
|
||||
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.2':
|
||||
resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.21.5':
|
||||
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.27.2':
|
||||
resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.21.5':
|
||||
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.27.2':
|
||||
resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.21.5':
|
||||
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.2':
|
||||
resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.21.5':
|
||||
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.2':
|
||||
resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.21.5':
|
||||
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.27.2':
|
||||
resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.21.5':
|
||||
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.27.2':
|
||||
resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.21.5':
|
||||
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.27.2':
|
||||
resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.21.5':
|
||||
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.27.2':
|
||||
resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.1':
|
||||
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -381,10 +567,17 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1':
|
||||
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
|
||||
|
||||
'@sindresorhus/is@5.6.0':
|
||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
'@sindresorhus/merge-streams@4.0.0':
|
||||
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@szmarczak/http-timer@5.0.1':
|
||||
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
|
||||
engines: {node: '>=14.16'}
|
||||
@@ -574,6 +767,10 @@ packages:
|
||||
engines: {'0': node >=0.10.0}
|
||||
hasBin: true
|
||||
|
||||
cac@6.7.14:
|
||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
cacheable-lookup@7.0.0:
|
||||
resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==}
|
||||
engines: {node: '>=14.16'}
|
||||
@@ -852,6 +1049,11 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.27.2:
|
||||
resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -932,6 +1134,10 @@ packages:
|
||||
resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
execa@9.6.1:
|
||||
resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==}
|
||||
engines: {node: ^18.19.0 || >=20.5.0}
|
||||
|
||||
extend@3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
|
||||
@@ -969,6 +1175,10 @@ packages:
|
||||
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||
engines: {node: ^12.20 || >= 14.13}
|
||||
|
||||
figures@6.1.0:
|
||||
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
@@ -1051,6 +1261,13 @@ packages:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
get-stream@9.0.1:
|
||||
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-tsconfig@4.13.1:
|
||||
resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==}
|
||||
|
||||
getpass@0.1.7:
|
||||
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
|
||||
|
||||
@@ -1068,19 +1285,21 @@ packages:
|
||||
glob@10.4.1:
|
||||
resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==}
|
||||
engines: {node: '>=16 || 14 >=14.18'}
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
hasBin: true
|
||||
|
||||
glob@10.5.0:
|
||||
resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
hasBin: true
|
||||
|
||||
glob@6.0.4:
|
||||
resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
global-dirs@3.0.1:
|
||||
resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
|
||||
@@ -1148,6 +1367,10 @@ packages:
|
||||
resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
|
||||
engines: {node: '>=8.12.0'}
|
||||
|
||||
human-signals@8.0.1:
|
||||
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
|
||||
@@ -1248,6 +1471,10 @@ packages:
|
||||
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-plain-obj@4.1.0:
|
||||
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-relative@0.1.3:
|
||||
resolution: {integrity: sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1256,9 +1483,17 @@ packages:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-stream@4.0.1:
|
||||
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-typedarray@1.0.0:
|
||||
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
|
||||
|
||||
is-unicode-supported@2.1.0:
|
||||
resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-utf8@0.2.1:
|
||||
resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==}
|
||||
|
||||
@@ -1518,6 +1753,10 @@ packages:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
@@ -1593,6 +1832,10 @@ packages:
|
||||
resolution: {integrity: sha512-SA5aMiaIjXkAiBrW/yPgLgQAQg42f7K3ACO+2l/zOvtQBwX58DMUsFJXelW2fx3yMBmWOVkR6j1MGsdSbCA4UA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
parse-ms@4.0.0:
|
||||
resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
parse5-htmlparser2-tree-adapter@7.1.0:
|
||||
resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
|
||||
|
||||
@@ -1611,6 +1854,10 @@ packages:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-key@4.0.0:
|
||||
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
path-scurry@1.11.1:
|
||||
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
|
||||
engines: {node: '>=16 || 14 >=14.18'}
|
||||
@@ -1646,6 +1893,10 @@ packages:
|
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
pretty-ms@9.3.0:
|
||||
resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
process-nextick-args@2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
|
||||
@@ -1749,6 +2000,9 @@ packages:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
resolve-pkg-maps@1.0.0:
|
||||
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
||||
|
||||
responselike@3.0.0:
|
||||
resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==}
|
||||
engines: {node: '>=14.16'}
|
||||
@@ -1919,6 +2173,10 @@ packages:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
strip-final-newline@4.0.0:
|
||||
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
strip-json-comments@2.0.1:
|
||||
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1971,6 +2229,11 @@ packages:
|
||||
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
tsx@4.21.0:
|
||||
resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
tunnel-agent@0.6.0:
|
||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||
|
||||
@@ -2003,9 +2266,18 @@ packages:
|
||||
typedarray@0.0.6:
|
||||
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
|
||||
|
||||
typescript@5.9.3:
|
||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
unicorn-magic@0.3.0:
|
||||
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
unique-string@3.0.0:
|
||||
resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2147,6 +2419,18 @@ packages:
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
ws@8.19.0:
|
||||
resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
xdg-basedir@5.1.0:
|
||||
resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2182,6 +2466,10 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yoctocolors@2.1.2:
|
||||
resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
zip-dir@2.0.0:
|
||||
resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==}
|
||||
|
||||
@@ -2218,72 +2506,150 @@ snapshots:
|
||||
'@esbuild/aix-ppc64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.21.5':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.27.2':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@8.57.0)':
|
||||
dependencies:
|
||||
eslint: 8.57.0
|
||||
@@ -2434,8 +2800,12 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.57.1':
|
||||
optional: true
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1': {}
|
||||
|
||||
'@sindresorhus/is@5.6.0': {}
|
||||
|
||||
'@sindresorhus/merge-streams@4.0.0': {}
|
||||
|
||||
'@szmarczak/http-timer@5.0.1':
|
||||
dependencies:
|
||||
defer-to-connect: 2.0.1
|
||||
@@ -2640,6 +3010,8 @@ snapshots:
|
||||
mv: 2.1.1
|
||||
safe-json-stringify: 1.2.0
|
||||
|
||||
cac@6.7.14: {}
|
||||
|
||||
cacheable-lookup@7.0.0: {}
|
||||
|
||||
cacheable-request@10.2.14:
|
||||
@@ -2936,6 +3308,35 @@ snapshots:
|
||||
'@esbuild/win32-ia32': 0.21.5
|
||||
'@esbuild/win32-x64': 0.21.5
|
||||
|
||||
esbuild@0.27.2:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.27.2
|
||||
'@esbuild/android-arm': 0.27.2
|
||||
'@esbuild/android-arm64': 0.27.2
|
||||
'@esbuild/android-x64': 0.27.2
|
||||
'@esbuild/darwin-arm64': 0.27.2
|
||||
'@esbuild/darwin-x64': 0.27.2
|
||||
'@esbuild/freebsd-arm64': 0.27.2
|
||||
'@esbuild/freebsd-x64': 0.27.2
|
||||
'@esbuild/linux-arm': 0.27.2
|
||||
'@esbuild/linux-arm64': 0.27.2
|
||||
'@esbuild/linux-ia32': 0.27.2
|
||||
'@esbuild/linux-loong64': 0.27.2
|
||||
'@esbuild/linux-mips64el': 0.27.2
|
||||
'@esbuild/linux-ppc64': 0.27.2
|
||||
'@esbuild/linux-riscv64': 0.27.2
|
||||
'@esbuild/linux-s390x': 0.27.2
|
||||
'@esbuild/linux-x64': 0.27.2
|
||||
'@esbuild/netbsd-arm64': 0.27.2
|
||||
'@esbuild/netbsd-x64': 0.27.2
|
||||
'@esbuild/openbsd-arm64': 0.27.2
|
||||
'@esbuild/openbsd-x64': 0.27.2
|
||||
'@esbuild/openharmony-arm64': 0.27.2
|
||||
'@esbuild/sunos-x64': 0.27.2
|
||||
'@esbuild/win32-arm64': 0.27.2
|
||||
'@esbuild/win32-ia32': 0.27.2
|
||||
'@esbuild/win32-x64': 0.27.2
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-goat@4.0.0: {}
|
||||
@@ -3042,6 +3443,21 @@ snapshots:
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
|
||||
execa@9.6.1:
|
||||
dependencies:
|
||||
'@sindresorhus/merge-streams': 4.0.0
|
||||
cross-spawn: 7.0.6
|
||||
figures: 6.1.0
|
||||
get-stream: 9.0.1
|
||||
human-signals: 8.0.1
|
||||
is-plain-obj: 4.1.0
|
||||
is-stream: 4.0.1
|
||||
npm-run-path: 6.0.0
|
||||
pretty-ms: 9.3.0
|
||||
signal-exit: 4.1.0
|
||||
strip-final-newline: 4.0.0
|
||||
yoctocolors: 2.1.2
|
||||
|
||||
extend@3.0.2: {}
|
||||
|
||||
extsprintf@1.3.0: {}
|
||||
@@ -3077,6 +3493,10 @@ snapshots:
|
||||
node-domexception: 1.0.0
|
||||
web-streams-polyfill: 3.3.3
|
||||
|
||||
figures@6.1.0:
|
||||
dependencies:
|
||||
is-unicode-supported: 2.1.0
|
||||
|
||||
file-entry-cache@6.0.1:
|
||||
dependencies:
|
||||
flat-cache: 3.2.0
|
||||
@@ -3168,6 +3588,15 @@ snapshots:
|
||||
|
||||
get-stream@6.0.1: {}
|
||||
|
||||
get-stream@9.0.1:
|
||||
dependencies:
|
||||
'@sec-ant/readable-stream': 0.4.1
|
||||
is-stream: 4.0.1
|
||||
|
||||
get-tsconfig@4.13.1:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
||||
getpass@0.1.7:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
@@ -3284,6 +3713,8 @@ snapshots:
|
||||
|
||||
human-signals@1.1.1: {}
|
||||
|
||||
human-signals@8.0.1: {}
|
||||
|
||||
ieee754@1.2.1: {}
|
||||
|
||||
ignore@5.3.2: {}
|
||||
@@ -3355,12 +3786,18 @@ snapshots:
|
||||
|
||||
is-path-inside@3.0.3: {}
|
||||
|
||||
is-plain-obj@4.1.0: {}
|
||||
|
||||
is-relative@0.1.3: {}
|
||||
|
||||
is-stream@2.0.1: {}
|
||||
|
||||
is-stream@4.0.1: {}
|
||||
|
||||
is-typedarray@1.0.0: {}
|
||||
|
||||
is-unicode-supported@2.1.0: {}
|
||||
|
||||
is-utf8@0.2.1: {}
|
||||
|
||||
is-wsl@2.2.0:
|
||||
@@ -3611,6 +4048,11 @@ snapshots:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
unicorn-magic: 0.3.0
|
||||
|
||||
nth-check@2.1.1:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
@@ -3688,6 +4130,8 @@ snapshots:
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 2.0.4
|
||||
|
||||
parse-ms@4.0.0: {}
|
||||
|
||||
parse5-htmlparser2-tree-adapter@7.1.0:
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
@@ -3703,6 +4147,8 @@ snapshots:
|
||||
|
||||
path-key@3.1.1: {}
|
||||
|
||||
path-key@4.0.0: {}
|
||||
|
||||
path-scurry@1.11.1:
|
||||
dependencies:
|
||||
lru-cache: 10.4.3
|
||||
@@ -3745,6 +4191,10 @@ snapshots:
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
|
||||
pretty-ms@9.3.0:
|
||||
dependencies:
|
||||
parse-ms: 4.0.0
|
||||
|
||||
process-nextick-args@2.0.1: {}
|
||||
|
||||
process-warning@3.0.0: {}
|
||||
@@ -3861,6 +4311,8 @@ snapshots:
|
||||
|
||||
resolve-from@4.0.0: {}
|
||||
|
||||
resolve-pkg-maps@1.0.0: {}
|
||||
|
||||
responselike@3.0.0:
|
||||
dependencies:
|
||||
lowercase-keys: 3.0.0
|
||||
@@ -4057,6 +4509,8 @@ snapshots:
|
||||
|
||||
strip-final-newline@2.0.0: {}
|
||||
|
||||
strip-final-newline@4.0.0: {}
|
||||
|
||||
strip-json-comments@2.0.1: {}
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
@@ -4102,6 +4556,13 @@ snapshots:
|
||||
psl: 1.15.0
|
||||
punycode: 2.3.1
|
||||
|
||||
tsx@4.21.0:
|
||||
dependencies:
|
||||
esbuild: 0.27.2
|
||||
get-tsconfig: 4.13.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
tunnel-agent@0.6.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
@@ -4126,8 +4587,12 @@ snapshots:
|
||||
|
||||
typedarray@0.0.6: {}
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
unicorn-magic@0.3.0: {}
|
||||
|
||||
unique-string@3.0.0:
|
||||
dependencies:
|
||||
crypto-random-string: 4.0.0
|
||||
@@ -4283,6 +4748,8 @@ snapshots:
|
||||
|
||||
ws@8.13.0: {}
|
||||
|
||||
ws@8.19.0: {}
|
||||
|
||||
xdg-basedir@5.1.0: {}
|
||||
|
||||
xml2js@0.5.0:
|
||||
@@ -4323,6 +4790,8 @@ snapshots:
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
yoctocolors@2.1.2: {}
|
||||
|
||||
zip-dir@2.0.0:
|
||||
dependencies:
|
||||
async: 3.2.6
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
packages:
|
||||
- '.'
|
||||
- 'apps/*'
|
||||
- 'packages/*'
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
// 51CTO 平台配置
|
||||
const CTO51Platform = {
|
||||
id: 'cto51',
|
||||
name: '51CTO',
|
||||
icon: 'https://blog.51cto.com/favicon.ico',
|
||||
url: 'https://blog.51cto.com',
|
||||
loginUrl: 'https://home.51cto.com/index/login',
|
||||
publishUrl: 'https://blog.51cto.com/blogger/publish',
|
||||
title: '51CTO',
|
||||
type: 'cto51',
|
||||
}
|
||||
|
||||
// 51CTO 登录检测配置
|
||||
const CTO51LoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://blog.51cto.com',
|
||||
cookieNames: ['www51cto', 'identity'], // 移除 uid 避免误判
|
||||
fetchUserInfoFromPage: true,
|
||||
userInfoUrl: 'https://blog.51cto.com/',
|
||||
|
||||
// 解析用户信息逻辑
|
||||
parseUserInfo: (html) => {
|
||||
let username = ''
|
||||
let avatar = ''
|
||||
let loggedIn = true
|
||||
|
||||
// 1. 优先检测明确的未登录信号
|
||||
// 检测全局变量 isLogin = 0 (源码中通常是 var isLogin = 0; 或 window.isLogin = 0;)
|
||||
if (html.match(/var\s+isLogin\s*=\s*0/) || html.match(/window\.isLogin\s*=\s*0/)) {
|
||||
return { loggedIn: false }
|
||||
}
|
||||
|
||||
// 检测顶部导航栏的 "登录" 链接
|
||||
// 匹配 <span class="fl">登录</span> 或单纯的 >登录<
|
||||
if (html.match(/<span[^>]*class=["'][^"']*fl[^"']*["'][^>]*>\s*登录\s*<\/span>/) ||
|
||||
html.match(/<a[^>]*href=["'][^"']*home\.51cto\.com\/index[^"']*["'][^>]*>[\s\S]*?登录[\s\S]*?<\/a>/)) {
|
||||
return { loggedIn: false }
|
||||
}
|
||||
|
||||
// 2. 尝试提取用户信息 (仅在未判定为未登录时执行)
|
||||
|
||||
// 尝试提取用户名 (Header 区域 - 针对已登录用户)
|
||||
// 登录后的下拉菜单通常包含 .user-base 或 .user-name
|
||||
const nameMatch = html.match(/class=["']user-base["'][^>]*>[\s\S]*?<span>\s*([^<]+?)\s*<\/span>/i) ||
|
||||
html.match(/class=["']user-name["'][^>]*>([^<]+)</i)
|
||||
|
||||
// 3. 尝试提取用户 ID
|
||||
// 注意:页面内容中(如文章列表)会有大量 data-uid,必须确保是 header/user 区域的
|
||||
// 登录后通常 header 区域的头像或链接会包含当前用户 ID
|
||||
// 限制只在 nameMatch 成功(即找到用户名)的情况下,或者特定结构的 header 中查找 ID
|
||||
let userId = null
|
||||
if (nameMatch) {
|
||||
const uidMatch = html.match(/data-uid=["'](\d+)["']/i) // 此时可以稍微放宽,因为已经匹配到用户名区域
|
||||
userId = uidMatch ? uidMatch[1] : null
|
||||
} else {
|
||||
// 如果没找到明确的 header 用户名,但找到了 explicit 的 header 用户结构
|
||||
const headerUserMatch = html.match(/class=["']header-user["'][\s\S]*?data-uid=["'](\d+)["']/i)
|
||||
if (headerUserMatch) {
|
||||
userId = headerUserMatch[1]
|
||||
}
|
||||
}
|
||||
|
||||
if (nameMatch) {
|
||||
username = nameMatch[1].trim()
|
||||
} else if (userId) {
|
||||
username = `User_${userId}`
|
||||
}
|
||||
|
||||
// 4. 双重确认
|
||||
// 如果最终没找到用户名也没找到 ID,那肯定是未登录
|
||||
if (!username && !userId) {
|
||||
return { loggedIn: false }
|
||||
}
|
||||
|
||||
// 提取头像
|
||||
const avatarMatch = html.match(/class=["']user-base["'][^>]*>[\s\S]*?<img[^>]+src=["']([^"']+)["']/i) ||
|
||||
html.match(/class=["']nav-insite-bar-avator["'][^>]*src=["']([^"']+)["']/i)
|
||||
|
||||
if (avatarMatch) {
|
||||
avatar = avatarMatch[1]
|
||||
if (avatar.startsWith('//')) {
|
||||
avatar = 'https:' + avatar
|
||||
}
|
||||
}
|
||||
|
||||
return { username, avatar, loggedIn }
|
||||
}
|
||||
}
|
||||
|
||||
// 51CTO 内容填充函数
|
||||
async function fillCTO51Content(content, waitFor, setInputValue) {
|
||||
const { title, body, markdown } = content
|
||||
const contentToFill = markdown || body || ''
|
||||
|
||||
// 1. 填充标题
|
||||
// 51CTO 标题输入框通常是 input#title 或 placeholder="请输入标题"
|
||||
const titleInput = await waitFor('#title, input[placeholder*="标题"]')
|
||||
if (titleInput) {
|
||||
setInputValue(titleInput, title)
|
||||
console.log('[COSE] 51CTO 标题填充成功')
|
||||
}
|
||||
|
||||
// 2. 等待编辑器加载
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
|
||||
// 3. 填充内容
|
||||
// 51CTO 有 Markdown 编辑器和富文本编辑器,通常默认 Markdown
|
||||
// 尝试寻找 Markdown 编辑器的 textarea 或 CodeMirror
|
||||
const editor = document.querySelector('.editormd-markdown-textarea') || // Editor.md
|
||||
document.querySelector('#my-editormd-markdown-doc') || // 常见 ID
|
||||
document.querySelector('.CodeMirror textarea') || // CodeMirror 核心
|
||||
document.querySelector('textarea[name="content"]') // 通用 fallback
|
||||
|
||||
if (editor) {
|
||||
// 如果是 CodeMirror,通常需要操作 DOM 或使用 setValue
|
||||
// 尝试直接设置 value 并触发事件
|
||||
editor.focus()
|
||||
editor.value = contentToFill
|
||||
editor.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
editor.dispatchEvent(new Event('change', { bubbles: true }))
|
||||
|
||||
// 如果页面上有 editor.md 的全局实例,尝试调用
|
||||
// 这需要在 page context 执行,目前 fillContentOnPage 是在 Main world 执行的,所以可以访问 window
|
||||
if (window.editor) {
|
||||
try {
|
||||
window.editor.setMarkdown(contentToFill)
|
||||
console.log('[COSE] 51CTO 通过 window.editor 设置成功')
|
||||
return
|
||||
} catch (e) {
|
||||
console.log('[COSE] 51CTO window.editor 调用失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[COSE] 51CTO textarea 填充尝试完成')
|
||||
} else {
|
||||
console.log('[COSE] 51CTO 未找到编辑器元素,尝试降级 contenteditable')
|
||||
|
||||
// 可能是富文本模式的 contenteditable
|
||||
const contentEditable = document.querySelector('[contenteditable="true"]')
|
||||
if (contentEditable) {
|
||||
contentEditable.innerHTML = contentToFill.replace(/\n/g, '<br>')
|
||||
console.log('[COSE] 51CTO contenteditable 填充成功')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { CTO51Platform, CTO51LoginConfig, fillCTO51Content }
|
||||
@@ -1,25 +0,0 @@
|
||||
// 电子发烧友平台配置
|
||||
|
||||
export const ElecfansPlatform = {
|
||||
id: 'elecfans',
|
||||
name: '电子发烧友',
|
||||
icon: 'https://www.elecfans.com/favicon.ico',
|
||||
publishUrl: 'https://www.elecfans.com/d/article/md/',
|
||||
loginUrl: 'https://bbs.elecfans.com/member.php?mod=logging&action=login',
|
||||
}
|
||||
|
||||
export const ElecfansLoginConfig = {
|
||||
type: 'api',
|
||||
apiUrl: 'https://www.elecfans.com/webapi/passport/checklogin',
|
||||
checkLoggedIn: (data) => {
|
||||
// API 返回格式: {"uid":"6999925","username":"jf_50493572","avatar":"https://..."}
|
||||
if (data && data.uid) {
|
||||
return {
|
||||
loggedIn: true,
|
||||
username: data.username || '',
|
||||
avatar: data.avatar || '',
|
||||
}
|
||||
}
|
||||
return { loggedIn: false }
|
||||
},
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// 华为云开发者博客平台配置
|
||||
const HuaweiCloudPlatform = {
|
||||
id: 'huaweicloud',
|
||||
name: 'HuaweiCloud',
|
||||
icon: 'https://www.huaweicloud.com/favicon.ico',
|
||||
url: 'https://bbs.huaweicloud.com/',
|
||||
publishUrl: 'https://bbs.huaweicloud.com/blogs/article',
|
||||
title: '华为云开发者博客',
|
||||
type: 'huaweicloud',
|
||||
}
|
||||
|
||||
// 华为云开发者博客登录检测配置
|
||||
// 使用 cookie 检测登录状态
|
||||
const HuaweiCloudLoginConfig = {
|
||||
useCookie: true,
|
||||
cookieUrl: 'https://bbs.huaweicloud.com',
|
||||
cookieNames: ['ua', 'SessionID'],
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { HuaweiCloudPlatform, HuaweiCloudLoginConfig }
|
||||
@@ -1,147 +0,0 @@
|
||||
// 平台配置汇总 - 统一通过导入方式引入
|
||||
import { CSDNPlatform, CSDNLoginConfig, syncCSDNContent } from './csdn.js'
|
||||
import { JuejinPlatform, JuejinLoginConfig, syncJuejinContent } from './juejin.js'
|
||||
import { WechatPlatform, WechatLoginConfig, syncWechatContent } from './wechat.js'
|
||||
import { ZhihuPlatform, ZhihuLoginConfig, syncZhihuContent } from './zhihu.js'
|
||||
import { ToutiaoPlatform, ToutiaoLoginConfig } from './toutiao.js'
|
||||
import { SegmentFaultPlatform, SegmentFaultLoginConfig } from './segmentfault.js'
|
||||
import { CnblogsPlatform, CnblogsLoginConfig } from './cnblogs.js'
|
||||
import { OSChinaPlatform, OSChinaLoginConfig } from './oschina.js'
|
||||
import { CTO51Platform, CTO51LoginConfig } from './cto51.js'
|
||||
import { InfoQPlatform, InfoQLoginConfig } from './infoq.js'
|
||||
import { JianshuPlatform, JianshuLoginConfig } from './jianshu.js'
|
||||
import { BaijiahaoPlatform, BaijiahaoLoginConfig } from './baijiahao.js'
|
||||
import { WangyihaoPlatform, WangyihaoLoginConfig } from './wangyihao.js'
|
||||
import { TencentCloudPlatform, TencentCloudLoginConfig } from './tencentcloud.js'
|
||||
import { MediumPlatform, MediumLoginConfig } from './medium.js'
|
||||
import { SspaiPlatform, SspaiLoginConfig } from './sspai.js'
|
||||
import { SohuPlatform, SohuLoginConfig } from './sohu.js'
|
||||
import { BilibiliPlatform, BilibiliLoginConfig } from './bilibili.js'
|
||||
import { WeiboPlatform, WeiboLoginConfig } from './weibo.js'
|
||||
import { AliyunPlatform, AliyunLoginConfig } from './aliyun.js'
|
||||
import { HuaweiCloudPlatform, HuaweiCloudLoginConfig } from './huaweicloud.js'
|
||||
import { HuaweiDevPlatform, HuaweiDevLoginConfig } from './huaweidev.js'
|
||||
import { TwitterPlatform, TwitterLoginConfig } from './twitter.js'
|
||||
import { QianfanPlatform, QianfanLoginConfig } from './qianfan.js'
|
||||
import { AlipayOpenPlatform, AlipayOpenLoginConfig } from './alipayopen.js'
|
||||
import { ModelScopePlatform, ModelScopeLoginConfig } from './modelscope.js'
|
||||
import { VolcenginePlatform, VolcengineLoginConfig } from './volcengine.js'
|
||||
import { DouyinPlatform, DouyinLoginConfig } from './douyin.js'
|
||||
import { XiaohongshuPlatform, XiaohongshuLoginConfig } from './xiaohongshu.js'
|
||||
import { ElecfansPlatform, ElecfansLoginConfig } from './elecfans.js'
|
||||
|
||||
// 合并平台配置
|
||||
const PLATFORMS = [
|
||||
CSDNPlatform,
|
||||
JuejinPlatform,
|
||||
WechatPlatform,
|
||||
ZhihuPlatform,
|
||||
ToutiaoPlatform,
|
||||
SegmentFaultPlatform,
|
||||
CnblogsPlatform,
|
||||
OSChinaPlatform,
|
||||
CTO51Platform,
|
||||
InfoQPlatform,
|
||||
JianshuPlatform,
|
||||
BaijiahaoPlatform,
|
||||
WangyihaoPlatform,
|
||||
TencentCloudPlatform,
|
||||
MediumPlatform,
|
||||
SspaiPlatform,
|
||||
SohuPlatform,
|
||||
BilibiliPlatform,
|
||||
WeiboPlatform,
|
||||
AliyunPlatform,
|
||||
HuaweiCloudPlatform,
|
||||
HuaweiDevPlatform,
|
||||
TwitterPlatform,
|
||||
QianfanPlatform,
|
||||
AlipayOpenPlatform,
|
||||
ModelScopePlatform,
|
||||
VolcenginePlatform,
|
||||
DouyinPlatform,
|
||||
XiaohongshuPlatform,
|
||||
ElecfansPlatform,
|
||||
]
|
||||
|
||||
// 合并登录检测配置
|
||||
const LOGIN_CHECK_CONFIG = {
|
||||
[CSDNPlatform.id]: CSDNLoginConfig,
|
||||
[JuejinPlatform.id]: JuejinLoginConfig,
|
||||
[WechatPlatform.id]: WechatLoginConfig,
|
||||
[ZhihuPlatform.id]: ZhihuLoginConfig,
|
||||
[ToutiaoPlatform.id]: ToutiaoLoginConfig,
|
||||
[SegmentFaultPlatform.id]: SegmentFaultLoginConfig,
|
||||
[CnblogsPlatform.id]: CnblogsLoginConfig,
|
||||
[OSChinaPlatform.id]: OSChinaLoginConfig,
|
||||
[CTO51Platform.id]: CTO51LoginConfig,
|
||||
[InfoQPlatform.id]: InfoQLoginConfig,
|
||||
[JianshuPlatform.id]: JianshuLoginConfig,
|
||||
[BaijiahaoPlatform.id]: BaijiahaoLoginConfig,
|
||||
[WangyihaoPlatform.id]: WangyihaoLoginConfig,
|
||||
[TencentCloudPlatform.id]: TencentCloudLoginConfig,
|
||||
[MediumPlatform.id]: MediumLoginConfig,
|
||||
[SspaiPlatform.id]: SspaiLoginConfig,
|
||||
[SohuPlatform.id]: SohuLoginConfig,
|
||||
[BilibiliPlatform.id]: BilibiliLoginConfig,
|
||||
[WeiboPlatform.id]: WeiboLoginConfig,
|
||||
[AliyunPlatform.id]: AliyunLoginConfig,
|
||||
[HuaweiCloudPlatform.id]: HuaweiCloudLoginConfig,
|
||||
[HuaweiDevPlatform.id]: HuaweiDevLoginConfig,
|
||||
[TwitterPlatform.id]: TwitterLoginConfig,
|
||||
[QianfanPlatform.id]: QianfanLoginConfig,
|
||||
[AlipayOpenPlatform.id]: AlipayOpenLoginConfig,
|
||||
[ModelScopePlatform.id]: ModelScopeLoginConfig,
|
||||
[VolcenginePlatform.id]: VolcengineLoginConfig,
|
||||
[DouyinPlatform.id]: DouyinLoginConfig,
|
||||
[XiaohongshuPlatform.id]: XiaohongshuLoginConfig,
|
||||
[ElecfansPlatform.id]: ElecfansLoginConfig,
|
||||
}
|
||||
|
||||
// 根据 hostname 获取平台填充函数
|
||||
function getPlatformFiller(hostname) {
|
||||
if (hostname.includes('csdn.net')) return 'csdn'
|
||||
if (hostname.includes('juejin.cn')) return 'juejin'
|
||||
if (hostname.includes('mp.weixin.qq.com')) return 'wechat'
|
||||
if (hostname.includes('zhihu.com')) return 'zhihu'
|
||||
if (hostname.includes('toutiao.com')) return 'toutiao'
|
||||
if (hostname.includes('segmentfault.com')) return 'segmentfault'
|
||||
if (hostname.includes('cnblogs.com')) return 'cnblogs'
|
||||
if (hostname.includes('oschina.net')) return 'oschina'
|
||||
if (hostname.includes('51cto.com')) return 'cto51'
|
||||
if (hostname.includes('infoq.cn')) return 'infoq'
|
||||
if (hostname.includes('jianshu.com')) return 'jianshu'
|
||||
if (hostname.includes('baijiahao.baidu.com')) return 'baijiahao'
|
||||
if (hostname.includes('mp.163.com')) return 'wangyihao'
|
||||
if (hostname.includes('cloud.tencent.com')) return 'tencentcloud'
|
||||
if (hostname.includes('medium.com')) return 'medium'
|
||||
if (hostname.includes('sspai.com')) return 'sspai'
|
||||
if (hostname.includes('mp.sohu.com')) return 'sohu'
|
||||
if (hostname.includes('member.bilibili.com')) return 'bilibili'
|
||||
if (hostname.includes('card.weibo.com')) return 'weibo'
|
||||
if (hostname.includes('developer.aliyun.com')) return 'aliyun'
|
||||
if (hostname.includes('bbs.huaweicloud.com')) return 'huaweicloud'
|
||||
if (hostname.includes('developer.huawei.com')) return 'huaweidev'
|
||||
if (hostname.includes('x.com') || hostname.includes('twitter.com')) return 'twitter'
|
||||
if (hostname.includes('qianfan.cloud.baidu.com')) return 'qianfan'
|
||||
if (hostname.includes('open.alipay.com')) return 'alipayopen'
|
||||
if (hostname.includes('modelscope.cn')) return 'modelscope'
|
||||
if (hostname.includes('developer.volcengine.com')) return 'volcengine'
|
||||
if (hostname.includes('creator.douyin.com')) return 'douyin'
|
||||
if (hostname.includes('creator.xiaohongshu.com')) return 'xiaohongshu'
|
||||
if (hostname.includes('elecfans.com')) return 'elecfans'
|
||||
return 'generic'
|
||||
}
|
||||
|
||||
// 同步处理器映射
|
||||
// 如果平台有自定义同步逻辑,在此注册处理器
|
||||
// 未注册的平台将使用 background.js 中的通用填充逻辑
|
||||
const SYNC_HANDLERS = {
|
||||
csdn: syncCSDNContent,
|
||||
juejin: syncJuejinContent,
|
||||
wechat: syncWechatContent,
|
||||
zhihu: syncZhihuContent,
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { PLATFORMS, LOGIN_CHECK_CONFIG, SYNC_HANDLERS, getPlatformFiller }
|
||||
@@ -1,25 +0,0 @@
|
||||
// 火山引擎开发者社区平台配置
|
||||
const VolcenginePlatform = {
|
||||
id: 'volcengine',
|
||||
name: 'Volcengine',
|
||||
icon: 'https://lf1-cdn-tos.bytegoofy.com/goofy/tech-fe/fav.png',
|
||||
url: 'https://developer.volcengine.com/',
|
||||
publishUrl: 'https://developer.volcengine.com/articles/draft',
|
||||
title: '火山引擎开发者社区',
|
||||
type: 'volcengine',
|
||||
}
|
||||
|
||||
// 火山引擎登录检测配置
|
||||
// 使用 API 检测登录状态
|
||||
const VolcengineLoginConfig = {
|
||||
api: 'https://developer.volcengine.com/api/fe/v1/user',
|
||||
method: 'GET',
|
||||
checkLogin: (response) => response?.err_no === 0 && response?.data?.user_id,
|
||||
getUserInfo: (response) => ({
|
||||
username: response?.data?.name,
|
||||
avatar: response?.data?.avatar?.url,
|
||||
}),
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { VolcenginePlatform, VolcengineLoginConfig }
|
||||
@@ -1,21 +0,0 @@
|
||||
// 微博头条文章平台配置
|
||||
const WeiboPlatform = {
|
||||
id: 'weibo',
|
||||
name: 'Weibo',
|
||||
icon: 'https://weibo.com/favicon.ico',
|
||||
url: 'https://weibo.com',
|
||||
publishUrl: 'https://card.weibo.com/article/v5/editor#/draft',
|
||||
title: '微博头条',
|
||||
type: 'weibo',
|
||||
}
|
||||
|
||||
// 微博登录检测配置 - 使用 API 检测,不使用 cookie
|
||||
const WeiboLoginConfig = {
|
||||
api: 'https://card.weibo.com/article/v5/aj/editor/draft/list?uid=0&allow_pay=1',
|
||||
method: 'GET',
|
||||
checkLogin: (data) => data?.code === 100000,
|
||||
getUserInfo: () => ({ username: '', avatar: '' }), // 用户信息在 background.js 中单独获取
|
||||
}
|
||||
|
||||
// 导出
|
||||
export { WeiboPlatform, WeiboLoginConfig }
|
||||