annotask 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -0
- package/dist/chunk-2TUWBFQG.js +882 -0
- package/dist/chunk-2TUWBFQG.js.map +1 -0
- package/dist/chunk-3VLTLTEO.js +53 -0
- package/dist/chunk-3VLTLTEO.js.map +1 -0
- package/dist/chunk-53D2PE43.js +105 -0
- package/dist/chunk-53D2PE43.js.map +1 -0
- package/dist/chunk-6UQW2W7S.js +358 -0
- package/dist/chunk-6UQW2W7S.js.map +1 -0
- package/dist/chunk-6VYCY34B.js +848 -0
- package/dist/chunk-6VYCY34B.js.map +1 -0
- package/dist/chunk-B7IKW7UB.js +792 -0
- package/dist/chunk-B7IKW7UB.js.map +1 -0
- package/dist/chunk-BDMOC2BG.js +794 -0
- package/dist/chunk-BDMOC2BG.js.map +1 -0
- package/dist/chunk-CFBRU3DQ.js +332 -0
- package/dist/chunk-CFBRU3DQ.js.map +1 -0
- package/dist/chunk-CWA33RDQ.js +21 -0
- package/dist/chunk-CWA33RDQ.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-EAT6V4LF.js +358 -0
- package/dist/chunk-EAT6V4LF.js.map +1 -0
- package/dist/chunk-FBXNRXMY.js +849 -0
- package/dist/chunk-FBXNRXMY.js.map +1 -0
- package/dist/chunk-LKRKKLOT.js +61 -0
- package/dist/chunk-LKRKKLOT.js.map +1 -0
- package/dist/chunk-STOP7QF3.js +61 -0
- package/dist/chunk-STOP7QF3.js.map +1 -0
- package/dist/chunk-T6TKVAAA.js +332 -0
- package/dist/chunk-T6TKVAAA.js.map +1 -0
- package/dist/chunk-VCC7UV6G.js +291 -0
- package/dist/chunk-VCC7UV6G.js.map +1 -0
- package/dist/chunk-XR26XVHT.js +21 -0
- package/dist/chunk-XR26XVHT.js.map +1 -0
- package/dist/chunk-XZNNRBUW.js +311 -0
- package/dist/chunk-XZNNRBUW.js.map +1 -0
- package/dist/cli.js +248 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +50 -0
- package/dist/server.js +15 -0
- package/dist/server.js.map +1 -0
- package/dist/shell/assets/index-BD3nZNWX.js +59 -0
- package/dist/shell/assets/index-DwbhEo-C.css +1 -0
- package/dist/shell/index.html +13 -0
- package/dist/standalone.d.ts +10 -0
- package/dist/standalone.js +9 -0
- package/dist/standalone.js.map +1 -0
- package/dist/webpack-loader.d.ts +3 -0
- package/dist/webpack-loader.js +59 -0
- package/dist/webpack-loader.js.map +1 -0
- package/dist/webpack.d.ts +11 -0
- package/dist/webpack.js +63 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +78 -0
- package/skills/annotask-apply/SKILL.md +133 -0
- package/skills/annotask-init/SKILL.md +230 -0
- package/skills/annotask-watch/SKILL.md +45 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin/transform.ts"],"sourcesContent":["/**\n * Source file transform — injects data-annotask-* attributes on HTML elements.\n *\n * Supports Vue SFC (.vue), React JSX (.jsx/.tsx), and Svelte (.svelte).\n * The core HTML scanner (injectAttributes + findTagEnd) is shared across\n * all frameworks. Each framework has its own extraction logic to locate\n * the markup regions within a source file.\n */\n\n/**\n * Top-level dispatcher. Detects framework by file extension and delegates\n * to the appropriate transform function.\n */\nexport function transformFile(\n code: string,\n filePath: string,\n projectRoot: string\n): string | null {\n if (filePath.endsWith('.vue')) return transformVueSFC(code, filePath, projectRoot)\n if (filePath.endsWith('.svelte')) return transformSvelte(code, filePath, projectRoot)\n if (/\\.[jt]sx$/.test(filePath)) return transformJSX(code, filePath, projectRoot)\n if (filePath.endsWith('.html')) return transformHTML(code, filePath, projectRoot)\n return null\n}\n\n// ── Vue SFC ─────────────────────────────────────────────\n\n/**\n * Transform a Vue SFC's raw source to inject data-annotask-* attributes\n * on every element in the <template> block.\n */\nexport function transformVueSFC(\n code: string,\n filePath: string,\n projectRoot: string\n): string | null {\n if (!code.includes('<template')) return null\n\n const templateMatch = code.match(/<template(\\s[^>]*)?>/)\n if (!templateMatch) return null\n\n const templateStart = code.indexOf(templateMatch[0])\n const templateEnd = code.lastIndexOf('</template>')\n if (templateEnd === -1) return null\n\n const templateOpenTagEnd = templateStart + templateMatch[0].length\n const templateContent = code.slice(templateOpenTagEnd, templateEnd)\n\n const relativeFile = relativePath(filePath, projectRoot)\n const componentName = extractComponentName(filePath)\n const templateStartLine = code.slice(0, templateOpenTagEnd).split('\\n').length\n\n const injected = injectAttributes(templateContent, relativeFile, componentName, templateStartLine)\n if (!injected) return null\n\n return code.slice(0, templateOpenTagEnd) + injected + code.slice(templateEnd)\n}\n\n/** @deprecated Use transformVueSFC instead */\nexport const transformSFC = transformVueSFC\n\n// ── Svelte ──────────────────────────────────────────────\n\n/**\n * Transform a Svelte component. Markup in .svelte files is everything\n * NOT inside <script> or <style> blocks.\n */\nexport function transformSvelte(\n code: string,\n filePath: string,\n projectRoot: string\n): string | null {\n const relativeFile = relativePath(filePath, projectRoot)\n const componentName = extractComponentName(filePath)\n\n // Find all <script> and <style> block ranges (including their tags)\n const blockRanges = findBlockRanges(code, ['script', 'style'])\n\n // Collect markup regions (gaps between blocks)\n const markupRegions = getMarkupRegions(code, blockRanges)\n\n if (markupRegions.length === 0) return null\n\n let result = ''\n let lastIndex = 0\n let changed = false\n\n for (const region of markupRegions) {\n // Add everything before this region (script/style blocks)\n result += code.slice(lastIndex, region.start)\n\n const regionContent = code.slice(region.start, region.end)\n const regionStartLine = code.slice(0, region.start).split('\\n').length\n\n const injected = injectAttributes(\n regionContent,\n relativeFile,\n componentName,\n regionStartLine,\n { skipTags: SVELTE_SKIP_TAGS }\n )\n\n if (injected) {\n result += injected\n changed = true\n } else {\n result += regionContent\n }\n\n lastIndex = region.end\n }\n\n if (!changed) return null\n\n result += code.slice(lastIndex)\n return result\n}\n\nconst SVELTE_SKIP_TAGS = new Set([\n 'script', 'style',\n 'svelte:head', 'svelte:window', 'svelte:document', 'svelte:body',\n 'svelte:options', 'svelte:fragment', 'svelte:self', 'svelte:component',\n 'svelte:element', 'svelte:boundary',\n])\n\n// ── React JSX ───────────────────────────────────────────\n\n/**\n * Transform a React JSX/TSX file. JSX is interleaved with JavaScript,\n * so we scan the full file with brace-depth tracking enabled.\n */\nexport function transformJSX(\n code: string,\n filePath: string,\n projectRoot: string\n): string | null {\n const relativeFile = relativePath(filePath, projectRoot)\n const componentName = extractComponentName(filePath)\n\n const injected = injectAttributes(code, relativeFile, componentName, 1, {\n jsxMode: true,\n skipTags: JSX_SKIP_TAGS,\n })\n\n return injected\n}\n\n/** Tags to skip in JSX mode. Fragments have empty tag names and are handled separately. */\nconst JSX_SKIP_TAGS = new Set(['script', 'style'])\n\n// ── HTML ───────────────────────────────────────────────\n\n/**\n * Transform a plain HTML file. Injects data-annotask-* attributes on\n * every element inside the <body> block.\n */\nexport function transformHTML(\n code: string,\n filePath: string,\n projectRoot: string\n): string | null {\n const bodyMatch = code.match(/<body(\\s[^>]*)?>/)\n if (!bodyMatch) return null\n\n const bodyStart = code.indexOf(bodyMatch[0])\n const bodyEnd = code.lastIndexOf('</body>')\n if (bodyEnd === -1) return null\n\n const bodyOpenTagEnd = bodyStart + bodyMatch[0].length\n const bodyContent = code.slice(bodyOpenTagEnd, bodyEnd)\n\n const relativeFile = relativePath(filePath, projectRoot)\n const componentName = extractComponentName(filePath)\n const bodyStartLine = code.slice(0, bodyOpenTagEnd).split('\\n').length\n\n const injected = injectAttributes(bodyContent, relativeFile, componentName, bodyStartLine, {\n skipTags: HTML_SKIP_TAGS,\n })\n if (!injected) return null\n\n return code.slice(0, bodyOpenTagEnd) + injected + code.slice(bodyEnd)\n}\n\nconst HTML_SKIP_TAGS = new Set(['script', 'style'])\n\n/**\n * Known TypeScript/JS generic type names that should NOT be treated as JSX tags.\n * When the scanner sees `<Array` or `<Promise` etc., it skips them.\n */\nconst TS_GENERIC_NAMES = new Set([\n 'Array', 'Map', 'Set', 'WeakMap', 'WeakSet', 'Promise', 'Generator',\n 'AsyncGenerator', 'Iterable', 'AsyncIterable', 'Iterator',\n 'Record', 'Partial', 'Required', 'Readonly', 'Pick', 'Omit',\n 'Exclude', 'Extract', 'NonNullable', 'ReturnType', 'Parameters',\n 'InstanceType', 'ConstructorParameters', 'Awaited',\n 'ReadonlyArray', 'ReadonlyMap', 'ReadonlySet',\n 'Uppercase', 'Lowercase', 'Capitalize', 'Uncapitalize',\n])\n\n// ── Shared Utilities ────────────────────────────────────\n\nexport function extractComponentName(filePath: string): string {\n const fileName = filePath.split('/').pop() || ''\n return fileName.replace(/\\.(vue|svelte|[jt]sx?)$/, '')\n}\n\nfunction relativePath(filePath: string, projectRoot: string): string {\n return filePath.startsWith(projectRoot)\n ? filePath.slice(projectRoot.length).replace(/^\\//, '')\n : filePath\n}\n\ninterface InjectOptions {\n /** Enable JSX mode: track {} brace depth, skip TS generics */\n jsxMode?: boolean\n /** Tags to skip (won't have attributes injected) */\n skipTags?: Set<string>\n}\n\n/**\n * Walk through HTML/JSX markup and inject data-annotask-* attributes on\n * every element's opening tag.\n *\n * Uses a character-level scanner that is quote-aware, so `>` inside\n * attribute values does not prematurely close the tag.\n */\nexport function injectAttributes(\n template: string,\n file: string,\n componentName: string,\n templateStartLine: number,\n options?: InjectOptions,\n): string | null {\n const skipTags = options?.skipTags ?? DEFAULT_SKIP_TAGS\n const jsxMode = options?.jsxMode ?? false\n\n let result = ''\n let lastIndex = 0\n let changed = false\n let i = 0\n\n while (i < template.length) {\n // Skip comments\n if (template.startsWith('<!--', i)) {\n const end = template.indexOf('-->', i + 4)\n i = end === -1 ? template.length : end + 3\n continue\n }\n\n // Skip closing tags\n if (template.startsWith('</', i)) {\n const end = template.indexOf('>', i + 2)\n i = end === -1 ? template.length : end + 1\n continue\n }\n\n // Check for opening tag\n if (template[i] === '<' && i + 1 < template.length && /[a-zA-Z]/.test(template[i + 1])) {\n const tagStart = i\n i++ // past '<'\n\n // Read tag name (including namespaced tags like svelte:head)\n const nameStart = i\n while (i < template.length && /[a-zA-Z0-9\\-:]/.test(template[i])) i++\n const tagName = template.slice(nameStart, i)\n\n // In JSX mode, skip React fragments (empty tag name won't reach here,\n // but <> starts with < followed by > which isn't [a-zA-Z])\n // Skip known TypeScript generics\n if (jsxMode && TS_GENERIC_NAMES.has(tagName)) {\n // This is a TS generic like Array<string>, not a JSX tag\n // Find the closing > accounting for nested generics\n i = skipGeneric(template, i)\n continue\n }\n\n // In JSX mode, check if this looks like a type context\n // (preceded by : or as or extends or implements)\n if (jsxMode && isTypeContext(template, tagStart)) {\n i = skipGeneric(template, i)\n continue\n }\n\n // Skip tags we don't want to instrument\n if (skipTags.has(tagName) || skipTags.has(tagName.toLowerCase())) {\n i = findTagEnd(template, i, jsxMode)\n continue\n }\n\n // Scan past attributes to find the closing > or />\n const tagEndIndex = findTagEnd(template, i, jsxMode)\n\n const tagSource = template.slice(tagStart, tagEndIndex)\n\n // Skip if already instrumented\n if (tagSource.includes('data-annotask-file')) {\n i = tagEndIndex\n continue\n }\n\n // Calculate file-relative line number\n const lineInFile = templateStartLine + template.slice(0, tagStart).split('\\n').length - 1\n\n const injection = ` data-annotask-file=\"${file}\" data-annotask-line=\"${lineInFile}\" data-annotask-component=\"${componentName}\"`\n\n // Find the insertion point: right before '>' or '/>'\n let insertAt = tagEndIndex - 1 // the '>'\n if (insertAt > 0 && template[insertAt - 1] === '/') insertAt-- // before '/>'\n\n result += template.slice(lastIndex, insertAt)\n result += injection\n result += template.slice(insertAt, tagEndIndex)\n lastIndex = tagEndIndex\n changed = true\n i = tagEndIndex\n\n continue\n }\n\n i++\n }\n\n if (!changed) return null\n\n result += template.slice(lastIndex)\n return result\n}\n\nconst DEFAULT_SKIP_TAGS = new Set(['script', 'style', 'template', 'slot'])\n\n/**\n * Starting from position `i` (after the tag name), scan forward past\n * all attributes and find the closing `>`. Handles quoted strings\n * so that `>` inside `\"...\"`, `'...'`, or `` `...` `` doesn't end the tag.\n *\n * In JSX mode, also tracks `{}` brace depth so that `>` inside\n * JSX expression attributes (e.g., `{x > 5}`) doesn't end the tag.\n */\nexport function findTagEnd(template: string, i: number, jsxMode = false): number {\n let inQuote: string | null = null\n let braceDepth = 0\n\n while (i < template.length) {\n const ch = template[i]\n\n if (inQuote === '`') {\n if (ch === '`' && braceDepth === 0) {\n inQuote = null\n } else if (ch === '$' && i + 1 < template.length && template[i + 1] === '{') {\n braceDepth++\n i++ // skip past '{'\n } else if (ch === '}' && braceDepth > 0) {\n braceDepth--\n }\n } else if (inQuote) {\n if (ch === inQuote) inQuote = null\n } else {\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n inQuote = ch\n } else if (jsxMode && ch === '{') {\n braceDepth++\n } else if (jsxMode && ch === '}' && braceDepth > 0) {\n braceDepth--\n } else if (ch === '>' && braceDepth === 0) {\n return i + 1\n }\n }\n i++\n }\n\n return i\n}\n\n// ── Svelte helpers ──────────────────────────────────────\n\ninterface Range { start: number; end: number }\n\n/**\n * Find all ranges of the given block-level tags (e.g., script, style)\n * including their opening and closing tags.\n */\nfunction findBlockRanges(code: string, tagNames: string[]): Range[] {\n const ranges: Range[] = []\n for (const tag of tagNames) {\n // Match opening tags like <script>, <script context=\"module\">, <style lang=\"scss\">\n const openRegex = new RegExp(`<${tag}(\\\\s[^>]*)?>`, 'gi')\n let match\n while ((match = openRegex.exec(code)) !== null) {\n const start = match.index\n const closeTag = `</${tag}>`\n const closeIndex = code.indexOf(closeTag, start + match[0].length)\n if (closeIndex !== -1) {\n ranges.push({ start, end: closeIndex + closeTag.length })\n }\n }\n }\n // Sort by start position\n ranges.sort((a, b) => a.start - b.start)\n return ranges\n}\n\n/**\n * Given sorted block ranges, return the markup regions (gaps between blocks).\n */\nfunction getMarkupRegions(code: string, blockRanges: Range[]): Range[] {\n const regions: Range[] = []\n let cursor = 0\n\n for (const block of blockRanges) {\n if (block.start > cursor) {\n const region = code.slice(cursor, block.start)\n // Only include regions that have actual markup (not just whitespace)\n if (region.trim().length > 0) {\n regions.push({ start: cursor, end: block.start })\n }\n }\n cursor = block.end\n }\n\n // Region after the last block\n if (cursor < code.length) {\n const region = code.slice(cursor)\n if (region.trim().length > 0) {\n regions.push({ start: cursor, end: code.length })\n }\n }\n\n return regions\n}\n\n// ── JSX helpers ─────────────────────────────────────────\n\n/**\n * Check if the `<` at position `tagStart` is in a TypeScript type/generic\n * context rather than JSX.\n *\n * Key insight: In JSX, `<` is always preceded by whitespace, an operator,\n * punctuation, or a JSX-context keyword (return, yield, etc.).\n * In generics, `<` immediately follows an identifier: `Array<string>`,\n * `foo<T>()`, `Promise<void>`.\n */\nfunction isTypeContext(code: string, tagStart: number): boolean {\n // Walk backward past whitespace to find the preceding token\n let j = tagStart - 1\n while (j >= 0 && (code[j] === ' ' || code[j] === '\\t' || code[j] === '\\n' || code[j] === '\\r')) j--\n if (j < 0) return false\n\n const ch = code[j]\n\n // Preceded by : (type annotation), < (nested generic), . (member access in type)\n if (ch === ':' || ch === '<' || ch === '.') return true\n\n // If preceded by an identifier character, it's likely a generic: Array<T>, foo<T>\n // Exception: JSX-context keywords like return, yield, case, etc.\n if (/[a-zA-Z0-9_$]/.test(ch)) {\n // Read the full preceding word\n let wordEnd = j + 1\n while (j >= 0 && /[a-zA-Z0-9_$]/.test(code[j])) j--\n const word = code.slice(j + 1, wordEnd)\n\n // These keywords can precede JSX: return <div>, yield <X />, etc.\n const jsxKeywords = new Set(['return', 'yield', 'case', 'default', 'throw', 'new', 'in', 'of', 'else'])\n if (jsxKeywords.has(word)) return false\n\n // Any other identifier before < means it's a generic\n return true\n }\n\n // Check for keyword tokens that signal type context\n // (already handled above via identifier check, but keep for safety)\n const typeKeywords = ['as', 'extends', 'implements', 'typeof', 'keyof', 'infer', 'type']\n for (const kw of typeKeywords) {\n if (j >= kw.length - 1) {\n const slice = code.slice(j - kw.length + 1, j + 1)\n if (slice === kw) {\n const before = j - kw.length\n if (before < 0 || /\\s|[,;({[<>|&=!?+\\-*/]/.test(code[before])) {\n return true\n }\n }\n }\n }\n\n return false\n}\n\n/**\n * Skip past a TypeScript generic expression like `<string>` or `<T extends U>`.\n * Tracks nested `<>` depth.\n */\nfunction skipGeneric(code: string, i: number): number {\n let depth = 1\n while (i < code.length && depth > 0) {\n if (code[i] === '<') depth++\n else if (code[i] === '>') depth--\n i++\n }\n return i\n}\n"],"mappings":";AAaO,SAAS,cACd,MACA,UACA,aACe;AACf,MAAI,SAAS,SAAS,MAAM,EAAG,QAAO,gBAAgB,MAAM,UAAU,WAAW;AACjF,MAAI,SAAS,SAAS,SAAS,EAAG,QAAO,gBAAgB,MAAM,UAAU,WAAW;AACpF,MAAI,YAAY,KAAK,QAAQ,EAAG,QAAO,aAAa,MAAM,UAAU,WAAW;AAC/E,MAAI,SAAS,SAAS,OAAO,EAAG,QAAO,cAAc,MAAM,UAAU,WAAW;AAChF,SAAO;AACT;AAQO,SAAS,gBACd,MACA,UACA,aACe;AACf,MAAI,CAAC,KAAK,SAAS,WAAW,EAAG,QAAO;AAExC,QAAM,gBAAgB,KAAK,MAAM,sBAAsB;AACvD,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,gBAAgB,KAAK,QAAQ,cAAc,CAAC,CAAC;AACnD,QAAM,cAAc,KAAK,YAAY,aAAa;AAClD,MAAI,gBAAgB,GAAI,QAAO;AAE/B,QAAM,qBAAqB,gBAAgB,cAAc,CAAC,EAAE;AAC5D,QAAM,kBAAkB,KAAK,MAAM,oBAAoB,WAAW;AAElE,QAAM,eAAe,aAAa,UAAU,WAAW;AACvD,QAAM,gBAAgB,qBAAqB,QAAQ;AACnD,QAAM,oBAAoB,KAAK,MAAM,GAAG,kBAAkB,EAAE,MAAM,IAAI,EAAE;AAExE,QAAM,WAAW,iBAAiB,iBAAiB,cAAc,eAAe,iBAAiB;AACjG,MAAI,CAAC,SAAU,QAAO;AAEtB,SAAO,KAAK,MAAM,GAAG,kBAAkB,IAAI,WAAW,KAAK,MAAM,WAAW;AAC9E;AAWO,SAAS,gBACd,MACA,UACA,aACe;AACf,QAAM,eAAe,aAAa,UAAU,WAAW;AACvD,QAAM,gBAAgB,qBAAqB,QAAQ;AAGnD,QAAM,cAAc,gBAAgB,MAAM,CAAC,UAAU,OAAO,CAAC;AAG7D,QAAM,gBAAgB,iBAAiB,MAAM,WAAW;AAExD,MAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,MAAI,UAAU;AAEd,aAAW,UAAU,eAAe;AAElC,cAAU,KAAK,MAAM,WAAW,OAAO,KAAK;AAE5C,UAAM,gBAAgB,KAAK,MAAM,OAAO,OAAO,OAAO,GAAG;AACzD,UAAM,kBAAkB,KAAK,MAAM,GAAG,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE;AAEhE,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,UAAU,iBAAiB;AAAA,IAC/B;AAEA,QAAI,UAAU;AACZ,gBAAU;AACV,gBAAU;AAAA,IACZ,OAAO;AACL,gBAAU;AAAA,IACZ;AAEA,gBAAY,OAAO;AAAA,EACrB;AAEA,MAAI,CAAC,QAAS,QAAO;AAErB,YAAU,KAAK,MAAM,SAAS;AAC9B,SAAO;AACT;AAEA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EAAU;AAAA,EACV;AAAA,EAAe;AAAA,EAAiB;AAAA,EAAmB;AAAA,EACnD;AAAA,EAAkB;AAAA,EAAmB;AAAA,EAAe;AAAA,EACpD;AAAA,EAAkB;AACpB,CAAC;AAQM,SAAS,aACd,MACA,UACA,aACe;AACf,QAAM,eAAe,aAAa,UAAU,WAAW;AACvD,QAAM,gBAAgB,qBAAqB,QAAQ;AAEnD,QAAM,WAAW,iBAAiB,MAAM,cAAc,eAAe,GAAG;AAAA,IACtE,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AAED,SAAO;AACT;AAGA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,UAAU,OAAO,CAAC;AAQ1C,SAAS,cACd,MACA,UACA,aACe;AACf,QAAM,YAAY,KAAK,MAAM,kBAAkB;AAC/C,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,YAAY,KAAK,QAAQ,UAAU,CAAC,CAAC;AAC3C,QAAM,UAAU,KAAK,YAAY,SAAS;AAC1C,MAAI,YAAY,GAAI,QAAO;AAE3B,QAAM,iBAAiB,YAAY,UAAU,CAAC,EAAE;AAChD,QAAM,cAAc,KAAK,MAAM,gBAAgB,OAAO;AAEtD,QAAM,eAAe,aAAa,UAAU,WAAW;AACvD,QAAM,gBAAgB,qBAAqB,QAAQ;AACnD,QAAM,gBAAgB,KAAK,MAAM,GAAG,cAAc,EAAE,MAAM,IAAI,EAAE;AAEhE,QAAM,WAAW,iBAAiB,aAAa,cAAc,eAAe,eAAe;AAAA,IACzF,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,CAAC,SAAU,QAAO;AAEtB,SAAO,KAAK,MAAM,GAAG,cAAc,IAAI,WAAW,KAAK,MAAM,OAAO;AACtE;AAEA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,OAAO,CAAC;AAMlD,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EAAS;AAAA,EAAO;AAAA,EAAO;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EACxD;AAAA,EAAkB;AAAA,EAAY;AAAA,EAAiB;AAAA,EAC/C;AAAA,EAAU;AAAA,EAAW;AAAA,EAAY;AAAA,EAAY;AAAA,EAAQ;AAAA,EACrD;AAAA,EAAW;AAAA,EAAW;AAAA,EAAe;AAAA,EAAc;AAAA,EACnD;AAAA,EAAgB;AAAA,EAAyB;AAAA,EACzC;AAAA,EAAiB;AAAA,EAAe;AAAA,EAChC;AAAA,EAAa;AAAA,EAAa;AAAA,EAAc;AAC1C,CAAC;AAIM,SAAS,qBAAqB,UAA0B;AAC7D,QAAM,WAAW,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAC9C,SAAO,SAAS,QAAQ,2BAA2B,EAAE;AACvD;AAEA,SAAS,aAAa,UAAkB,aAA6B;AACnE,SAAO,SAAS,WAAW,WAAW,IAClC,SAAS,MAAM,YAAY,MAAM,EAAE,QAAQ,OAAO,EAAE,IACpD;AACN;AAgBO,SAAS,iBACd,UACA,MACA,eACA,mBACA,SACe;AACf,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,UAAU,SAAS,WAAW;AAEpC,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI,IAAI;AAER,SAAO,IAAI,SAAS,QAAQ;AAE1B,QAAI,SAAS,WAAW,QAAQ,CAAC,GAAG;AAClC,YAAM,MAAM,SAAS,QAAQ,OAAO,IAAI,CAAC;AACzC,UAAI,QAAQ,KAAK,SAAS,SAAS,MAAM;AACzC;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,MAAM,CAAC,GAAG;AAChC,YAAM,MAAM,SAAS,QAAQ,KAAK,IAAI,CAAC;AACvC,UAAI,QAAQ,KAAK,SAAS,SAAS,MAAM;AACzC;AAAA,IACF;AAGA,QAAI,SAAS,CAAC,MAAM,OAAO,IAAI,IAAI,SAAS,UAAU,WAAW,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG;AACtF,YAAM,WAAW;AACjB;AAGA,YAAM,YAAY;AAClB,aAAO,IAAI,SAAS,UAAU,iBAAiB,KAAK,SAAS,CAAC,CAAC,EAAG;AAClE,YAAM,UAAU,SAAS,MAAM,WAAW,CAAC;AAK3C,UAAI,WAAW,iBAAiB,IAAI,OAAO,GAAG;AAG5C,YAAI,YAAY,UAAU,CAAC;AAC3B;AAAA,MACF;AAIA,UAAI,WAAW,cAAc,UAAU,QAAQ,GAAG;AAChD,YAAI,YAAY,UAAU,CAAC;AAC3B;AAAA,MACF;AAGA,UAAI,SAAS,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,YAAY,CAAC,GAAG;AAChE,YAAI,WAAW,UAAU,GAAG,OAAO;AACnC;AAAA,MACF;AAGA,YAAM,cAAc,WAAW,UAAU,GAAG,OAAO;AAEnD,YAAM,YAAY,SAAS,MAAM,UAAU,WAAW;AAGtD,UAAI,UAAU,SAAS,oBAAoB,GAAG;AAC5C,YAAI;AACJ;AAAA,MACF;AAGA,YAAM,aAAa,oBAAoB,SAAS,MAAM,GAAG,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS;AAExF,YAAM,YAAY,wBAAwB,IAAI,yBAAyB,UAAU,8BAA8B,aAAa;AAG5H,UAAI,WAAW,cAAc;AAC7B,UAAI,WAAW,KAAK,SAAS,WAAW,CAAC,MAAM,IAAK;AAEpD,gBAAU,SAAS,MAAM,WAAW,QAAQ;AAC5C,gBAAU;AACV,gBAAU,SAAS,MAAM,UAAU,WAAW;AAC9C,kBAAY;AACZ,gBAAU;AACV,UAAI;AAEJ;AAAA,IACF;AAEA;AAAA,EACF;AAEA,MAAI,CAAC,QAAS,QAAO;AAErB,YAAU,SAAS,MAAM,SAAS;AAClC,SAAO;AACT;AAEA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,UAAU,SAAS,YAAY,MAAM,CAAC;AAUlE,SAAS,WAAW,UAAkB,GAAW,UAAU,OAAe;AAC/E,MAAI,UAAyB;AAC7B,MAAI,aAAa;AAEjB,SAAO,IAAI,SAAS,QAAQ;AAC1B,UAAM,KAAK,SAAS,CAAC;AAErB,QAAI,YAAY,KAAK;AACnB,UAAI,OAAO,OAAO,eAAe,GAAG;AAClC,kBAAU;AAAA,MACZ,WAAW,OAAO,OAAO,IAAI,IAAI,SAAS,UAAU,SAAS,IAAI,CAAC,MAAM,KAAK;AAC3E;AACA;AAAA,MACF,WAAW,OAAO,OAAO,aAAa,GAAG;AACvC;AAAA,MACF;AAAA,IACF,WAAW,SAAS;AAClB,UAAI,OAAO,QAAS,WAAU;AAAA,IAChC,OAAO;AACL,UAAI,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAC1C,kBAAU;AAAA,MACZ,WAAW,WAAW,OAAO,KAAK;AAChC;AAAA,MACF,WAAW,WAAW,OAAO,OAAO,aAAa,GAAG;AAClD;AAAA,MACF,WAAW,OAAO,OAAO,eAAe,GAAG;AACzC,eAAO,IAAI;AAAA,MACb;AAAA,IACF;AACA;AAAA,EACF;AAEA,SAAO;AACT;AAUA,SAAS,gBAAgB,MAAc,UAA6B;AAClE,QAAM,SAAkB,CAAC;AACzB,aAAW,OAAO,UAAU;AAE1B,UAAM,YAAY,IAAI,OAAO,IAAI,GAAG,gBAAgB,IAAI;AACxD,QAAI;AACJ,YAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,YAAM,QAAQ,MAAM;AACpB,YAAM,WAAW,KAAK,GAAG;AACzB,YAAM,aAAa,KAAK,QAAQ,UAAU,QAAQ,MAAM,CAAC,EAAE,MAAM;AACjE,UAAI,eAAe,IAAI;AACrB,eAAO,KAAK,EAAE,OAAO,KAAK,aAAa,SAAS,OAAO,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACvC,SAAO;AACT;AAKA,SAAS,iBAAiB,MAAc,aAA+B;AACrE,QAAM,UAAmB,CAAC;AAC1B,MAAI,SAAS;AAEb,aAAW,SAAS,aAAa;AAC/B,QAAI,MAAM,QAAQ,QAAQ;AACxB,YAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,KAAK;AAE7C,UAAI,OAAO,KAAK,EAAE,SAAS,GAAG;AAC5B,gBAAQ,KAAK,EAAE,OAAO,QAAQ,KAAK,MAAM,MAAM,CAAC;AAAA,MAClD;AAAA,IACF;AACA,aAAS,MAAM;AAAA,EACjB;AAGA,MAAI,SAAS,KAAK,QAAQ;AACxB,UAAM,SAAS,KAAK,MAAM,MAAM;AAChC,QAAI,OAAO,KAAK,EAAE,SAAS,GAAG;AAC5B,cAAQ,KAAK,EAAE,OAAO,QAAQ,KAAK,KAAK,OAAO,CAAC;AAAA,IAClD;AAAA,EACF;AAEA,SAAO;AACT;AAaA,SAAS,cAAc,MAAc,UAA2B;AAE9D,MAAI,IAAI,WAAW;AACnB,SAAO,KAAK,MAAM,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,OAAQ,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,MAAO;AAChG,MAAI,IAAI,EAAG,QAAO;AAElB,QAAM,KAAK,KAAK,CAAC;AAGjB,MAAI,OAAO,OAAO,OAAO,OAAO,OAAO,IAAK,QAAO;AAInD,MAAI,gBAAgB,KAAK,EAAE,GAAG;AAE5B,QAAI,UAAU,IAAI;AAClB,WAAO,KAAK,KAAK,gBAAgB,KAAK,KAAK,CAAC,CAAC,EAAG;AAChD,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG,OAAO;AAGtC,UAAM,cAAc,oBAAI,IAAI,CAAC,UAAU,SAAS,QAAQ,WAAW,SAAS,OAAO,MAAM,MAAM,MAAM,CAAC;AACtG,QAAI,YAAY,IAAI,IAAI,EAAG,QAAO;AAGlC,WAAO;AAAA,EACT;AAIA,QAAM,eAAe,CAAC,MAAM,WAAW,cAAc,UAAU,SAAS,SAAS,MAAM;AACvF,aAAW,MAAM,cAAc;AAC7B,QAAI,KAAK,GAAG,SAAS,GAAG;AACtB,YAAM,QAAQ,KAAK,MAAM,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AACjD,UAAI,UAAU,IAAI;AAChB,cAAM,SAAS,IAAI,GAAG;AACtB,YAAI,SAAS,KAAK,yBAAyB,KAAK,KAAK,MAAM,CAAC,GAAG;AAC7D,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,YAAY,MAAc,GAAmB;AACpD,MAAI,QAAQ;AACZ,SAAO,IAAI,KAAK,UAAU,QAAQ,GAAG;AACnC,QAAI,KAAK,CAAC,MAAM,IAAK;AAAA,aACZ,KAAK,CAAC,MAAM,IAAK;AAC1B;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/index.ts
|
|
4
|
+
import WebSocket from "ws";
|
|
5
|
+
import { existsSync, mkdirSync, cpSync, readdirSync, symlinkSync, lstatSync, rmSync, readlinkSync } from "fs";
|
|
6
|
+
import { resolve, dirname, relative } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
var args = process.argv.slice(2);
|
|
9
|
+
var command = args[0] || "watch";
|
|
10
|
+
var port = args.find((a) => a.startsWith("--port="))?.split("=")[1] || "5173";
|
|
11
|
+
var host = args.find((a) => a.startsWith("--host="))?.split("=")[1] || "localhost";
|
|
12
|
+
var wsUrl = `ws://${host}:${port}/__annotask/ws`;
|
|
13
|
+
var apiUrl = `http://${host}:${port}/__annotask/api`;
|
|
14
|
+
var KNOWN_TARGETS = {
|
|
15
|
+
claude: ".claude/skills",
|
|
16
|
+
agents: ".agents/skills",
|
|
17
|
+
copilot: ".copilot/skills"
|
|
18
|
+
};
|
|
19
|
+
var DEFAULT_TARGETS = ["claude", "agents"];
|
|
20
|
+
function parseTargets() {
|
|
21
|
+
const targetArg = args.find((a) => a.startsWith("--target="));
|
|
22
|
+
if (targetArg) {
|
|
23
|
+
return targetArg.split("=")[1].split(",").map((t) => t.trim());
|
|
24
|
+
}
|
|
25
|
+
return DEFAULT_TARGETS;
|
|
26
|
+
}
|
|
27
|
+
if (command === "watch") {
|
|
28
|
+
watchChanges();
|
|
29
|
+
} else if (command === "report") {
|
|
30
|
+
fetchReport();
|
|
31
|
+
} else if (command === "status") {
|
|
32
|
+
checkStatus();
|
|
33
|
+
} else if (command === "init-skills") {
|
|
34
|
+
initSkills();
|
|
35
|
+
} else if (command === "help" || command === "--help") {
|
|
36
|
+
printHelp();
|
|
37
|
+
} else {
|
|
38
|
+
console.error(`Unknown command: ${command}`);
|
|
39
|
+
printHelp();
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
var MAX_RETRIES = 20;
|
|
43
|
+
function watchChanges() {
|
|
44
|
+
let attempt = 0;
|
|
45
|
+
let ws = null;
|
|
46
|
+
function connect() {
|
|
47
|
+
console.log(`\x1B[36m[Annotask]\x1B[0m ${attempt > 0 ? "Reconnecting" : "Connecting"} to ${wsUrl}...`);
|
|
48
|
+
ws = new WebSocket(wsUrl);
|
|
49
|
+
ws.on("open", () => {
|
|
50
|
+
attempt = 0;
|
|
51
|
+
console.log(`\x1B[32m[Annotask]\x1B[0m Connected. Watching for changes...
|
|
52
|
+
`);
|
|
53
|
+
});
|
|
54
|
+
ws.on("message", (raw) => {
|
|
55
|
+
try {
|
|
56
|
+
const msg = JSON.parse(raw.toString());
|
|
57
|
+
if (msg.event === "report:updated" && msg.data) {
|
|
58
|
+
const report = msg.data;
|
|
59
|
+
const count = report.changes?.length || 0;
|
|
60
|
+
console.log(`\x1B[33m\u2500\u2500 Report updated (${count} change${count === 1 ? "" : "s"}) \u2500\u2500\x1B[0m`);
|
|
61
|
+
for (const change of report.changes || []) {
|
|
62
|
+
const file = `\x1B[36m${change.file}:${change.line}\x1B[0m`;
|
|
63
|
+
const prop = `\x1B[33m${change.property}\x1B[0m`;
|
|
64
|
+
const before = `\x1B[31m${change.before || "(none)"}\x1B[0m`;
|
|
65
|
+
const after = `\x1B[32m${change.after}\x1B[0m`;
|
|
66
|
+
console.log(` ${file} ${prop}: ${before} \u2192 ${after}`);
|
|
67
|
+
}
|
|
68
|
+
console.log();
|
|
69
|
+
}
|
|
70
|
+
if (msg.event === "report:current" && msg.data) {
|
|
71
|
+
console.log(`\x1B[36m[Annotask]\x1B[0m Current report:`);
|
|
72
|
+
console.log(JSON.stringify(msg.data, null, 2));
|
|
73
|
+
console.log();
|
|
74
|
+
}
|
|
75
|
+
if (msg.event === "changes:cleared") {
|
|
76
|
+
console.log(`\x1B[36m[Annotask]\x1B[0m Changes cleared.
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
ws.on("close", () => {
|
|
83
|
+
ws = null;
|
|
84
|
+
retry("Disconnected");
|
|
85
|
+
});
|
|
86
|
+
ws.on("error", (err) => {
|
|
87
|
+
ws = null;
|
|
88
|
+
retry(`Connection failed: ${err.message}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function retry(reason) {
|
|
92
|
+
attempt++;
|
|
93
|
+
if (attempt > MAX_RETRIES) {
|
|
94
|
+
console.error(`\x1B[31m[Annotask]\x1B[0m ${reason}. Giving up after ${MAX_RETRIES} retries.`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const delay = Math.min(1e3 * Math.pow(2, attempt - 1), 3e4);
|
|
98
|
+
console.error(`\x1B[31m[Annotask]\x1B[0m ${reason}. Retrying in ${(delay / 1e3).toFixed(0)}s (attempt ${attempt}/${MAX_RETRIES})...`);
|
|
99
|
+
setTimeout(connect, delay);
|
|
100
|
+
}
|
|
101
|
+
connect();
|
|
102
|
+
process.on("SIGINT", () => {
|
|
103
|
+
if (ws) ws.close();
|
|
104
|
+
process.exit(0);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async function fetchReport() {
|
|
108
|
+
try {
|
|
109
|
+
const res = await fetch(`${apiUrl}/report`);
|
|
110
|
+
const data = await res.json();
|
|
111
|
+
console.log(JSON.stringify(data, null, 2));
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.error(`\x1B[31m[Annotask]\x1B[0m Failed to fetch report: ${err.message}`);
|
|
114
|
+
console.error(`Make sure your Vite dev server is running with the annotask() plugin on port ${port}`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function checkStatus() {
|
|
119
|
+
try {
|
|
120
|
+
const res = await fetch(`${apiUrl}/status`);
|
|
121
|
+
const data = await res.json();
|
|
122
|
+
console.log(`\x1B[32m[Annotask]\x1B[0m Server is running on port ${port}`);
|
|
123
|
+
console.log(JSON.stringify(data, null, 2));
|
|
124
|
+
} catch {
|
|
125
|
+
console.log(`\x1B[31m[Annotask]\x1B[0m No Annotask server found on port ${port}`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function initSkills() {
|
|
130
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
131
|
+
const srcSkills = resolve(__dirname, "..", "skills");
|
|
132
|
+
const force = args.includes("--force");
|
|
133
|
+
const targets = parseTargets();
|
|
134
|
+
if (!existsSync(srcSkills)) {
|
|
135
|
+
console.error(`\x1B[31m[Annotask]\x1B[0m Skills directory not found in package. Expected: ${srcSkills}`);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
const skillNames = readdirSync(srcSkills).filter(
|
|
139
|
+
(name) => existsSync(resolve(srcSkills, name, "SKILL.md"))
|
|
140
|
+
);
|
|
141
|
+
if (skillNames.length === 0) {
|
|
142
|
+
console.error(`\x1B[31m[Annotask]\x1B[0m No skills found in ${srcSkills}`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
const targetPaths = targets.map((t) => ({
|
|
146
|
+
name: t,
|
|
147
|
+
dir: resolve(process.cwd(), KNOWN_TARGETS[t] || t)
|
|
148
|
+
}));
|
|
149
|
+
const primary = targetPaths[0];
|
|
150
|
+
const secondaries = targetPaths.slice(1);
|
|
151
|
+
mkdirSync(primary.dir, { recursive: true });
|
|
152
|
+
let installed = 0;
|
|
153
|
+
let skipped = 0;
|
|
154
|
+
for (const skill of skillNames) {
|
|
155
|
+
const dest = resolve(primary.dir, skill);
|
|
156
|
+
if (existsSync(dest) && !isSymlink(dest)) {
|
|
157
|
+
if (force) {
|
|
158
|
+
cpSync(resolve(srcSkills, skill), dest, { recursive: true });
|
|
159
|
+
installed++;
|
|
160
|
+
} else {
|
|
161
|
+
console.log(` \x1B[33mskip\x1B[0m ${skill} \u2192 ${primary.name} (already exists)`);
|
|
162
|
+
skipped++;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
if (isSymlink(dest)) rmSync(dest, { recursive: true });
|
|
166
|
+
cpSync(resolve(srcSkills, skill), dest, { recursive: true });
|
|
167
|
+
installed++;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
console.log(`\x1B[32m[Annotask]\x1B[0m ${primary.name}: ${installed} installed, ${skipped} skipped`);
|
|
171
|
+
for (const target of secondaries) {
|
|
172
|
+
mkdirSync(target.dir, { recursive: true });
|
|
173
|
+
let linked = 0;
|
|
174
|
+
let linkSkipped = 0;
|
|
175
|
+
for (const skill of skillNames) {
|
|
176
|
+
const dest = resolve(target.dir, skill);
|
|
177
|
+
const linkTarget = relative(target.dir, resolve(primary.dir, skill));
|
|
178
|
+
if (existsSync(dest)) {
|
|
179
|
+
if (isSymlink(dest)) {
|
|
180
|
+
const existing = readlinkSync(dest);
|
|
181
|
+
if (existing === linkTarget && !force) {
|
|
182
|
+
linkSkipped++;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
rmSync(dest);
|
|
186
|
+
} else if (force) {
|
|
187
|
+
rmSync(dest, { recursive: true });
|
|
188
|
+
} else {
|
|
189
|
+
console.log(` \x1B[33mskip\x1B[0m ${skill} \u2192 ${target.name} (already exists, not a symlink)`);
|
|
190
|
+
linkSkipped++;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
symlinkSync(linkTarget, dest, "dir");
|
|
195
|
+
linked++;
|
|
196
|
+
}
|
|
197
|
+
console.log(`\x1B[32m[Annotask]\x1B[0m ${target.name}: ${linked} linked \u2192 ${primary.name}, ${linkSkipped} skipped`);
|
|
198
|
+
}
|
|
199
|
+
console.log();
|
|
200
|
+
for (const skill of skillNames) {
|
|
201
|
+
console.log(` \x1B[32m\u2713\x1B[0m /${skill}`);
|
|
202
|
+
}
|
|
203
|
+
if (secondaries.length > 0) {
|
|
204
|
+
console.log(`
|
|
205
|
+
Files in \x1B[36m${KNOWN_TARGETS[primary.name] || primary.name}\x1B[0m, symlinked from ${secondaries.map((t) => `\x1B[36m${KNOWN_TARGETS[t.name] || t.name}\x1B[0m`).join(", ")}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function isSymlink(p) {
|
|
209
|
+
try {
|
|
210
|
+
return lstatSync(p).isSymbolicLink();
|
|
211
|
+
} catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function printHelp() {
|
|
216
|
+
console.log(`
|
|
217
|
+
\x1B[36mAnnotask CLI\x1B[0m \u2014 interact with Annotask design tool from the terminal
|
|
218
|
+
|
|
219
|
+
\x1B[33mUsage:\x1B[0m
|
|
220
|
+
annotask <command> [options]
|
|
221
|
+
|
|
222
|
+
\x1B[33mCommands:\x1B[0m
|
|
223
|
+
watch Live stream of design changes (default)
|
|
224
|
+
report Fetch the current change report as JSON
|
|
225
|
+
status Check if Annotask server is running
|
|
226
|
+
init-skills Install AI agent skills to your project
|
|
227
|
+
help Show this help
|
|
228
|
+
|
|
229
|
+
\x1B[33mOptions:\x1B[0m
|
|
230
|
+
--port=N Vite dev server port (default: 5173)
|
|
231
|
+
--host=H Vite dev server host (default: localhost)
|
|
232
|
+
--force Overwrite existing skills (for init-skills)
|
|
233
|
+
--target=NAME Comma-separated targets (default: claude,agents)
|
|
234
|
+
Built-in: claude, agents, copilot
|
|
235
|
+
Custom: --target=.my-tool/skills
|
|
236
|
+
|
|
237
|
+
\x1B[33mExamples:\x1B[0m
|
|
238
|
+
annotask watch # Watch live changes
|
|
239
|
+
annotask watch --port=3000 # Watch on custom port
|
|
240
|
+
annotask report # Get current report JSON
|
|
241
|
+
annotask report | jq # Pipe to jq for formatting
|
|
242
|
+
annotask status # Check connection
|
|
243
|
+
annotask init-skills # Install to .claude + .agents (default)
|
|
244
|
+
annotask init-skills --target=claude # Only .claude/skills/
|
|
245
|
+
annotask init-skills --target=copilot # Only .copilot/skills/
|
|
246
|
+
annotask init-skills --target=claude,agent,copilot # All three
|
|
247
|
+
`);
|
|
248
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
interface AnnotaskOptions {
|
|
4
|
+
/** @experimental Not yet implemented. OpenAPI spec path or URL */
|
|
5
|
+
openapi?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function annotask(options?: AnnotaskOptions): Plugin[];
|
|
8
|
+
|
|
9
|
+
export { type AnnotaskOptions, annotask, annotask as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bridgeClientScript,
|
|
3
|
+
toggleButtonScript
|
|
4
|
+
} from "./chunk-2TUWBFQG.js";
|
|
5
|
+
import {
|
|
6
|
+
writeServerInfo
|
|
7
|
+
} from "./chunk-XR26XVHT.js";
|
|
8
|
+
import {
|
|
9
|
+
createAnnotaskServer
|
|
10
|
+
} from "./chunk-T6TKVAAA.js";
|
|
11
|
+
import {
|
|
12
|
+
transformFile,
|
|
13
|
+
transformHTML
|
|
14
|
+
} from "./chunk-6UQW2W7S.js";
|
|
15
|
+
|
|
16
|
+
// src/plugin/index.ts
|
|
17
|
+
function annotask(options = {}) {
|
|
18
|
+
let projectRoot = "";
|
|
19
|
+
const transformPlugin = {
|
|
20
|
+
name: "annotask:transform",
|
|
21
|
+
enforce: "pre",
|
|
22
|
+
apply: "serve",
|
|
23
|
+
configResolved(config) {
|
|
24
|
+
projectRoot = config.root;
|
|
25
|
+
},
|
|
26
|
+
transform(code, id) {
|
|
27
|
+
if (id.endsWith("/main.ts") || id.endsWith("/main.js") || id.endsWith("/main.tsx") || id.endsWith("/main.jsx")) {
|
|
28
|
+
let injection = "";
|
|
29
|
+
if (code.includes("from 'vue'") || code.includes('from "vue"')) {
|
|
30
|
+
injection = `
|
|
31
|
+
;import { createApp as __uf_createApp, h as __uf_h } from 'vue';
|
|
32
|
+
window.__ANNOTASK_VUE__ = { createApp: __uf_createApp, h: __uf_h };
|
|
33
|
+
`;
|
|
34
|
+
} else if (code.includes("from 'react'") || code.includes('from "react"')) {
|
|
35
|
+
injection = `
|
|
36
|
+
;import { createElement as __uf_createElement } from 'react';
|
|
37
|
+
import { createRoot as __uf_createRoot } from 'react-dom/client';
|
|
38
|
+
window.__ANNOTASK_REACT__ = { createElement: __uf_createElement, createRoot: __uf_createRoot };
|
|
39
|
+
`;
|
|
40
|
+
} else if (code.includes("from 'svelte'") || code.includes('from "svelte"')) {
|
|
41
|
+
injection = `
|
|
42
|
+
;import { mount as __uf_mount, unmount as __uf_unmount } from 'svelte';
|
|
43
|
+
window.__ANNOTASK_SVELTE__ = { mount: __uf_mount, unmount: __uf_unmount };
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
if (injection) {
|
|
47
|
+
return { code: code + injection, map: null };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!id.endsWith(".vue") && !id.endsWith(".svelte") && !/\.[jt]sx$/.test(id)) return null;
|
|
51
|
+
const result = transformFile(code, id, projectRoot);
|
|
52
|
+
if (!result) return null;
|
|
53
|
+
let output = result;
|
|
54
|
+
const importRegex = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g;
|
|
55
|
+
let match;
|
|
56
|
+
const registrations = [];
|
|
57
|
+
while ((match = importRegex.exec(result)) !== null) {
|
|
58
|
+
const [, name, source] = match;
|
|
59
|
+
if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase() && !source.startsWith(".")) {
|
|
60
|
+
registrations.push(`window.__ANNOTASK_COMPONENTS__['${name}'] = ${name}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (registrations.length > 0) {
|
|
64
|
+
const regCode = `
|
|
65
|
+
if (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__ANNOTASK_COMPONENTS__ || {}; ${registrations.join("; ")} }
|
|
66
|
+
`;
|
|
67
|
+
if (id.endsWith(".vue") && output.includes("</script>")) {
|
|
68
|
+
output = output.replace(/<\/script>/, regCode + "</script>");
|
|
69
|
+
} else {
|
|
70
|
+
output += regCode;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { code: output, map: null };
|
|
74
|
+
},
|
|
75
|
+
transformIndexHtml(html, ctx) {
|
|
76
|
+
const transformed = transformHTML(html, ctx.filename, projectRoot);
|
|
77
|
+
return {
|
|
78
|
+
html: transformed ?? html,
|
|
79
|
+
tags: [
|
|
80
|
+
{
|
|
81
|
+
tag: "script",
|
|
82
|
+
attrs: { type: "module" },
|
|
83
|
+
children: toggleButtonScript(),
|
|
84
|
+
injectTo: "body"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
tag: "script",
|
|
88
|
+
children: bridgeClientScript(),
|
|
89
|
+
injectTo: "body"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const servePlugin = {
|
|
96
|
+
name: "annotask:serve",
|
|
97
|
+
apply: "serve",
|
|
98
|
+
configureServer(server) {
|
|
99
|
+
const uiServer = createAnnotaskServer({ projectRoot });
|
|
100
|
+
server.middlewares.use(uiServer.middleware);
|
|
101
|
+
server.httpServer?.on("upgrade", (req, socket, head) => {
|
|
102
|
+
if (req.url === "/__annotask/ws") {
|
|
103
|
+
uiServer.handleUpgrade(req, socket, head);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
server.httpServer?.once("listening", () => {
|
|
107
|
+
const addr = server.httpServer?.address();
|
|
108
|
+
const port = typeof addr === "object" && addr ? addr.port : 5173;
|
|
109
|
+
writeServerInfo(projectRoot, port);
|
|
110
|
+
});
|
|
111
|
+
console.log("[Annotask] Design tool available at /__annotask/");
|
|
112
|
+
console.log("[Annotask] WebSocket: ws://localhost:<port>/__annotask/ws");
|
|
113
|
+
console.log("[Annotask] API: http://localhost:<port>/__annotask/api/report");
|
|
114
|
+
server.middlewares.use((req, res, next) => {
|
|
115
|
+
if (req.url?.startsWith("/__annotask")) return next();
|
|
116
|
+
const _end = res.end;
|
|
117
|
+
const _write = res.write;
|
|
118
|
+
const _writeHead = res.writeHead;
|
|
119
|
+
const chunks = [];
|
|
120
|
+
let isHtml = false;
|
|
121
|
+
let decided = false;
|
|
122
|
+
res.writeHead = function(statusCode, ...rest) {
|
|
123
|
+
if (!decided) {
|
|
124
|
+
decided = true;
|
|
125
|
+
const headers = rest.find((a) => typeof a === "object" && a !== null);
|
|
126
|
+
if (headers) {
|
|
127
|
+
const ct = headers["content-type"] || headers["Content-Type"];
|
|
128
|
+
if (typeof ct === "string") isHtml = ct.includes("text/html");
|
|
129
|
+
}
|
|
130
|
+
if (!isHtml) {
|
|
131
|
+
const ct = res.getHeader("content-type");
|
|
132
|
+
if (typeof ct === "string") isHtml = ct.includes("text/html");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return _writeHead.apply(res, [statusCode, ...rest]);
|
|
136
|
+
};
|
|
137
|
+
res.write = function(chunk, ...args) {
|
|
138
|
+
if (isHtml) {
|
|
139
|
+
if (chunk != null) chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString());
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return _write.apply(res, [chunk, ...args]);
|
|
143
|
+
};
|
|
144
|
+
res.end = function(chunk, ...args) {
|
|
145
|
+
if (isHtml) {
|
|
146
|
+
if (chunk != null && chunk !== "") chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString());
|
|
147
|
+
if (chunks.length > 0) {
|
|
148
|
+
let body = chunks.join("");
|
|
149
|
+
if (body.includes("</body>") && !body.includes("__ANNOTASK_BRIDGE__")) {
|
|
150
|
+
const scripts = `<script type="module">${toggleButtonScript()}</script>
|
|
151
|
+
<script>${bridgeClientScript()}</script>
|
|
152
|
+
`;
|
|
153
|
+
body = body.replace("</body>", scripts + "</body>");
|
|
154
|
+
}
|
|
155
|
+
return _end.call(res, body);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return _end.apply(res, [chunk, ...args]);
|
|
159
|
+
};
|
|
160
|
+
next();
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return [transformPlugin, servePlugin];
|
|
165
|
+
}
|
|
166
|
+
var plugin_default = annotask;
|
|
167
|
+
export {
|
|
168
|
+
annotask,
|
|
169
|
+
plugin_default as default
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin/index.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport { transformFile, transformHTML } from './transform.js'\nimport { toggleButtonScript } from './toggle-button.js'\nimport { bridgeClientScript } from './bridge-client.js'\nimport { createAnnotaskServer } from '../server/index.js'\nimport { writeServerInfo } from '../server/discovery.js'\n\nexport interface AnnotaskOptions {\n /** @experimental Not yet implemented. OpenAPI spec path or URL */\n openapi?: string\n}\n\nexport function annotask(options: AnnotaskOptions = {}): Plugin[] {\n let projectRoot = ''\n\n const transformPlugin: Plugin = {\n name: 'annotask:transform',\n enforce: 'pre',\n apply: 'serve',\n\n configResolved(config) {\n projectRoot = config.root\n },\n\n transform(code, id) {\n // Expose framework runtime for Annotask component rendering\n if (id.endsWith('/main.ts') || id.endsWith('/main.js') || id.endsWith('/main.tsx') || id.endsWith('/main.jsx')) {\n let injection = ''\n if (code.includes(\"from 'vue'\") || code.includes('from \"vue\"')) {\n injection = `\\n;import { createApp as __uf_createApp, h as __uf_h } from 'vue';\\nwindow.__ANNOTASK_VUE__ = { createApp: __uf_createApp, h: __uf_h };\\n`\n } else if (code.includes(\"from 'react'\") || code.includes('from \"react\"')) {\n injection = `\\n;import { createElement as __uf_createElement } from 'react';\\nimport { createRoot as __uf_createRoot } from 'react-dom/client';\\nwindow.__ANNOTASK_REACT__ = { createElement: __uf_createElement, createRoot: __uf_createRoot };\\n`\n } else if (code.includes(\"from 'svelte'\") || code.includes('from \"svelte\"')) {\n injection = `\\n;import { mount as __uf_mount, unmount as __uf_unmount } from 'svelte';\\nwindow.__ANNOTASK_SVELTE__ = { mount: __uf_mount, unmount: __uf_unmount };\\n`\n }\n if (injection) {\n return { code: code + injection, map: null }\n }\n }\n\n // Transform source files to inject data-annotask-* attributes\n // Note: .astro files are excluded because Astro's compiler runs before\n // our transform (even with enforce: 'pre'). Astro source mapping is\n // handled via data-astro-source-* attributes in the bridge client.\n if (!id.endsWith('.vue') && !id.endsWith('.svelte') && !/\\.[jt]sx$/.test(id)) return null\n\n const result = transformFile(code, id, projectRoot)\n if (!result) return null\n\n // Register imported PascalCase components globally\n let output = result\n const importRegex = /import\\s+(\\w+)\\s+from\\s+['\"]([^'\"]+)['\"]/g\n let match\n const registrations: string[] = []\n while ((match = importRegex.exec(result)) !== null) {\n const [, name, source] = match\n if (name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase() && !source.startsWith('.')) {\n registrations.push(`window.__ANNOTASK_COMPONENTS__['${name}'] = ${name}`)\n }\n }\n if (registrations.length > 0) {\n const regCode = `\\nif (typeof window !== 'undefined') { window.__ANNOTASK_COMPONENTS__ = window.__ANNOTASK_COMPONENTS__ || {}; ${registrations.join('; ')} }\\n`\n // Vue SFCs: inject before </script>. JSX/Svelte: append to end of file.\n if (id.endsWith('.vue') && output.includes('</script>')) {\n output = output.replace(/<\\/script>/, regCode + '</script>')\n } else {\n output += regCode\n }\n }\n\n return { code: output, map: null }\n },\n\n transformIndexHtml(html, ctx) {\n const transformed = transformHTML(html, ctx.filename, projectRoot)\n return {\n html: transformed ?? html,\n tags: [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: toggleButtonScript(),\n injectTo: 'body',\n },\n {\n tag: 'script',\n children: bridgeClientScript(),\n injectTo: 'body',\n },\n ],\n }\n },\n }\n\n const servePlugin: Plugin = {\n name: 'annotask:serve',\n apply: 'serve',\n\n configureServer(server: ViteDevServer) {\n const uiServer = createAnnotaskServer({ projectRoot })\n\n // Mount middleware on Vite's connect instance\n server.middlewares.use(uiServer.middleware)\n\n // Handle WebSocket upgrades\n server.httpServer?.on('upgrade', (req, socket, head) => {\n if (req.url === '/__annotask/ws') {\n uiServer.handleUpgrade(req, socket, head)\n }\n })\n\n // Write server.json so skills/CLI know where to connect\n server.httpServer?.once('listening', () => {\n const addr = server.httpServer?.address()\n const port = typeof addr === 'object' && addr ? addr.port : 5173\n writeServerInfo(projectRoot, port)\n })\n\n console.log('[Annotask] Design tool available at /__annotask/')\n console.log('[Annotask] WebSocket: ws://localhost:<port>/__annotask/ws')\n console.log('[Annotask] API: http://localhost:<port>/__annotask/api/report')\n\n // Inject bridge scripts into SSR HTML responses (Astro, etc.)\n // Sniffs content-type from writeHead, buffers only HTML responses,\n // and injects scripts before </body>.\n server.middlewares.use((req: any, res: any, next: any) => {\n if (req.url?.startsWith('/__annotask')) return next()\n\n const _end = res.end\n const _write = res.write\n const _writeHead = res.writeHead\n const chunks: string[] = []\n let isHtml = false\n let decided = false\n\n res.writeHead = function (statusCode: any, ...rest: any[]) {\n if (!decided) {\n decided = true\n const headers = rest.find((a: any) => typeof a === 'object' && a !== null)\n if (headers) {\n const ct = headers['content-type'] || headers['Content-Type']\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n if (!isHtml) {\n const ct = res.getHeader('content-type')\n if (typeof ct === 'string') isHtml = ct.includes('text/html')\n }\n }\n return _writeHead.apply(res, [statusCode, ...rest])\n }\n\n res.write = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null) chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n return true\n }\n return _write.apply(res, [chunk, ...args] as any)\n }\n\n res.end = function (chunk: any, ...args: any[]) {\n if (isHtml) {\n if (chunk != null && chunk !== '') chunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString())\n if (chunks.length > 0) {\n let body = chunks.join('')\n if (body.includes('</body>') && !body.includes('__ANNOTASK_BRIDGE__')) {\n const scripts = `<script type=\"module\">${toggleButtonScript()}</script>\\n<script>${bridgeClientScript()}</script>\\n`\n body = body.replace('</body>', scripts + '</body>')\n }\n return _end.call(res, body)\n }\n }\n return _end.apply(res, [chunk, ...args] as any)\n }\n\n next()\n })\n },\n }\n\n return [transformPlugin, servePlugin]\n}\n\nexport default annotask\n"],"mappings":"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","names":[]}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { Duplex } from 'node:stream';
|
|
3
|
+
import { WebSocket } from 'ws';
|
|
4
|
+
|
|
5
|
+
interface ProjectState {
|
|
6
|
+
getDesignSpec: () => unknown;
|
|
7
|
+
getConfig: () => unknown;
|
|
8
|
+
getTasks: () => {
|
|
9
|
+
version: string;
|
|
10
|
+
tasks: any[];
|
|
11
|
+
};
|
|
12
|
+
addTask: (task: Record<string, unknown>) => unknown;
|
|
13
|
+
updateTask: (id: string, updates: Record<string, unknown>) => unknown;
|
|
14
|
+
dispose: () => void;
|
|
15
|
+
}
|
|
16
|
+
declare function createProjectState(projectRoot: string, broadcast: (event: string, data: unknown) => void): ProjectState;
|
|
17
|
+
|
|
18
|
+
interface AnnotaskWSServer {
|
|
19
|
+
handleUpgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => void;
|
|
20
|
+
broadcast: (event: string, data: unknown) => void;
|
|
21
|
+
getReport: () => unknown;
|
|
22
|
+
clients: Set<WebSocket>;
|
|
23
|
+
}
|
|
24
|
+
declare function createWSServer(): AnnotaskWSServer;
|
|
25
|
+
|
|
26
|
+
interface APIOptions {
|
|
27
|
+
getReport: () => unknown;
|
|
28
|
+
getConfig: () => unknown;
|
|
29
|
+
getDesignSpec: () => unknown;
|
|
30
|
+
getTasks: () => unknown;
|
|
31
|
+
updateTask: (id: string, updates: Record<string, unknown>) => unknown;
|
|
32
|
+
addTask: (task: Record<string, unknown>) => unknown;
|
|
33
|
+
}
|
|
34
|
+
declare function createAPIMiddleware(options: APIOptions): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
|
|
35
|
+
|
|
36
|
+
declare function createShellMiddleware(): (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
|
|
37
|
+
|
|
38
|
+
interface AnnotaskServer {
|
|
39
|
+
middleware: (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
|
|
40
|
+
handleUpgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => void;
|
|
41
|
+
broadcast: (event: string, data: unknown) => void;
|
|
42
|
+
getReport: () => unknown;
|
|
43
|
+
dispose: () => void;
|
|
44
|
+
}
|
|
45
|
+
interface AnnotaskServerOptions {
|
|
46
|
+
projectRoot: string;
|
|
47
|
+
}
|
|
48
|
+
declare function createAnnotaskServer(options: AnnotaskServerOptions): AnnotaskServer;
|
|
49
|
+
|
|
50
|
+
export { type APIOptions, type AnnotaskServer, type AnnotaskServerOptions, type AnnotaskWSServer, type ProjectState, createAPIMiddleware, createAnnotaskServer, createProjectState, createShellMiddleware, createWSServer };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAPIMiddleware,
|
|
3
|
+
createAnnotaskServer,
|
|
4
|
+
createProjectState,
|
|
5
|
+
createShellMiddleware,
|
|
6
|
+
createWSServer
|
|
7
|
+
} from "./chunk-T6TKVAAA.js";
|
|
8
|
+
export {
|
|
9
|
+
createAPIMiddleware,
|
|
10
|
+
createAnnotaskServer,
|
|
11
|
+
createProjectState,
|
|
12
|
+
createShellMiddleware,
|
|
13
|
+
createWSServer
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|