@longform/longform 0.0.7 → 0.0.8
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 +28 -0
- package/dist/longform.cjs +128 -16
- package/dist/longform.cjs.map +1 -1
- package/dist/longform.d.ts +4 -4
- package/dist/longform.js +128 -16
- package/dist/longform.js.br +0 -0
- package/dist/longform.js.gz +0 -0
- package/dist/longform.js.map +1 -1
- package/dist/longform.min.js +128 -16
- package/dist/longform.min.js.br +0 -0
- package/dist/longform.min.js.gz +0 -0
- package/dist/longform.min.js.map +1 -1
- package/dist/types.d.ts +70 -1
- package/lib/longform.ts +167 -18
- package/lib/types.ts +91 -1
- package/package.json +19 -12
- package/lib/longform.test.ts +0 -354
package/lib/longform.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FragmentType, ParsedResult, WorkingElement, WorkingFragment } from "./types.ts";
|
|
1
|
+
import type { AppliedDirective, DirectiveDef, FragmentType, LongformArgs, ParsedResult, SerializationElement, SerializerConfig, SimplifiedElement, WorkingElement, WorkingFragment } from "./types.ts";
|
|
2
2
|
|
|
3
3
|
const LINE = 0
|
|
4
4
|
, INDENT = 1
|
|
@@ -28,7 +28,7 @@ const sniffTestRe = /^((?: )*)(?:(@)([a-z][a-z\-]*(?::[a-z][a-z\-]*)?)(?:(?:::
|
|
|
28
28
|
, attribute1 = /((?:\ \ )+)\[(\w[\w-]*(?::\w[\w-]*)?)(?:=([^\n]+))?\]/
|
|
29
29
|
, preformattedClose = /[ \t]*}}?[ \t]*/
|
|
30
30
|
, id1 = /((?:\ \ )+)?#(#)?([\w\-]+)(?: ([\["]))?/gmi
|
|
31
|
-
,
|
|
31
|
+
, identRe = /^(\ \ )+/
|
|
32
32
|
, text1 = /^((?:\ \ )+)([^ \n][^\n]*)$/i
|
|
33
33
|
, refRe = /#\[([\w\-]+)\]/g
|
|
34
34
|
, escapeRe = /([&<>"'#\[\]{}])/g
|
|
@@ -63,9 +63,17 @@ function escape(value: string): string {
|
|
|
63
63
|
function makeElement(indent: number = 0): WorkingElement {
|
|
64
64
|
return {
|
|
65
65
|
indent,
|
|
66
|
-
|
|
66
|
+
key: undefined,
|
|
67
|
+
id: undefined,
|
|
68
|
+
tag: undefined,
|
|
69
|
+
class: undefined,
|
|
70
|
+
text: undefined,
|
|
67
71
|
attrs: {},
|
|
72
|
+
html: '',
|
|
73
|
+
mount: undefined,
|
|
74
|
+
serializerConfig: undefined,
|
|
68
75
|
chain: undefined,
|
|
76
|
+
beforeRender: undefined,
|
|
69
77
|
};
|
|
70
78
|
}
|
|
71
79
|
|
|
@@ -81,14 +89,70 @@ function makeFragment(type: FragmentType = 'bare'): WorkingFragment {
|
|
|
81
89
|
};
|
|
82
90
|
}
|
|
83
91
|
|
|
92
|
+
class Doc {
|
|
93
|
+
id?: string = undefined;
|
|
94
|
+
lang?: string = undefined;
|
|
95
|
+
meta: Record<string, unknown> = {};
|
|
96
|
+
#serializerConfig: SerializerConfig;
|
|
97
|
+
|
|
98
|
+
constructor(
|
|
99
|
+
id?: string | undefined,
|
|
100
|
+
lang?: string | undefined,
|
|
101
|
+
allowAll?: boolean | undefined,
|
|
102
|
+
allowedAttributes?: string[] | undefined,
|
|
103
|
+
allowedElements?: Array<string | SerializationElement>,
|
|
104
|
+
) {
|
|
105
|
+
this.id = id;
|
|
106
|
+
this.lang = lang;
|
|
107
|
+
this.#serializerConfig = {
|
|
108
|
+
allowAll: allowAll ?? false,
|
|
109
|
+
allowedAttributes: allowedAttributes ?? [],
|
|
110
|
+
allowedElements: {},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (allowedElements != null) {
|
|
114
|
+
for (let i = 0, l = allowedElements.length, el = allowedElements[i]; i < l; i++) {
|
|
115
|
+
if (typeof el === 'string') {
|
|
116
|
+
this.#serializerConfig.allowedElements[el] = {
|
|
117
|
+
tag: el,
|
|
118
|
+
attrs: [],
|
|
119
|
+
};
|
|
120
|
+
} else {
|
|
121
|
+
this.#serializerConfig.allowedElements[el.tag] = el;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
Object.freeze(this);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
allowAll() {
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
allowAttributes() {
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
allowElements() {
|
|
138
|
+
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const directiveValidator = /^[a-z][a-z\-]*\:[a-z][a-z\-]*$/gi;
|
|
143
|
+
|
|
144
|
+
|
|
84
145
|
/**
|
|
85
146
|
* Parses a longform document into a object containing the root and fragments
|
|
86
147
|
* in the output format.
|
|
87
148
|
*
|
|
88
|
-
* @param
|
|
89
|
-
* @
|
|
149
|
+
* @param input - The Longform document to parse.
|
|
150
|
+
* @param args - Arguments for the Longform parser.
|
|
90
151
|
*/
|
|
91
|
-
export function longform(
|
|
152
|
+
export function longform(
|
|
153
|
+
input: string,
|
|
154
|
+
args?: LongformArgs,
|
|
155
|
+
): ParsedResult {
|
|
92
156
|
let skipping: boolean = false
|
|
93
157
|
, textIndent: number | null = null
|
|
94
158
|
, verbatimSerialize: boolean = true
|
|
@@ -98,20 +162,68 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
98
162
|
, fragment: WorkingFragment = makeFragment()
|
|
99
163
|
// the root fragment
|
|
100
164
|
, root: WorkingFragment | null = null
|
|
165
|
+
, id: string | undefined
|
|
166
|
+
, lang: string | undefined
|
|
167
|
+
, doc: Doc | undefined
|
|
101
168
|
// ids of claimed fragments
|
|
102
169
|
const claimed: Set<string> = new Set()
|
|
103
170
|
// parsed fragments
|
|
104
171
|
, parsed: Map<string, WorkingFragment> = new Map()
|
|
105
|
-
, output: ParsedResult = Object.create(null)
|
|
172
|
+
, output: ParsedResult = Object.create(null)
|
|
173
|
+
, directives: Record<string, DirectiveDef> = {}
|
|
174
|
+
|
|
106
175
|
|
|
107
176
|
output.fragments = Object.create(null);
|
|
108
177
|
output.templates = Object.create(null);
|
|
178
|
+
|
|
179
|
+
if (args?.directives != null) {
|
|
180
|
+
const entries = Object.entries(args.directives);
|
|
181
|
+
|
|
182
|
+
for (let i = 0, l = entries.length; i < l; i++) {
|
|
183
|
+
if (!directiveValidator.test(entries[i][0])) {
|
|
184
|
+
console.warn(`Invalid custom directive name '${entries[i][0]}'`);
|
|
185
|
+
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
109
188
|
|
|
189
|
+
directives[entries[i][0]] = entries[i][1];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
110
193
|
/**
|
|
111
194
|
* Closes any current in progress element definition
|
|
112
195
|
* and creates a new working element.
|
|
113
196
|
*/
|
|
114
197
|
function applyIndent(targetIndent: number) {
|
|
198
|
+
if (Array.isArray(element.beforeRender)) {
|
|
199
|
+
const el: SimplifiedElement = {
|
|
200
|
+
id: element.id,
|
|
201
|
+
tag: element.tag,
|
|
202
|
+
class: element.class,
|
|
203
|
+
attrs: element.attrs,
|
|
204
|
+
};
|
|
205
|
+
const chain: SimplifiedElement[] = [];
|
|
206
|
+
|
|
207
|
+
for (let i = 0, l = element.chain.length, el = element.chain[i]; i < l; i++) {
|
|
208
|
+
chain.push({
|
|
209
|
+
id: el.id,
|
|
210
|
+
tag: el.tag,
|
|
211
|
+
class: el.class,
|
|
212
|
+
attrs: el.attrs,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
for (let i = 0, l = element.beforeRender.length, def = element.beforeRender[i]; i < l; i++) {
|
|
217
|
+
def.beforeRender({
|
|
218
|
+
el,
|
|
219
|
+
chain,
|
|
220
|
+
doc,
|
|
221
|
+
inlineArg: def.inlineArg,
|
|
222
|
+
blockArg: def.blockArg,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
115
227
|
if (element.tag != null) {
|
|
116
228
|
const root = fragment.type === 'range'
|
|
117
229
|
? targetIndent < 2
|
|
@@ -210,7 +322,6 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
210
322
|
}
|
|
211
323
|
|
|
212
324
|
if (targetIndent === 0) {
|
|
213
|
-
debug(0, '<', fragment.type, fragment.id);
|
|
214
325
|
if (fragment.template) {
|
|
215
326
|
output.templates[fragment.id] = fragment.html;
|
|
216
327
|
} else if (fragment.type === 'root') {
|
|
@@ -226,7 +337,7 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
226
337
|
}
|
|
227
338
|
}
|
|
228
339
|
|
|
229
|
-
while ((m1 = sniffTestRe.exec(
|
|
340
|
+
main: while ((m1 = sniffTestRe.exec(input))) {
|
|
230
341
|
if (m1[1] === '--') {
|
|
231
342
|
continue;
|
|
232
343
|
} else if (fragment.template) {
|
|
@@ -239,15 +350,14 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
239
350
|
// by ending the declaration with `:: {`.
|
|
240
351
|
if (verbatimIndent != null) {
|
|
241
352
|
// inside a script or preformatted block
|
|
242
|
-
|
|
243
|
-
m2 =
|
|
353
|
+
identRe.lastIndex = 0;
|
|
354
|
+
m2 = identRe.exec(m1[0]);
|
|
244
355
|
const indent = m2 == null
|
|
245
356
|
? null
|
|
246
357
|
: m2[0].length / 2;
|
|
247
358
|
|
|
248
359
|
if (m2 == null || indent as number <= verbatimIndent) {
|
|
249
360
|
fragment.html += '\n';
|
|
250
|
-
debug(indent, '}', m2?.[0]);
|
|
251
361
|
|
|
252
362
|
applyIndent(indent);
|
|
253
363
|
verbatimIndent = null;
|
|
@@ -259,7 +369,6 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
259
369
|
}
|
|
260
370
|
} else {
|
|
261
371
|
const line = m1[0].replace(' '.repeat(verbatimIndent + 1), '');
|
|
262
|
-
debug(indent, '{', line);
|
|
263
372
|
|
|
264
373
|
if (element.tag != null) {
|
|
265
374
|
applyIndent(indent as number);
|
|
@@ -285,6 +394,26 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
285
394
|
continue;
|
|
286
395
|
}
|
|
287
396
|
|
|
397
|
+
// The id and lang directives should proceed all other directives and
|
|
398
|
+
// fragment declarations.
|
|
399
|
+
if (doc === undefined) {
|
|
400
|
+
const inlineArgs = m1[DIRECTIVE_INLINE_ARGS] ?? '';
|
|
401
|
+
|
|
402
|
+
switch (m1[DIRECTIVE]) {
|
|
403
|
+
case 'id': {
|
|
404
|
+
// TODO: Add id validation
|
|
405
|
+
id = inlineArgs.trim();
|
|
406
|
+
continue main;
|
|
407
|
+
}
|
|
408
|
+
case 'lang': {
|
|
409
|
+
lang = inlineArgs.trim();
|
|
410
|
+
continue main;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
doc = new Doc(id, lang, args?.allowAll, args?.allowedAttributes, args?.allowedElements);
|
|
415
|
+
}
|
|
416
|
+
|
|
288
417
|
switch (m1[DIRECTIVE_KEY] ?? m1[ID_TYPE] ?? m1[ELEMENT] ?? m1[ATTR]) {
|
|
289
418
|
case '#':
|
|
290
419
|
case '##': {
|
|
@@ -339,7 +468,7 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
339
468
|
fragment.template = indent === 0;
|
|
340
469
|
|
|
341
470
|
templateLinesRe.lastIndex = sniffTestRe.lastIndex;
|
|
342
|
-
while ((m2 = templateLinesRe.exec(
|
|
471
|
+
while ((m2 = templateLinesRe.exec(input))) {
|
|
343
472
|
if (m2[1] == null && !indented && fragment.id == null) {
|
|
344
473
|
id1.lastIndex = 0;
|
|
345
474
|
m3 = id1.exec(m2[0]);
|
|
@@ -370,6 +499,27 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
370
499
|
element.mount = m1[DIRECTIVE_INLINE_ARGS].trim();
|
|
371
500
|
break;
|
|
372
501
|
}
|
|
502
|
+
default: {
|
|
503
|
+
const def = directives[m1[DIRECTIVE]];
|
|
504
|
+
|
|
505
|
+
if (def == null) break;
|
|
506
|
+
|
|
507
|
+
if (typeof def.beforeRender === 'function') {
|
|
508
|
+
if (element.id != null) {
|
|
509
|
+
applyIndent(indent);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (element.beforeRender == null) element.beforeRender = [];
|
|
513
|
+
|
|
514
|
+
// TODO: Parse block args
|
|
515
|
+
const applied: AppliedDirective = {
|
|
516
|
+
...def,
|
|
517
|
+
inlineArg: m1[DIRECTIVE_INLINE_ARGS],
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
element.beforeRender.push(applied);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
373
523
|
}
|
|
374
524
|
|
|
375
525
|
break;
|
|
@@ -492,8 +642,6 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
492
642
|
: undefined;
|
|
493
643
|
|
|
494
644
|
if (m2 != null && element.tag != null) {
|
|
495
|
-
debug('a', m2[2], m2[3]);
|
|
496
|
-
|
|
497
645
|
if (m2[2] === 'id') {
|
|
498
646
|
if (element.id == null) {
|
|
499
647
|
element.id = m2[3].trim();
|
|
@@ -522,8 +670,6 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
522
670
|
const indent = m2[1].length / 2;
|
|
523
671
|
const tx = m2[2].trim();
|
|
524
672
|
|
|
525
|
-
debug(indent, 't', m2[2]);
|
|
526
|
-
|
|
527
673
|
if (element.tag != null) {
|
|
528
674
|
applyIndent(indent);
|
|
529
675
|
|
|
@@ -637,6 +783,9 @@ export function longform(doc: string, debug: (...d: unknown[]) => void = () => {
|
|
|
637
783
|
};
|
|
638
784
|
}
|
|
639
785
|
|
|
786
|
+
output.id = doc?.id;
|
|
787
|
+
output.lang = doc?.lang;
|
|
788
|
+
|
|
640
789
|
return output;
|
|
641
790
|
}
|
|
642
791
|
|
package/lib/types.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
|
|
2
|
+
|
|
3
|
+
export type SerializationElement = {
|
|
4
|
+
tag: string;
|
|
5
|
+
attrs: string[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type SerializerConfig = {
|
|
9
|
+
allowAll: boolean;
|
|
10
|
+
allowedAttributes: string[];
|
|
11
|
+
allowedElements: Record<string, SerializationElement>;
|
|
12
|
+
};
|
|
13
|
+
|
|
2
14
|
export type WorkingElement = {
|
|
3
15
|
indent: number;
|
|
4
16
|
key?: string;
|
|
@@ -9,7 +21,9 @@ export type WorkingElement = {
|
|
|
9
21
|
text?: string;
|
|
10
22
|
html: string;
|
|
11
23
|
mount?: string;
|
|
24
|
+
serializerConfig?: SerializerConfig;
|
|
12
25
|
chain: WorkingElement[];
|
|
26
|
+
beforeRender?: AppliedDirective[];
|
|
13
27
|
};
|
|
14
28
|
|
|
15
29
|
export type WorkingFragmentType =
|
|
@@ -43,7 +57,7 @@ export type WorkingFragment = {
|
|
|
43
57
|
html: string;
|
|
44
58
|
refs: FragmentRef[];
|
|
45
59
|
els: WorkingElement[];
|
|
46
|
-
mountPoints
|
|
60
|
+
mountPoints?: MountPoint[];
|
|
47
61
|
};
|
|
48
62
|
|
|
49
63
|
export type Fragment = {
|
|
@@ -59,6 +73,8 @@ export type MountPoint = {
|
|
|
59
73
|
};
|
|
60
74
|
|
|
61
75
|
export type ParsedResult = {
|
|
76
|
+
id?: string;
|
|
77
|
+
lang?: string;
|
|
62
78
|
mountable?: boolean;
|
|
63
79
|
root?: string;
|
|
64
80
|
selector?: string;
|
|
@@ -68,3 +84,77 @@ export type ParsedResult = {
|
|
|
68
84
|
templates: Record<string, string>;
|
|
69
85
|
};
|
|
70
86
|
|
|
87
|
+
export type Doc = {
|
|
88
|
+
id?: string;
|
|
89
|
+
lang?: string;
|
|
90
|
+
meta: Readonly<Record<string, unknown>>;
|
|
91
|
+
serializerConfig?: SerializerConfig;
|
|
92
|
+
allowAll(): void;
|
|
93
|
+
allowAttributes(attributes: string[]): void;
|
|
94
|
+
allowElements(elements: Record<string, SerializationElement>): void;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type SimplifiedElement = {
|
|
98
|
+
id?: string;
|
|
99
|
+
tag: string;
|
|
100
|
+
class?: string;
|
|
101
|
+
attrs: Record<string, string | boolean | null>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type GlobalCtx = {
|
|
105
|
+
doc: Doc;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export type BeforeRenderCtx = {
|
|
109
|
+
inlineArg?: string;
|
|
110
|
+
blockArg?: string;
|
|
111
|
+
el: SimplifiedElement;
|
|
112
|
+
chain: SimplifiedElement[];
|
|
113
|
+
doc: Readonly<Doc>;
|
|
114
|
+
//serializerConfig?: SerializerConfig;
|
|
115
|
+
//setMeta(key: string, value: unknown): void;
|
|
116
|
+
//allowAll(): void;
|
|
117
|
+
//allowAttributes(attributes: string[]): void;
|
|
118
|
+
//allowElements(elements: Record<string, SerializationElement>): void;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type AttrValueCtx = {
|
|
122
|
+
tag: string;
|
|
123
|
+
doc: Readonly<Doc>;
|
|
124
|
+
meta: Readonly<Record<string, string>>
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export type AppliesTo =
|
|
128
|
+
| 'self'
|
|
129
|
+
| 'direct-descendants'
|
|
130
|
+
| 'children'
|
|
131
|
+
| 'all'
|
|
132
|
+
;
|
|
133
|
+
|
|
134
|
+
export type DirectiveDef = {
|
|
135
|
+
onGlobal?: (ctx: GlobalCtx) => void;
|
|
136
|
+
beforeFragment?: () => void;
|
|
137
|
+
beforeElement?: () => void;
|
|
138
|
+
beforeRender?: (ctx: BeforeRenderCtx) => void;
|
|
139
|
+
render?: (inlineArgs?: string, blockArgs?: string) => string;
|
|
140
|
+
renderAttr?: (ctx: AttrValueCtx) => string;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export type AppliedDirective = {
|
|
144
|
+
inlineArg?: string;
|
|
145
|
+
blockArg?: string;
|
|
146
|
+
onGlobal?: (ctx: GlobalCtx) => void;
|
|
147
|
+
beforeFragment?: () => void;
|
|
148
|
+
beforeElement?: () => void;
|
|
149
|
+
beforeRender?: (ctx: BeforeRenderCtx) => void;
|
|
150
|
+
render?: (inlineArgs?: string, blockArgs?: string) => string;
|
|
151
|
+
renderAttr?: (ctx: AttrValueCtx) => string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export type LongformArgs = {
|
|
155
|
+
key?: string;
|
|
156
|
+
allowAll?: boolean;
|
|
157
|
+
allowedAttributes?: string[];
|
|
158
|
+
allowedElements?: Array<string | SerializationElement>;
|
|
159
|
+
directives?: Record<string, DirectiveDef>;
|
|
160
|
+
};
|
package/package.json
CHANGED
|
@@ -4,10 +4,23 @@
|
|
|
4
4
|
"author": "Matthew Quinn",
|
|
5
5
|
"homepage": "https://github.com/occultist-dev/longform",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"version": "0.0.
|
|
7
|
+
"version": "0.0.8",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"
|
|
9
|
+
"keywords": [
|
|
10
|
+
"HTML",
|
|
11
|
+
"Fragments",
|
|
12
|
+
"Templating",
|
|
13
|
+
"Longform"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/longform.js",
|
|
10
16
|
"types": "dist/mod.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"node": "./lib/longform.ts",
|
|
20
|
+
"import": "./dist/longform.js",
|
|
21
|
+
"require": "./dist/longform.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
11
24
|
"repository": {
|
|
12
25
|
"type": "git",
|
|
13
26
|
"url": "https://github.com/occultist-dev/longform"
|
|
@@ -24,12 +37,6 @@
|
|
|
24
37
|
"url": "https://github.com/occultist-dev/longform/blob/main/LICENSE"
|
|
25
38
|
}
|
|
26
39
|
],
|
|
27
|
-
"keywords": [
|
|
28
|
-
"HTML",
|
|
29
|
-
"Fragments",
|
|
30
|
-
"Templating",
|
|
31
|
-
"Longform"
|
|
32
|
-
],
|
|
33
40
|
"devDependencies": {
|
|
34
41
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
35
42
|
"@types/commonmark": "^0.27.10",
|
|
@@ -37,14 +44,14 @@
|
|
|
37
44
|
"@types/jsdom": "^27.0.0",
|
|
38
45
|
"@types/node": "^24.8.1",
|
|
39
46
|
"commonmark": "^0.31.2",
|
|
40
|
-
"dompurify": "^3.
|
|
47
|
+
"dompurify": "^3.4.1",
|
|
41
48
|
"jsdom": "^27.0.1",
|
|
42
49
|
"marked": "^16.4.1",
|
|
43
50
|
"prettier": "^3.6.2",
|
|
44
|
-
"rollup": "^4.
|
|
51
|
+
"rollup": "^4.60.2",
|
|
45
52
|
"tslib": "^2.8.1",
|
|
46
53
|
"typescript": "^5.9.3",
|
|
47
|
-
"vnu-jar": "^
|
|
54
|
+
"vnu-jar": "^26.4.16"
|
|
48
55
|
},
|
|
49
56
|
"files": [
|
|
50
57
|
"package.json",
|
|
@@ -56,7 +63,7 @@
|
|
|
56
63
|
"scripts": {
|
|
57
64
|
"build": "node build.ts",
|
|
58
65
|
"bench": "deno bench --no-check --allow-read ./bench/longform.bench.ts",
|
|
59
|
-
"test": "node --test
|
|
66
|
+
"test": "node --test test/**/*.test.ts",
|
|
60
67
|
"serve": "node ./serve.ts"
|
|
61
68
|
}
|
|
62
69
|
}
|