@bastani/atomic 0.8.20-0 → 0.8.21-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/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +5 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +5 -0
- package/dist/builtin/subagents/agents/code-simplifier.md +78 -22
- package/dist/builtin/subagents/agents/debugger.md +4 -3
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +5 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +25 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/create-spec/SKILL.md +169 -125
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +89 -80
- package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +92 -0
- package/dist/builtin/workflows/skills/impeccable/agents/impeccable_manual_edit_applier.toml +95 -0
- package/dist/builtin/workflows/skills/impeccable/agents/openai.yaml +4 -0
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +122 -1
- package/dist/builtin/workflows/skills/impeccable/reference/animate.md +38 -12
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +5 -5
- package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +7 -7
- package/dist/builtin/workflows/skills/impeccable/reference/brand.md +4 -14
- package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +115 -1
- package/dist/builtin/workflows/skills/impeccable/reference/codex.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +109 -6
- package/dist/builtin/workflows/skills/impeccable/reference/craft.md +7 -7
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +623 -94
- package/dist/builtin/workflows/skills/impeccable/reference/delight.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/distill.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/document.md +16 -14
- package/dist/builtin/workflows/skills/impeccable/reference/extract.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/harden.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/init.md +172 -0
- package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +0 -6
- package/dist/builtin/workflows/skills/impeccable/reference/layout.md +33 -13
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +96 -19
- package/dist/builtin/workflows/skills/impeccable/reference/onboard.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/polish.md +3 -4
- package/dist/builtin/workflows/skills/impeccable/reference/product.md +1 -3
- package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/shape.md +5 -5
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +158 -3
- package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +225 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +266 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +17 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/design-parser.mjs +16 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detect.mjs +21 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1725 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +244 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +4543 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/findings.mjs +12 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +198 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +2316 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/constants.mjs +101 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +17 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/is-generated.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +139 -96
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +4491 -526
- package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-event-validation.mjs +136 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +22 -9
- package/dist/builtin/workflows/skills/impeccable/scripts/live-insert-ui.mjs +458 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +232 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +288 -110
- package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +47 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +1443 -100
- package/dist/builtin/workflows/skills/impeccable/scripts/live-session-store.mjs +17 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +17 -3
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +216 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +2 -3
- package/dist/builtin/workflows/skills/impeccable/scripts/palette.mjs +633 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +1 -1
- package/dist/builtin/workflows/src/extension/index.ts +67 -3
- package/dist/builtin/workflows/src/extension/render-result.ts +26 -1
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +227 -3
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +94 -7
- package/dist/builtin/workflows/src/shared/stage-prompt.ts +326 -0
- package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +62 -7
- package/dist/builtin/workflows/src/shared/store-types.ts +43 -0
- package/dist/builtin/workflows/src/shared/store.ts +37 -0
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -4
- package/dist/builtin/workflows/src/tui/graph-view.ts +47 -0
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +43 -1
- package/dist/builtin/workflows/src/tui/run-detail.ts +10 -4
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +117 -15
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +9 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +2 -5
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +11 -29
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/docs/quickstart.md +1 -2
- package/package.json +4 -4
- package/dist/builtin/workflows/skills/impeccable/reference/cognitive-load.md +0 -106
- package/dist/builtin/workflows/skills/impeccable/reference/color-and-contrast.md +0 -105
- package/dist/builtin/workflows/skills/impeccable/reference/heuristics-scoring.md +0 -234
- package/dist/builtin/workflows/skills/impeccable/reference/motion-design.md +0 -109
- package/dist/builtin/workflows/skills/impeccable/reference/personas.md +0 -179
- package/dist/builtin/workflows/skills/impeccable/reference/responsive-design.md +0 -114
- package/dist/builtin/workflows/skills/impeccable/reference/spatial-design.md +0 -100
- package/dist/builtin/workflows/skills/impeccable/reference/teach.md +0 -156
- package/dist/builtin/workflows/skills/impeccable/reference/typography.md +0 -159
- package/dist/builtin/workflows/skills/impeccable/reference/ux-writing.md +0 -107
- package/dist/builtin/workflows/skills/impeccable/scripts/load-context.mjs +0 -141
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI helper: discard pending manual edits from the buffer without applying.
|
|
4
|
+
*
|
|
5
|
+
* Reads .impeccable/live/pending-manual-edits.json, drops entries, writes back.
|
|
6
|
+
* No source-file writes. Use this when the user wants to throw away unsaved
|
|
7
|
+
* manual edits.
|
|
8
|
+
*
|
|
9
|
+
* Trigger: only when the user explicitly asks the AI to discard / throw away /
|
|
10
|
+
* clear pending manual edits.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* node live-discard-manual-edits.mjs # discard all pending
|
|
14
|
+
* node live-discard-manual-edits.mjs --page-url=/ # discard only entries for "/"
|
|
15
|
+
*
|
|
16
|
+
* Output JSON: { discarded: N, entries: [...discardedEntries], totalCount: N }
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readBuffer, removeEntries, truncateBuffer } from './live-manual-edits-buffer.mjs';
|
|
20
|
+
|
|
21
|
+
function argVal(args, name) {
|
|
22
|
+
const prefix = name + '=';
|
|
23
|
+
for (const a of args) {
|
|
24
|
+
if (a === name) return true;
|
|
25
|
+
if (a.startsWith(prefix)) return a.slice(prefix.length);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
32
|
+
console.log('Usage: node live-discard-manual-edits.mjs [--page-url=<url>]');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const pageUrlFilter = argVal(args, '--page-url');
|
|
37
|
+
const cwd = process.cwd();
|
|
38
|
+
|
|
39
|
+
let discarded;
|
|
40
|
+
let entries;
|
|
41
|
+
const buffer = readBuffer(cwd);
|
|
42
|
+
if (pageUrlFilter) {
|
|
43
|
+
entries = buffer.entries.filter((entry) => entry.pageUrl === pageUrlFilter);
|
|
44
|
+
discarded = removeEntries(cwd, (entry) => entry.pageUrl === pageUrlFilter);
|
|
45
|
+
} else {
|
|
46
|
+
entries = buffer.entries;
|
|
47
|
+
discarded = truncateBuffer(cwd);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const remaining = readBuffer(cwd).entries.reduce((n, e) => n + e.ops.length, 0);
|
|
51
|
+
console.log(JSON.stringify({ discarded, entries, totalCount: remaining }));
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared event validation for the live helper server.
|
|
3
|
+
* Extracted for unit testing (insert mode rules).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { canCreateInsert } from './live-insert-ui.mjs';
|
|
7
|
+
|
|
8
|
+
export const VISUAL_ACTIONS = [
|
|
9
|
+
'impeccable', 'bolder', 'quieter', 'distill', 'polish', 'typeset',
|
|
10
|
+
'colorize', 'layout', 'adapt', 'animate', 'delight', 'overdrive',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const ID_PATTERN = /^[0-9a-f]{8}$/;
|
|
14
|
+
const VARIANT_ID_PATTERN = /^[0-9]{1,3}$/;
|
|
15
|
+
const INSERT_POSITIONS = new Set(['before', 'after']);
|
|
16
|
+
const FORBIDDEN_MANUAL_EDIT_TEXT_CHARS = ['<', '{', '}', '`'];
|
|
17
|
+
|
|
18
|
+
function isValidId(v) { return typeof v === 'string' && ID_PATTERN.test(v); }
|
|
19
|
+
function isValidVariantId(v) { return typeof v === 'string' && VARIANT_ID_PATTERN.test(v); }
|
|
20
|
+
|
|
21
|
+
function validateManualEditText(newText) {
|
|
22
|
+
if (typeof newText !== 'string') return null;
|
|
23
|
+
const hits = FORBIDDEN_MANUAL_EDIT_TEXT_CHARS.filter((char) => newText.includes(char));
|
|
24
|
+
return hits.length > 0 ? hits : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function validateAnnotationFields(msg) {
|
|
28
|
+
if (msg.screenshotPath !== undefined && typeof msg.screenshotPath !== 'string') {
|
|
29
|
+
return 'generate: screenshotPath must be string';
|
|
30
|
+
}
|
|
31
|
+
if (msg.comments !== undefined && !Array.isArray(msg.comments)) {
|
|
32
|
+
return 'generate: comments must be array';
|
|
33
|
+
}
|
|
34
|
+
if (msg.strokes !== undefined && !Array.isArray(msg.strokes)) {
|
|
35
|
+
return 'generate: strokes must be array';
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function validateInsertGenerate(msg) {
|
|
41
|
+
if (!msg.insert || typeof msg.insert !== 'object') return 'generate: insert mode requires insert object';
|
|
42
|
+
if (!INSERT_POSITIONS.has(msg.insert.position)) return 'generate: insert.position must be before or after';
|
|
43
|
+
const anchor = msg.insert.anchor;
|
|
44
|
+
if (!anchor || typeof anchor !== 'object') return 'generate: insert.anchor required';
|
|
45
|
+
if (!anchor.tagName && !anchor.outerHTML && !(Array.isArray(anchor.classes) && anchor.classes.length)) {
|
|
46
|
+
return 'generate: insert.anchor needs tagName, classes, or outerHTML';
|
|
47
|
+
}
|
|
48
|
+
if (!msg.placeholder || typeof msg.placeholder !== 'object') return 'generate: insert mode requires placeholder dimensions';
|
|
49
|
+
if (!Number.isFinite(msg.placeholder.width) || !Number.isFinite(msg.placeholder.height)) {
|
|
50
|
+
return 'generate: placeholder width and height must be numbers';
|
|
51
|
+
}
|
|
52
|
+
if (!canCreateInsert({
|
|
53
|
+
prompt: msg.freeformPrompt,
|
|
54
|
+
comments: msg.comments,
|
|
55
|
+
strokes: msg.strokes,
|
|
56
|
+
})) {
|
|
57
|
+
return 'generate: insert requires freeformPrompt or annotations';
|
|
58
|
+
}
|
|
59
|
+
return validateAnnotationFields(msg);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function validateReplaceGenerate(msg) {
|
|
63
|
+
if (!msg.action || !VISUAL_ACTIONS.includes(msg.action)) return 'generate: invalid action';
|
|
64
|
+
if (!msg.element || !msg.element.outerHTML) return 'generate: missing element context';
|
|
65
|
+
return validateAnnotationFields(msg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function validateManualEditEvent(msg, label) {
|
|
69
|
+
if (!isValidId(msg.id)) return label + ': missing or malformed id';
|
|
70
|
+
if (!msg.pageUrl || typeof msg.pageUrl !== 'string') return label + ': missing pageUrl';
|
|
71
|
+
if (!msg.element || typeof msg.element !== 'object') return label + ': missing element';
|
|
72
|
+
if (!Array.isArray(msg.ops) || msg.ops.length === 0) return label + ': ops must be non-empty array';
|
|
73
|
+
if (msg.ops.length > 100) return label + ': too many ops (max 100)';
|
|
74
|
+
for (const op of msg.ops) {
|
|
75
|
+
if (typeof op.ref !== 'string') return label + ': op.ref required';
|
|
76
|
+
if (typeof op.tag !== 'string') return label + ': op.tag required';
|
|
77
|
+
if (typeof op.originalText !== 'string') return label + ': op.originalText required';
|
|
78
|
+
if (op.deleted !== true && typeof op.newText !== 'string') {
|
|
79
|
+
return label + ': text op requires newText';
|
|
80
|
+
}
|
|
81
|
+
if (typeof op.newText === 'string') {
|
|
82
|
+
if (op.deleted !== true && op.newText.trim().length === 0) {
|
|
83
|
+
return label + ': newText cannot be empty';
|
|
84
|
+
}
|
|
85
|
+
const forbidden = validateManualEditText(op.newText);
|
|
86
|
+
if (forbidden) {
|
|
87
|
+
return label + ': newText cannot contain ' + forbidden.join(' ') + ' (plain text only; ask the AI to insert markup)';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function validateEvent(msg) {
|
|
95
|
+
if (!msg || typeof msg !== 'object' || !msg.type) return 'Missing or invalid message';
|
|
96
|
+
switch (msg.type) {
|
|
97
|
+
case 'generate':
|
|
98
|
+
if (!isValidId(msg.id)) return 'generate: missing or malformed id';
|
|
99
|
+
if (!Number.isInteger(msg.count) || msg.count < 1 || msg.count > 8) return 'generate: count must be 1-8';
|
|
100
|
+
if (msg.mode === 'insert') return validateInsertGenerate(msg);
|
|
101
|
+
return validateReplaceGenerate(msg);
|
|
102
|
+
case 'accept':
|
|
103
|
+
if (!isValidId(msg.id)) return 'accept: missing or malformed id';
|
|
104
|
+
if (!isValidVariantId(msg.variantId)) return 'accept: missing or malformed variantId';
|
|
105
|
+
if (msg.paramValues !== undefined) {
|
|
106
|
+
if (typeof msg.paramValues !== 'object' || msg.paramValues === null || Array.isArray(msg.paramValues)) {
|
|
107
|
+
return 'accept: paramValues must be an object';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
case 'discard':
|
|
112
|
+
return isValidId(msg.id) ? null : 'discard: missing or malformed id';
|
|
113
|
+
case 'checkpoint':
|
|
114
|
+
if (!isValidId(msg.id)) return 'checkpoint: missing or malformed id';
|
|
115
|
+
if (!Number.isInteger(msg.revision) || msg.revision < 0) return 'checkpoint: revision must be a non-negative integer';
|
|
116
|
+
if (msg.paramValues !== undefined && (typeof msg.paramValues !== 'object' || msg.paramValues === null || Array.isArray(msg.paramValues))) {
|
|
117
|
+
return 'checkpoint: paramValues must be an object';
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
case 'exit':
|
|
121
|
+
return null;
|
|
122
|
+
case 'prefetch':
|
|
123
|
+
if (!msg.pageUrl || typeof msg.pageUrl !== 'string') return 'prefetch: missing pageUrl';
|
|
124
|
+
return null;
|
|
125
|
+
case 'manual_edits':
|
|
126
|
+
return validateManualEditEvent(msg, 'manual_edits');
|
|
127
|
+
case 'steer':
|
|
128
|
+
if (!isValidId(msg.id)) return 'steer: missing or malformed id';
|
|
129
|
+
if (typeof msg.message !== 'string' || !msg.message.trim()) return 'steer: message required';
|
|
130
|
+
if (msg.message.length > 4000) return 'steer: message too long';
|
|
131
|
+
if (msg.pageUrl !== undefined && typeof msg.pageUrl !== 'string') return 'steer: pageUrl must be string';
|
|
132
|
+
return null;
|
|
133
|
+
default:
|
|
134
|
+
return 'Unknown event type: ' + msg.type;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -116,7 +116,7 @@ Output (JSON):
|
|
|
116
116
|
if (!fs.existsSync(absFile)) return { file: relFile, error: 'file_not_found' };
|
|
117
117
|
const content = fs.readFileSync(absFile, 'utf-8');
|
|
118
118
|
const withoutOld = revertCspMeta(removeTag(content, config.commentSyntax));
|
|
119
|
-
const withTag = insertTag(withoutOld, config, port);
|
|
119
|
+
const withTag = insertTag(withoutOld, config, port, relFile);
|
|
120
120
|
if (withTag === withoutOld) {
|
|
121
121
|
return { file: relFile, error: 'insertion_point_not_found', anchor: config.insertBefore || config.insertAfter };
|
|
122
122
|
}
|
|
@@ -256,18 +256,22 @@ function validateConfig(cfg) {
|
|
|
256
256
|
function commentOpen(syntax) { return syntax === 'jsx' ? '{/*' : '<!--'; }
|
|
257
257
|
function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; }
|
|
258
258
|
|
|
259
|
-
function buildTagBlock(syntax, port) {
|
|
259
|
+
function buildTagBlock(syntax, port, filePath) {
|
|
260
260
|
const open = commentOpen(syntax);
|
|
261
261
|
const close = commentClose(syntax);
|
|
262
|
+
// Astro processes <script> tags by default and rewrites src to its own
|
|
263
|
+
// bundled URL. is:inline opts out so the literal external src survives.
|
|
264
|
+
const isAstro = typeof filePath === 'string' && filePath.endsWith('.astro');
|
|
265
|
+
const scriptAttrs = isAstro ? 'is:inline ' : '';
|
|
262
266
|
return (
|
|
263
267
|
open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' +
|
|
264
|
-
'<script src="http://localhost:' + port + '/live.js"></script>\n' +
|
|
268
|
+
'<script ' + scriptAttrs + 'src="http://localhost:' + port + '/live.js"></script>\n' +
|
|
265
269
|
open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n'
|
|
266
270
|
);
|
|
267
271
|
}
|
|
268
272
|
|
|
269
|
-
function insertTag(content, config, port) {
|
|
270
|
-
const block = buildTagBlock(config.commentSyntax, port);
|
|
273
|
+
function insertTag(content, config, port, filePath) {
|
|
274
|
+
const block = buildTagBlock(config.commentSyntax, port, filePath);
|
|
271
275
|
// insertBefore: match the LAST occurrence. Anchors like `</body>` naturally
|
|
272
276
|
// belong at the end, and the same literal can appear earlier in code blocks
|
|
273
277
|
// within rendered documentation pages.
|
|
@@ -299,12 +303,21 @@ function insertTag(content, config, port) {
|
|
|
299
303
|
*/
|
|
300
304
|
function removeTag(content, _syntax) {
|
|
301
305
|
const patterns = [
|
|
302
|
-
/([ \t]*)<!--\s*impeccable-live-start\s*-->[\s\S]*?<!--\s*impeccable-live-end\s*-->[ \t]
|
|
303
|
-
/([ \t]*)\{\/\*\s*impeccable-live-start\s*\*\/\}[\s\S]*?\{\/\*\s*impeccable-live-end\s*\*\/\}[ \t]
|
|
306
|
+
/([ \t]*)<!--\s*impeccable-live-start\s*-->[\s\S]*?<!--\s*impeccable-live-end\s*-->([ \t]*(?:\n|$)?)/,
|
|
307
|
+
/([ \t]*)\{\/\*\s*impeccable-live-start\s*\*\/\}[\s\S]*?\{\/\*\s*impeccable-live-end\s*\*\/\}([ \t]*(?:\n|$)?)/,
|
|
304
308
|
];
|
|
305
309
|
for (const pat of patterns) {
|
|
306
|
-
|
|
307
|
-
|
|
310
|
+
let changed = false;
|
|
311
|
+
let next = content;
|
|
312
|
+
do {
|
|
313
|
+
content = next;
|
|
314
|
+
next = content.replace(pat, (_match, leadingIndent, trailing = '') => {
|
|
315
|
+
if (trailing.includes('\n')) return leadingIndent;
|
|
316
|
+
return leadingIndent || trailing || '';
|
|
317
|
+
});
|
|
318
|
+
if (next !== content) changed = true;
|
|
319
|
+
} while (next !== content);
|
|
320
|
+
if (changed) return next;
|
|
308
321
|
}
|
|
309
322
|
return content;
|
|
310
323
|
}
|