@pathmx/core 0.5.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/LICENSE.md +172 -0
- package/README.md +111 -0
- package/actions/actions.ts +307 -0
- package/actions/draft.ts +105 -0
- package/actions/transaction.ts +164 -0
- package/assets.ts +149 -0
- package/authority/access.ts +820 -0
- package/authority/actors.ts +271 -0
- package/authority/agents.ts +95 -0
- package/authority/credentials.ts +144 -0
- package/authority/model.ts +71 -0
- package/authority/sharing.ts +89 -0
- package/browser-bundle.ts +61 -0
- package/canonical.ts +41 -0
- package/cli/dev.ts +134 -0
- package/cli/export.ts +74 -0
- package/cli/index.ts +52 -0
- package/cli/lint.ts +164 -0
- package/cli/mv.ts +30 -0
- package/cli/perms.ts +182 -0
- package/cli/plugin-packages.ts +159 -0
- package/cli/plugins.ts +95 -0
- package/cli/query.ts +225 -0
- package/cli/readme.md +95 -0
- package/cli/release.ts +75 -0
- package/cli/rm.ts +22 -0
- package/cli/serve.ts +100 -0
- package/cli/tree.ts +131 -0
- package/cli/update.ts +78 -0
- package/cli/utils.ts +53 -0
- package/core.ts +96 -0
- package/database.ts +189 -0
- package/dependencies.ts +60 -0
- package/dist/pathmx.js +1224 -0
- package/document.ts +194 -0
- package/environment.ts +110 -0
- package/environments/bun-plugins.ts +68 -0
- package/environments/bun-publish.ts +194 -0
- package/environments/bun.ts +223 -0
- package/globals.d.ts +14 -0
- package/graph.ts +153 -0
- package/host/compiler.ts +314 -0
- package/host/create.ts +66 -0
- package/host/engine.ts +630 -0
- package/host/plugin-host.ts +487 -0
- package/host/render.ts +102 -0
- package/host/response.ts +20 -0
- package/host/shell.html +15 -0
- package/host/source-sync.ts +254 -0
- package/html-attributes.ts +15 -0
- package/html.ts +48 -0
- package/icons/LICENSE +43 -0
- package/icons/lucide.ts +54 -0
- package/index.ts +75 -0
- package/invalidation.ts +85 -0
- package/log.ts +84 -0
- package/ops/href.ts +87 -0
- package/ops/index.ts +9 -0
- package/ops/move-source.ts +114 -0
- package/ops/plan.ts +47 -0
- package/ops/remove-source.ts +70 -0
- package/package.json +46 -0
- package/path.ts +75 -0
- package/pattern.ts +314 -0
- package/perf.ts +88 -0
- package/plugins/actor-path.ts +43 -0
- package/plugins/actor-profile.ts +55 -0
- package/plugins/agent-browsing.ts +183 -0
- package/plugins/app-component.ts +23 -0
- package/plugins/block-layout/index.ts +78 -0
- package/plugins/block-layout/theme.css +90 -0
- package/plugins/callout/index.ts +236 -0
- package/plugins/callout/theme.css +138 -0
- package/plugins/canonical-links.ts +144 -0
- package/plugins/code-highlight/client.ts +89 -0
- package/plugins/code-highlight/index.ts +147 -0
- package/plugins/code-highlight/theme.css +89 -0
- package/plugins/context.ts +131 -0
- package/plugins/datatype/Datatype[wdth,wght].woff2 +0 -0
- package/plugins/datatype/OFL.txt +96 -0
- package/plugins/datatype/index.ts +287 -0
- package/plugins/definition-list.ts +236 -0
- package/plugins/directive-definitions.ts +13 -0
- package/plugins/embedding/client.ts +88 -0
- package/plugins/embedding/index.ts +43 -0
- package/plugins/image/index.ts +68 -0
- package/plugins/image/theme.css +43 -0
- package/plugins/include.ts +119 -0
- package/plugins/index.ts +91 -0
- package/plugins/input/authoring.ts +236 -0
- package/plugins/input/config.ts +85 -0
- package/plugins/input/index.ts +359 -0
- package/plugins/input/model.ts +173 -0
- package/plugins/input/state.ts +272 -0
- package/plugins/layout.ts +313 -0
- package/plugins/literate/client.ts +208 -0
- package/plugins/literate/index.ts +742 -0
- package/plugins/math/index.ts +140 -0
- package/plugins/meta.ts +42 -0
- package/plugins/navigation/index.ts +158 -0
- package/plugins/navigation/model.ts +364 -0
- package/plugins/preset.ts +65 -0
- package/plugins/query/index.ts +322 -0
- package/plugins/rss/index.ts +46 -0
- package/plugins/runtime/actions.ts +62 -0
- package/plugins/runtime/client.ts +8 -0
- package/plugins/runtime/document.ts +506 -0
- package/plugins/runtime/error.ts +154 -0
- package/plugins/runtime/heading-links.ts +31 -0
- package/plugins/runtime/index.ts +104 -0
- package/plugins/runtime/live.ts +51 -0
- package/plugins/runtime/navigation.ts +113 -0
- package/plugins/runtime/pending.ts +53 -0
- package/plugins/runtime/publication.ts +19 -0
- package/plugins/runtime/start.ts +177 -0
- package/plugins/runtime/static-client.ts +6 -0
- package/plugins/runtime/static-live.ts +188 -0
- package/plugins/runtime/view-transition.ts +72 -0
- package/plugins/runtime/viewport.ts +110 -0
- package/plugins/schema.ts +24 -0
- package/plugins/scripts.ts +140 -0
- package/plugins/source-preview/client.ts +256 -0
- package/plugins/source-preview/index.ts +132 -0
- package/plugins/source-preview/model.ts +11 -0
- package/plugins/source-preview/preview.css +107 -0
- package/plugins/styles.ts +145 -0
- package/plugins/theme/components.ts +10 -0
- package/plugins/theme/foundation.css +358 -0
- package/plugins/theme/index.ts +333 -0
- package/plugins/theme/prose.css +284 -0
- package/plugins/theme/scheme.js +63 -0
- package/plugins/theme/toggle.css +44 -0
- package/plugins/theme/view-transition.css +68 -0
- package/plugins/toc/client.ts +146 -0
- package/plugins/toc/index.ts +232 -0
- package/plugins/toc/theme.css +172 -0
- package/plugins/types.ts +538 -0
- package/problem.ts +41 -0
- package/project.ts +6 -0
- package/publish/build.ts +402 -0
- package/publish/concurrent.ts +32 -0
- package/publish/identity.ts +63 -0
- package/publish/index.ts +11 -0
- package/publish/location.ts +167 -0
- package/publish/model.ts +58 -0
- package/publish/plan.ts +300 -0
- package/publish/validate.ts +150 -0
- package/query/candidate-index.ts +101 -0
- package/query/dependency-index.ts +99 -0
- package/query/fields.ts +216 -0
- package/query/invalidation.ts +48 -0
- package/query/kernel.ts +776 -0
- package/query/model.ts +79 -0
- package/repository.ts +374 -0
- package/runtime-profile.ts +34 -0
- package/schema/model.ts +92 -0
- package/schema/registry.ts +642 -0
- package/schema/standard.ts +226 -0
- package/server/context.ts +94 -0
- package/server/css-imports.ts +66 -0
- package/server/http.ts +333 -0
- package/server/page.ts +21 -0
- package/server/protocols.ts +12 -0
- package/server/representations.ts +66 -0
- package/server/router.ts +131 -0
- package/server/routes.ts +202 -0
- package/server/serve.ts +5 -0
- package/server/watch.ts +120 -0
- package/source/blocks.ts +71 -0
- package/source/format.ts +164 -0
- package/source/index.ts +67 -0
- package/source/interpolate.ts +63 -0
- package/source/markdown/blocks.ts +46 -0
- package/source/markdown/comments.ts +32 -0
- package/source/markdown/fences.ts +67 -0
- package/source/markdown/headings.ts +88 -0
- package/source/markdown/index.ts +34 -0
- package/source/markdown/inline-code.ts +6 -0
- package/source/markdown/links.ts +326 -0
- package/source/markdown/lists.ts +223 -0
- package/source/markdown/prose.ts +74 -0
- package/source/markdown/scan.ts +79 -0
- package/source/markdown/text.ts +82 -0
- package/source/meta.ts +87 -0
- package/source/source.ts +121 -0
- package/source/topmatter.ts +57 -0
- package/source/utils.ts +21 -0
- package/source-diagnostic.ts +63 -0
- package/text-file.ts +26 -0
- package/util.ts +35 -0
- package/view/components.ts +499 -0
- package/view/model.ts +91 -0
- package/view/projection.ts +162 -0
- package/view/session.ts +146 -0
- package/view/syntax.ts +372 -0
package/view/syntax.ts
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import type { HtmlStringRewrite } from "../environment.ts"
|
|
2
|
+
import { parseHtmlAttributes } from "../html-attributes.ts"
|
|
3
|
+
import type { CompileContext } from "../plugins/types.ts"
|
|
4
|
+
import {
|
|
5
|
+
transformMarkdownProse,
|
|
6
|
+
transformOutsideHtmlComments,
|
|
7
|
+
} from "../source/markdown/prose.ts"
|
|
8
|
+
|
|
9
|
+
const NAME = "[a-z][a-z0-9]*(?:-[a-z0-9]+)*"
|
|
10
|
+
const VIEW_ELEMENT = new RegExp("^" + NAME + ":" + NAME + "$")
|
|
11
|
+
const AUTHORED_VIEW_ELEMENT = new RegExp("^x-" + NAME + "$")
|
|
12
|
+
const LITERATE_ELEMENT = /^[a-z][\w.-]*$/
|
|
13
|
+
export const VIEW_USE_TAG = "pmx-view"
|
|
14
|
+
export const VIEW_NAME_ATTR = "data-pmx-view"
|
|
15
|
+
export const VIEW_SLOT_ATTR = "data-pmx-view-slot"
|
|
16
|
+
const ATTRS = "((?:\\s+(?:[^<>\\\"']|\\\"[^\\\"]*\\\"|'[^']*')*)?)"
|
|
17
|
+
const AUTHORED_VIEW_USE = new RegExp(
|
|
18
|
+
"<(x-" + NAME + ")" + ATTRS + "\\s*(?:/\\s*>|>\\s*</\\1\\s*>)",
|
|
19
|
+
"gi",
|
|
20
|
+
)
|
|
21
|
+
const REMAINING_AUTHORED_VIEW_USE = new RegExp(
|
|
22
|
+
"<(x-" + NAME + ")(?:\\s|/?>)",
|
|
23
|
+
"i",
|
|
24
|
+
)
|
|
25
|
+
const VIEW_SYNTAX_CANDIDATE = /<x-[a-z]/i
|
|
26
|
+
const COMPONENT_SYNTAX_SLOT = /<!--pmx-component-syntax:(\d+)-->/g
|
|
27
|
+
const VIEW_VARIABLE_USE =
|
|
28
|
+
/\{\{\s*([A-Za-z_][\w-]*)\.([A-Za-z_][\w-]*(?:\.[A-Za-z_][\w-]*)*)\s*\}\}/g
|
|
29
|
+
export const COMPONENT_ORIGIN_ATTR = "data-pmx-component-origin"
|
|
30
|
+
|
|
31
|
+
function escapeRegExp(value: string) {
|
|
32
|
+
return value.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isViewComponentTag(tag: string) {
|
|
36
|
+
return VIEW_ELEMENT.test(tag)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isAuthoredViewTag(tag: string) {
|
|
40
|
+
return AUTHORED_VIEW_ELEMENT.test(tag)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isLiterateComponentTag(tag: string) {
|
|
44
|
+
return LITERATE_ELEMENT.test(tag)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Map a plugin-owned identity to its standards-compatible authored tag. */
|
|
48
|
+
export function authoredViewTag(tag: string) {
|
|
49
|
+
if (!isViewComponentTag(tag)) {
|
|
50
|
+
throw new Error("Invalid View Component tag: " + tag)
|
|
51
|
+
}
|
|
52
|
+
return "x-" + tag.replace(":", "-")
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function viewUsePattern() {
|
|
56
|
+
const escaped = escapeRegExp(VIEW_USE_TAG)
|
|
57
|
+
const attrs = "((?:\\s+(?:[^<>\\\"']|\\\"[^\\\"]*\\\"|'[^']*')*)?)"
|
|
58
|
+
return new RegExp(
|
|
59
|
+
"<" + escaped + attrs + "\\s*(?:/\\s*>|>\\s*</" + escaped + "\\s*>)",
|
|
60
|
+
"gi",
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function hasRemainingViewUse(html: string) {
|
|
65
|
+
return new RegExp("<" + VIEW_USE_TAG + "(?:\\s|/?>)", "i").test(html)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function compileVisibleViewUses(markup: string, sourcePath: string) {
|
|
69
|
+
const compiled = markup.replace(
|
|
70
|
+
AUTHORED_VIEW_USE,
|
|
71
|
+
(_match, tag: string, attrs: string) =>
|
|
72
|
+
"<" +
|
|
73
|
+
VIEW_USE_TAG +
|
|
74
|
+
" " +
|
|
75
|
+
VIEW_NAME_ATTR +
|
|
76
|
+
'="' +
|
|
77
|
+
tag +
|
|
78
|
+
'"' +
|
|
79
|
+
attrs +
|
|
80
|
+
" />",
|
|
81
|
+
)
|
|
82
|
+
const remaining = compiled.match(REMAINING_AUTHORED_VIEW_USE)
|
|
83
|
+
if (remaining) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
"<" +
|
|
86
|
+
remaining[1] +
|
|
87
|
+
"> must be empty or self-closing in " +
|
|
88
|
+
sourcePath +
|
|
89
|
+
".",
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
return compiled
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function compileViewUses(markup: string, sourcePath: string) {
|
|
96
|
+
return transformOutsideHtmlComments(markup, (visible) =>
|
|
97
|
+
compileVisibleViewUses(visible, sourcePath),
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stashLiterateUses(
|
|
102
|
+
markup: string,
|
|
103
|
+
tags: readonly string[],
|
|
104
|
+
slots: string[],
|
|
105
|
+
) {
|
|
106
|
+
if (!tags.length) return markup
|
|
107
|
+
const names = tags.map(escapeRegExp).join("|")
|
|
108
|
+
const uses = new RegExp("<\\/?(?:" + names + ")" + ATTRS + "\\s*\\/?>", "gi")
|
|
109
|
+
return markup.replace(uses, (use) => {
|
|
110
|
+
const slot = slots.push(use) - 1
|
|
111
|
+
return "<!--pmx-component-syntax:" + slot + "-->"
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Compile authored syntax without touching comments, fences, or inline code. */
|
|
116
|
+
function compileComponentSyntax(
|
|
117
|
+
markdown: string,
|
|
118
|
+
sourcePath: string,
|
|
119
|
+
literateTags: readonly string[] = [],
|
|
120
|
+
slots: string[] = [],
|
|
121
|
+
) {
|
|
122
|
+
return transformMarkdownProse(markdown, (markup) =>
|
|
123
|
+
stashLiterateUses(compileViewUses(markup, sourcePath), literateTags, slots),
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type AuthoredViewComponentUse = Readonly<{
|
|
128
|
+
tag: string
|
|
129
|
+
props: Readonly<Record<string, string>>
|
|
130
|
+
}>
|
|
131
|
+
|
|
132
|
+
/** Read empty authored View Component uses without touching code examples. */
|
|
133
|
+
export function authoredViewComponentUses(markdown: string) {
|
|
134
|
+
const uses: AuthoredViewComponentUse[] = []
|
|
135
|
+
transformMarkdownProse(markdown, (markup) => {
|
|
136
|
+
for (const match of markup.matchAll(
|
|
137
|
+
new RegExp(AUTHORED_VIEW_USE.source, "gi"),
|
|
138
|
+
)) {
|
|
139
|
+
uses.push(
|
|
140
|
+
Object.freeze({
|
|
141
|
+
tag: match[1]!.toLowerCase(),
|
|
142
|
+
props: Object.freeze(parseHtmlAttributes(match[2])),
|
|
143
|
+
}),
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
return markup
|
|
147
|
+
})
|
|
148
|
+
return Object.freeze(uses)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function elementTagNames(markup: string) {
|
|
152
|
+
const tags = new Set<string>()
|
|
153
|
+
for (const match of markup.matchAll(/<([a-z][\w:.-]*)\b/gi)) {
|
|
154
|
+
if (match[1]) tags.add(match[1].toLowerCase())
|
|
155
|
+
}
|
|
156
|
+
return tags
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Attach trusted origin metadata before authored components are expanded. */
|
|
160
|
+
export function stampComponentOrigins(
|
|
161
|
+
html: string,
|
|
162
|
+
originPath: string,
|
|
163
|
+
authoredTags: Pick<ReadonlySet<string>, "has">,
|
|
164
|
+
rewriteHtml: HtmlStringRewrite,
|
|
165
|
+
) {
|
|
166
|
+
return rewriteHtml(html, [
|
|
167
|
+
[
|
|
168
|
+
"*",
|
|
169
|
+
{
|
|
170
|
+
element(element) {
|
|
171
|
+
if (element.tagName === "pmx-content") return
|
|
172
|
+
if (
|
|
173
|
+
element.tagName === VIEW_USE_TAG ||
|
|
174
|
+
element.tagName.includes(":") ||
|
|
175
|
+
element.tagName.includes("-") ||
|
|
176
|
+
authoredTags.has(element.tagName)
|
|
177
|
+
) {
|
|
178
|
+
element.setAttribute(COMPONENT_ORIGIN_ATTR, originPath)
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
])
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Attach attributes to the first root in trusted rendered HTML. */
|
|
187
|
+
export function stampHtmlRoot(
|
|
188
|
+
html: string,
|
|
189
|
+
attrs: Readonly<Record<string, string>>,
|
|
190
|
+
rewriteHtml: HtmlStringRewrite,
|
|
191
|
+
) {
|
|
192
|
+
let stamped = false
|
|
193
|
+
return rewriteHtml(html, [
|
|
194
|
+
[
|
|
195
|
+
"*",
|
|
196
|
+
{
|
|
197
|
+
element(element) {
|
|
198
|
+
if (stamped) return
|
|
199
|
+
stamped = true
|
|
200
|
+
for (const [name, value] of Object.entries(attrs)) {
|
|
201
|
+
element.setAttribute(name, value)
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
])
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Mark the first rendered root as the semantic boundary of a component. */
|
|
210
|
+
export function stampComponentRoot(
|
|
211
|
+
html: string,
|
|
212
|
+
tag: string,
|
|
213
|
+
rewriteHtml: HtmlStringRewrite,
|
|
214
|
+
attrs?: Record<string, string>,
|
|
215
|
+
) {
|
|
216
|
+
return stampHtmlRoot(
|
|
217
|
+
html,
|
|
218
|
+
{
|
|
219
|
+
"data-component": tag,
|
|
220
|
+
...(attrs ? { "data-pmx-attrs": JSON.stringify(attrs) } : {}),
|
|
221
|
+
},
|
|
222
|
+
rewriteHtml,
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function stripComponentOrigins(html: string) {
|
|
227
|
+
if (!html.includes(COMPONENT_ORIGIN_ATTR)) return html
|
|
228
|
+
return html.replace(
|
|
229
|
+
new RegExp("\\s" + COMPONENT_ORIGIN_ATTR + '="[^"]*"', "g"),
|
|
230
|
+
"",
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Stateful authored syntax indexes kept separate from component execution. */
|
|
235
|
+
export class ViewComponentSyntax {
|
|
236
|
+
private variables = new Map<string, string>()
|
|
237
|
+
private variableMatcher?: RegExp
|
|
238
|
+
private authoredTags = new Map<string, string>()
|
|
239
|
+
private authoredMatcher?: RegExp
|
|
240
|
+
private slots = new WeakMap<CompileContext, string[]>()
|
|
241
|
+
|
|
242
|
+
registerVariables(variables: Iterable<readonly [string, string]>) {
|
|
243
|
+
let changed = false
|
|
244
|
+
for (const [namespace, tag] of variables) {
|
|
245
|
+
this.variables.set(namespace, tag)
|
|
246
|
+
changed = true
|
|
247
|
+
}
|
|
248
|
+
if (!changed) return
|
|
249
|
+
this.variableMatcher = new RegExp(
|
|
250
|
+
"\\{\\{\\s*(?:" +
|
|
251
|
+
[...this.variables.keys()].map(escapeRegExp).join("|") +
|
|
252
|
+
")\\.",
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
compileVariables(markdown: string) {
|
|
257
|
+
if (!this.variableMatcher?.test(markdown)) return markdown
|
|
258
|
+
return transformMarkdownProse(markdown, (prose) =>
|
|
259
|
+
prose.replace(
|
|
260
|
+
VIEW_VARIABLE_USE,
|
|
261
|
+
(token, namespace: string, path: string) => {
|
|
262
|
+
const tag = this.variables.get(namespace)
|
|
263
|
+
return tag
|
|
264
|
+
? "<" +
|
|
265
|
+
VIEW_USE_TAG +
|
|
266
|
+
" " +
|
|
267
|
+
VIEW_NAME_ATTR +
|
|
268
|
+
'="' +
|
|
269
|
+
tag +
|
|
270
|
+
'" data-pmx-variable="' +
|
|
271
|
+
path +
|
|
272
|
+
'" />'
|
|
273
|
+
: token
|
|
274
|
+
},
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
compile(markdown: string, ctx: CompileContext) {
|
|
280
|
+
if (!markdown.includes("<")) return markdown
|
|
281
|
+
const hasViewSyntax = VIEW_SYNTAX_CANDIDATE.test(markdown)
|
|
282
|
+
const hasLiterateSyntax = this.authoredMatcher?.test(markdown) ?? false
|
|
283
|
+
if (!hasViewSyntax && !hasLiterateSyntax) return markdown
|
|
284
|
+
const slots: string[] = []
|
|
285
|
+
const compiled = compileComponentSyntax(
|
|
286
|
+
markdown,
|
|
287
|
+
ctx.source.path,
|
|
288
|
+
hasLiterateSyntax ? [...this.authoredTags.keys()] : [],
|
|
289
|
+
slots,
|
|
290
|
+
)
|
|
291
|
+
if (slots.length) this.slots.set(ctx, slots)
|
|
292
|
+
return compiled
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
restore(html: string, ctx: CompileContext) {
|
|
296
|
+
const slots = this.slots.get(ctx)
|
|
297
|
+
if (!slots) return html
|
|
298
|
+
this.slots.delete(ctx)
|
|
299
|
+
return html.replace(
|
|
300
|
+
COMPONENT_SYNTAX_SLOT,
|
|
301
|
+
(marker, index: string) => slots[Number(index)] ?? marker,
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
replaceAuthored(sourcePath: string, tags: Iterable<string>) {
|
|
306
|
+
const pending = new Set(tags)
|
|
307
|
+
for (const tag of pending) {
|
|
308
|
+
if (!isLiterateComponentTag(tag)) {
|
|
309
|
+
throw new Error("Invalid Literate Component tag: " + tag)
|
|
310
|
+
}
|
|
311
|
+
if (tag.startsWith("x-")) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
"Literate Component tag <" + tag + "> uses the reserved x- prefix.",
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
const authoredBy = this.authoredTags.get(tag)
|
|
317
|
+
if (authoredBy && authoredBy !== sourcePath) {
|
|
318
|
+
throw new Error(
|
|
319
|
+
"Duplicate Literate Component <" +
|
|
320
|
+
tag +
|
|
321
|
+
"> in " +
|
|
322
|
+
sourcePath +
|
|
323
|
+
" and " +
|
|
324
|
+
authoredBy +
|
|
325
|
+
".",
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
for (const [tag, owner] of this.authoredTags) {
|
|
330
|
+
if (owner === sourcePath) this.authoredTags.delete(tag)
|
|
331
|
+
}
|
|
332
|
+
for (const tag of pending) this.authoredTags.set(tag, sourcePath)
|
|
333
|
+
this.rebuildMatcher()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
deleteAuthored(sourcePath: string) {
|
|
337
|
+
let deleted = false
|
|
338
|
+
for (const [tag, owner] of this.authoredTags) {
|
|
339
|
+
if (owner !== sourcePath) continue
|
|
340
|
+
this.authoredTags.delete(tag)
|
|
341
|
+
deleted = true
|
|
342
|
+
}
|
|
343
|
+
if (deleted) this.rebuildMatcher()
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
has(tag: string) {
|
|
347
|
+
return this.authoredTags.has(tag)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
stampOrigins(
|
|
351
|
+
html: string,
|
|
352
|
+
originPath: string,
|
|
353
|
+
rewriteHtml: HtmlStringRewrite,
|
|
354
|
+
) {
|
|
355
|
+
return stampComponentOrigins(
|
|
356
|
+
html,
|
|
357
|
+
originPath,
|
|
358
|
+
this.authoredTags,
|
|
359
|
+
rewriteHtml,
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private rebuildMatcher() {
|
|
364
|
+
const tags = [...this.authoredTags.keys()]
|
|
365
|
+
this.authoredMatcher = tags.length
|
|
366
|
+
? new RegExp(
|
|
367
|
+
"<(?:" + tags.map(escapeRegExp).join("|") + ")(?:\\s|/?>)",
|
|
368
|
+
"i",
|
|
369
|
+
)
|
|
370
|
+
: undefined
|
|
371
|
+
}
|
|
372
|
+
}
|