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