@longform/longform 0.0.3 → 0.0.5

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/dist/longform.js CHANGED
@@ -1,398 +1,508 @@
1
- const sniffTestRe = /^(?:(?:(--).*)|(?: *(@|#).*)|(?: *[\w\-]+(?::[\w\-]+)?(?:[#.[][^\n]+)?(::).*)|(?: +([\["]).*)|(\ \ .*))$/gmi, element1 = /((?:\ \ )+)? ?([\w\-]+(?::[\w\-]+)?)([#\.\[][^\n]*)?::(?: ({{?|[^\n]+))?/gmi, directive1 = /((?:\ \ )+)? ?@([\w][\w\-]+)(?::: ?([^\n]+)?)?/gmi, attribute1 = /((?:\ \ )+)\[(\w[\w-]*(?::\w[\w-]*)?)(?:=([^\n]+))?\]/, preformattedClose = /[ \t]*}}?[ \t]*/, id1 = /((?:\ \ )+)?#(#)?([\w\-]+)(?: ([\["]))?/gmi, idnt1 = /^(\ \ )+/, text1 = /^((?:\ \ )+)([^ \n][^\n]*)$/i, paramsRe = /(?:(#|\.)([^#.\[\n]+)|(?:\[(\w[\w\-]*(?::\w[\w\-]*)?)(?:=([^\n\]]+))?\]))/g, refRe = /#\[([\w\-]+)\]/g, escapeRe = /([&<>"'#\[\]{}])/g, templateLinesRe = /^(\ \ )?([^\n]+)$/gmi, voids = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wrb"]);
1
+ const sniffTestRe = /^(?:(?:(--).*)|(?: *(@|#).*)|(?: *[\w\-]+(?::[\w\-]+)?(?:[#.[][^\n]+)?(::).*)|(?: +([\["]).*)|(\ \ .*))$/gmi, element1 = /((?:\ \ )+)? ?([\w\-]+(?::[\w\-]+)?)([#\.\[][^\n]*)?::(?: ({{?|[^\n]+))?/gmi, directive1 = /((?:\ \ )+)? ?@([\w][\w\-]+)(?::: ?([^\n]+)?)?/gmi, attribute1 = /((?:\ \ )+)\[(\w[\w-]*(?::\w[\w-]*)?)(?:=([^\n]+))?\]/, preformattedClose = /[ \t]*}}?[ \t]*/, id1 = /((?:\ \ )+)?#(#)?([\w\-]+)(?: ([\["]))?/gmi, idnt1 = /^(\ \ )+/, text1 = /^((?:\ \ )+)([^ \n][^\n]*)$/i, paramsRe = /(?:(#|\.)([^#.\[\n]+)|(?:\[(\w[\w\-]*(?::\w[\w\-]*)?)(?:=([^\n\]]+))?\]))/g, refRe = /#\[([\w\-]+)\]/g, escapeRe = /([&<>"'#\[\]{}])/g, templateLinesRe = /^(\ \ )?([^\n]+)$/gmi, voids = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wrb']);
2
2
  let m1, m2, m3;
3
3
  const entities = {
4
- "&": "&amp;",
5
- "<": "&lt;",
6
- ">": "&gt;",
7
- '"': "&quot;",
8
- "'": "&apos;"
9
- // '#': '&num;',
10
- // '[': '&lbrak;',
11
- // ']': '&rbrak;',
12
- // '{': '&rbrace;',
13
- // '}': '&lbrace;',
4
+ '&': '&amp;',
5
+ '<': '&lt;',
6
+ '>': '&gt;',
7
+ '"': '&quot;',
8
+ "'": '&apos;',
9
+ // '#': '&num;',
10
+ // '[': '&lbrak;',
11
+ // ']': '&rbrak;',
12
+ // '{': '&rbrace;',
13
+ // '}': '&lbrace;',
14
14
  };
15
15
  function escape(value) {
16
- return value.replace(escapeRe, (match) => {
17
- var _a;
18
- return (_a = entities[match]) != null ? _a : match;
19
- });
16
+ return value.replace(escapeRe, (match) => {
17
+ return entities[match] ?? match;
18
+ });
20
19
  }
21
20
  function makeElement(indent = 0) {
22
- return {
23
- indent,
24
- html: "",
25
- attrs: {}
26
- };
27
- }
28
- function makeChunk(type = "parsed") {
29
- return {
30
- type,
31
- html: "",
32
- els: []
33
- };
21
+ return {
22
+ indent,
23
+ html: '',
24
+ attrs: {},
25
+ };
34
26
  }
35
- function makeFragment(type = "bare") {
36
- return {
37
- type,
38
- html: "",
39
- template: false,
40
- els: [],
41
- chunks: [],
42
- refs: []
43
- };
27
+ function makeFragment(type = 'bare') {
28
+ return {
29
+ type,
30
+ html: '',
31
+ template: false,
32
+ mountable: false,
33
+ els: [],
34
+ refs: [],
35
+ mountPoints: [],
36
+ };
44
37
  }
45
- export function longform(doc, debug = () => {
46
- }) {
47
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
48
- let skipping = false, textIndent = null, verbatimSerialize = true, verbatimIndent = null, verbatimFirst = false, element = makeElement(), chunk = makeChunk(), fragment = makeFragment(), root = null;
49
- const claimed = /* @__PURE__ */ new Set(), parsed = /* @__PURE__ */ new Map(), output = /* @__PURE__ */ Object.create(null);
50
- output.fragments = /* @__PURE__ */ Object.create(null);
51
- output.templates = /* @__PURE__ */ Object.create(null);
52
- function applyIndent(targetIndent) {
53
- if (element.tag != null) {
54
- const root2 = fragment.type === "range" ? targetIndent < 2 : fragment.html === "";
55
- fragment.html += `<${element.tag}`;
56
- if (root2) {
57
- if (fragment.type === "root") {
58
- fragment.html += ` data-lf-root`;
59
- } else if (fragment.type === "bare" || fragment.type === "range") {
60
- fragment.html += ` data-lf="${fragment.id}"`;
61
- }
62
- }
63
- if (element.id != null) {
64
- fragment.html += ' id="' + element.id + '"';
65
- }
66
- if (element.class != null) {
67
- fragment.html += ' class="' + element.class + '"';
68
- }
69
- for (const attr of Object.entries(element.attrs)) {
70
- if (attr[1] == null) {
71
- fragment.html += " " + attr[0];
72
- } else {
73
- fragment.html += ` ${attr[0]}="${attr[1]}"`;
74
- }
75
- }
76
- fragment.html += ">";
77
- if (!voids.has(element.tag) && element.text != null) {
78
- fragment.html += element.text;
79
- }
80
- if (!voids.has(element.tag)) {
81
- fragment.els.push(element);
82
- }
83
- }
84
- if (targetIndent <= element.indent) {
85
- element = makeElement(targetIndent);
86
- while (fragment.els.length !== 0 && (targetIndent == null || fragment.els[fragment.els.length - 1].indent !== targetIndent - 1)) {
87
- const element2 = fragment.els.pop();
88
- fragment.html += `</${element2 == null ? void 0 : element2.tag}>`;
89
- }
90
- if (targetIndent === 0) {
91
- debug(0, "<", fragment.type, fragment.id);
92
- if (fragment.template) {
93
- output.templates[fragment.id] = fragment.html;
94
- } else if (fragment.type === "root") {
95
- root = fragment;
96
- } else {
97
- parsed.set(fragment.id, fragment);
98
- }
99
- fragment = makeFragment();
100
- }
101
- } else {
102
- element = makeElement(targetIndent);
103
- }
104
- }
105
- while (m1 = sniffTestRe.exec(doc)) {
106
- if (m1[1] === "--") {
107
- continue;
108
- } else if (fragment.template) {
109
- fragment.html += m1[0];
110
- }
111
- if (verbatimIndent != null) {
112
- idnt1.lastIndex = 0;
113
- m2 = idnt1.exec(m1[0]);
114
- const indent = m2 == null ? null : m2[0].length / 2;
115
- if (m2 == null || indent <= verbatimIndent) {
116
- fragment.html += "\n";
117
- debug(indent, "}", m2 == null ? void 0 : m2[0]);
118
- applyIndent(indent);
119
- verbatimIndent = null;
120
- verbatimFirst = false;
121
- textIndent = indent;
122
- if (preformattedClose.test(m1[0])) {
123
- continue;
124
- }
125
- } else {
126
- const line = m1[0].replace(" ".repeat(verbatimIndent + 1), "");
127
- debug(indent, "{", line);
38
+ /**
39
+ * Parses a longform document into a object containing the root and fragments
40
+ * in the output format.
41
+ *
42
+ * @param {string} doc - The longform document to parse.
43
+ * @returns {ParsedResult}
44
+ */
45
+ function longform(doc, debug = () => { }) {
46
+ let textIndent = null, verbatimSerialize = true, verbatimIndent = null, verbatimFirst = false, element = makeElement(), fragment = makeFragment()
47
+ // the root fragment
48
+ , root = null;
49
+ // ids of claimed fragments
50
+ const claimed = new Set()
51
+ // parsed fragments
52
+ , parsed = new Map(), output = Object.create(null);
53
+ output.fragments = Object.create(null);
54
+ output.templates = Object.create(null);
55
+ /**
56
+ * Closes any current in progress element definition
57
+ * and creates a new working element.
58
+ */
59
+ function applyIndent(targetIndent) {
128
60
  if (element.tag != null) {
129
- applyIndent(indent);
61
+ const root = fragment.type === 'range'
62
+ ? targetIndent < 2
63
+ : fragment.html === '';
64
+ fragment.html += `<${element.tag}`;
65
+ if (root) {
66
+ if (fragment.type === 'root') {
67
+ fragment.html += ` data-lf-root`;
68
+ }
69
+ else if (fragment.type === 'bare' || fragment.type === 'range') {
70
+ fragment.html += ` data-lf="${fragment.id}"`;
71
+ }
72
+ }
73
+ if (element.mount != null) {
74
+ fragment.html += ` data-lf-mount="${element.mount}"`;
75
+ }
76
+ if (element.id != null) {
77
+ fragment.html += ' id="' + element.id + '"';
78
+ }
79
+ if (element.class != null) {
80
+ fragment.html += ' class="' + element.class + '"';
81
+ }
82
+ for (const attr of Object.entries(element.attrs)) {
83
+ if (attr[1] == null) {
84
+ fragment.html += ' ' + attr[0];
85
+ }
86
+ else {
87
+ fragment.html += ` ${attr[0]}="${attr[1]}"`;
88
+ }
89
+ }
90
+ fragment.html += '>';
91
+ if (!voids.has(element.tag) && element.text != null) {
92
+ fragment.html += element.text;
93
+ }
94
+ if (!voids.has(element.tag)) {
95
+ fragment.els.push(element);
96
+ }
130
97
  }
131
- if (verbatimFirst) {
132
- verbatimFirst = false;
133
- } else {
134
- fragment.html += "\n";
98
+ if (targetIndent <= element.indent) {
99
+ element = makeElement(targetIndent);
100
+ while (fragment.els.length !== 0 && (targetIndent == null ||
101
+ fragment.els[fragment.els.length - 1].indent !== targetIndent - 1)) {
102
+ const element = fragment.els.pop();
103
+ fragment.html += `</${element?.tag}>`;
104
+ }
105
+ if (targetIndent === 0) {
106
+ debug(0, '<', fragment.type, fragment.id);
107
+ if (fragment.template) {
108
+ output.templates[fragment.id] = fragment.html;
109
+ }
110
+ else if (fragment.type === 'root') {
111
+ root = fragment;
112
+ }
113
+ else {
114
+ parsed.set(fragment.id, fragment);
115
+ }
116
+ fragment = makeFragment();
117
+ }
135
118
  }
136
- if (verbatimSerialize) {
137
- fragment.html += escape(line);
138
- } else {
139
- fragment.html += line;
119
+ else {
120
+ element = makeElement(targetIndent);
140
121
  }
141
- continue;
142
- }
143
- }
144
- if (m1[0].trim() === "") {
145
- continue;
146
122
  }
147
- switch ((_b = (_a = m1[2]) != null ? _a : m1[3]) != null ? _b : m1[4]) {
148
- // deno-lint-ignore no-fallthrough
149
- case "#": {
150
- id1.lastIndex = 0;
151
- m2 = id1.exec(m1[0]);
152
- if (m2 != null) {
153
- const indent = ((_d = (_c = m2[1]) == null ? void 0 : _c.length) != null ? _d : 0) / 2;
154
- if (element.tag != null || textIndent != null) {
155
- applyIndent(indent);
156
- textIndent = null;
157
- }
158
- debug(indent, "id", m2[2], m2[3], m2[4]);
159
- fragment.id = m2[3];
160
- if (indent === 0) {
161
- if (m2[4] == "[") {
162
- fragment.type = "range";
163
- } else if (m2[4] === '"') {
164
- fragment.type = "text";
165
- } else if (m2[2] != null) {
166
- fragment.type = "bare";
167
- } else {
168
- fragment.type = "embed";
169
- element.id = fragment.id;
170
- }
171
- }
172
- break;
123
+ while ((m1 = sniffTestRe.exec(doc))) {
124
+ if (m1[1] === '--') {
125
+ continue;
126
+ }
127
+ else if (fragment.template) {
128
+ fragment.html += m1[0];
173
129
  }
174
- }
175
- case "@":
176
- case "[":
177
- // deno-lint-ignore no-fallthrough
178
- case "::": {
179
- element1.lastIndex = 0;
180
- m2 = ((_e = m1[2]) != null ? _e : m1[4] != null) ? null : element1.exec(m1[0]);
181
- if (m2 != null) {
182
- const indent = ((_g = (_f = m2[1]) == null ? void 0 : _f.length) != null ? _g : 0) / 2, tg = m2[2], ar = m2[3], pr = m2[4] === "{" || m2[4] === "{{";
183
- const tx = pr ? null : m2[4];
184
- debug(indent, "e", tg, pr, tx);
185
- if (element.tag != null || element.indent > indent) {
186
- applyIndent(indent);
187
- }
188
- element.indent = indent;
189
- element.tag = tg;
190
- textIndent = null;
191
- if (indent === 0 && fragment.id == null) {
192
- if (root != null) {
193
- skipping = true;
194
- } else {
195
- fragment.type = "root";
196
- root = fragment;
130
+ // If this is a script tag or preformatted block
131
+ // we want to retain the intended formatting less
132
+ // the indent. Preformatting can apply to any element
133
+ // by ending the declaration with `:: {`.
134
+ if (verbatimIndent != null) {
135
+ // inside a script or preformatted block
136
+ idnt1.lastIndex = 0;
137
+ m2 = idnt1.exec(m1[0]);
138
+ const indent = m2 == null
139
+ ? null
140
+ : m2[0].length / 2;
141
+ if (m2 == null || indent <= verbatimIndent) {
142
+ fragment.html += '\n';
143
+ debug(indent, '}', m2?.[0]);
144
+ applyIndent(indent);
145
+ verbatimIndent = null;
146
+ verbatimFirst = false;
147
+ textIndent = indent;
148
+ if (preformattedClose.test(m1[0])) {
149
+ continue;
150
+ }
197
151
  }
198
- }
199
- if (ar != null) {
200
- debug(indent, "a", ar);
201
- while (m2 = paramsRe.exec(ar)) {
202
- if (m2[1] === "#") {
203
- element.id = m2[2];
204
- } else if (m2[1] === ".") {
205
- if (element.class == null) {
206
- element.class = m2[2];
207
- } else {
208
- element.class += " " + m2[2];
152
+ else {
153
+ const line = m1[0].replace(' '.repeat(verbatimIndent + 1), '');
154
+ debug(indent, '{', line);
155
+ if (element.tag != null) {
156
+ applyIndent(indent);
209
157
  }
210
- } else {
211
- if (m2[3] === "id") {
212
- if (element.id == null) {
213
- element.id = m2[4];
214
- }
215
- } else if (m2[3] === "class") {
216
- if (element.class == null) {
217
- element.class = m2[4];
218
- } else {
219
- element.class += " " + m2[4];
220
- }
221
- } else {
222
- element.attrs[m2[3]] = m2[4];
158
+ if (verbatimFirst) {
159
+ verbatimFirst = false;
223
160
  }
224
- }
161
+ else {
162
+ fragment.html += '\n';
163
+ }
164
+ if (verbatimSerialize) {
165
+ fragment.html += escape(line);
166
+ }
167
+ else {
168
+ fragment.html += line;
169
+ }
170
+ continue;
225
171
  }
226
- }
227
- if (!pr && tx != null) {
228
- element.text = tx;
229
- } else if (pr) {
230
- verbatimFirst = true;
231
- verbatimIndent = indent;
232
- verbatimSerialize = m2[4] === "{";
233
- }
234
- break;
235
172
  }
236
- attribute1.lastIndex = 0;
237
- m2 = m1[2] != null ? null : attribute1.exec(m1[0]);
238
- if (m2 != null && element.tag != null) {
239
- debug("a", m2[2], m2[3]);
240
- if (m2[2] === "id") {
241
- if (element.id == null) {
242
- element.id = m2[3].trim();
173
+ if (m1[0].trim() === '') {
174
+ continue;
175
+ }
176
+ switch (m1[2] ?? m1[3] ?? m1[4]) {
177
+ // deno-lint-ignore no-fallthrough
178
+ case '#': {
179
+ id1.lastIndex = 0;
180
+ m2 = id1.exec(m1[0]);
181
+ if (m2 != null) {
182
+ const indent = (m2[1]?.length ?? 0) / 2;
183
+ if (element.tag != null || textIndent != null) {
184
+ applyIndent(indent);
185
+ textIndent = null;
186
+ }
187
+ debug(indent, 'id', m2[2], m2[3], m2[4]);
188
+ fragment.id = m2[3];
189
+ if (indent === 0) {
190
+ if (m2[4] == '[') {
191
+ fragment.type = 'range';
192
+ }
193
+ else if (m2[4] === '"') {
194
+ fragment.type = 'text';
195
+ }
196
+ else if (m2[2] != null) {
197
+ fragment.type = 'bare';
198
+ }
199
+ else {
200
+ fragment.type = 'embed';
201
+ element.id = fragment.id;
202
+ }
203
+ }
204
+ break;
205
+ }
243
206
  }
244
- } else if (m2[2] === "class") {
245
- if (element.class != null) {
246
- element.class += " " + m2[3].trim();
247
- } else {
248
- element.class = m2[3].trim();
207
+ case '@':
208
+ case '[':
209
+ // deno-lint-ignore no-fallthrough
210
+ case '::': {
211
+ element1.lastIndex = 0;
212
+ // fall through if m1[3] is a # or @
213
+ m2 = m1[2] ?? m1[4] != null
214
+ ? null
215
+ : element1.exec(m1[0]);
216
+ // if null then invalid element selector
217
+ // allow the default text case to handle
218
+ if (m2 != null) {
219
+ const indent = (m2[1]?.length ?? 0) / 2, tg = m2[2], ar = m2[3], pr = m2[4] === '{' || m2[4] === '{{';
220
+ const tx = pr ? null : m2[4];
221
+ debug(indent, 'e', tg, pr, tx);
222
+ if (element.tag != null ||
223
+ element.indent > indent) {
224
+ applyIndent(indent);
225
+ }
226
+ element.indent = indent;
227
+ element.tag = tg;
228
+ textIndent = null;
229
+ if (indent === 0 && fragment.id == null) {
230
+ if (root != null) ;
231
+ else {
232
+ fragment.type = 'root';
233
+ root = fragment;
234
+ }
235
+ }
236
+ if (ar != null) {
237
+ debug(indent, 'a', ar);
238
+ while ((m2 = paramsRe.exec(ar))) {
239
+ if (m2[1] === '#') {
240
+ element.id = m2[2];
241
+ }
242
+ else if (m2[1] === '.') {
243
+ if (element.class == null) {
244
+ element.class = m2[2];
245
+ }
246
+ else {
247
+ element.class += ' ' + m2[2];
248
+ }
249
+ }
250
+ else {
251
+ if (m2[3] === 'id') {
252
+ if (element.id == null) {
253
+ element.id = m2[4];
254
+ }
255
+ }
256
+ else if (m2[3] === 'class') {
257
+ if (element.class == null) {
258
+ element.class = m2[4];
259
+ }
260
+ else {
261
+ element.class += ' ' + m2[4];
262
+ }
263
+ }
264
+ else {
265
+ element.attrs[m2[3]] = m2[4];
266
+ }
267
+ }
268
+ }
269
+ }
270
+ // this is a hack to get temp support of mounting
271
+ // working. In the future it will be moved to a
272
+ // server specific process.
273
+ if (element.mount != null) {
274
+ const id = element.mount;
275
+ applyIndent(indent + 1);
276
+ fragment.mountPoints.push({
277
+ id,
278
+ part: fragment.html,
279
+ });
280
+ fragment.html = '';
281
+ applyIndent(indent);
282
+ break;
283
+ }
284
+ if (!pr && tx != null) {
285
+ element.text = tx;
286
+ }
287
+ else if (pr) {
288
+ verbatimFirst = true;
289
+ verbatimIndent = indent;
290
+ verbatimSerialize = m2[4] === '{';
291
+ }
292
+ break;
293
+ }
294
+ attribute1.lastIndex = 0;
295
+ m2 = m1[2] != null
296
+ ? null
297
+ : attribute1.exec(m1[0]);
298
+ if (m2 != null && element.tag != null) {
299
+ debug('a', m2[2], m2[3]);
300
+ if (m2[2] === 'id') {
301
+ if (element.id == null) {
302
+ element.id = m2[3].trim();
303
+ }
304
+ }
305
+ else if (m2[2] === 'class') {
306
+ if (element.class != null) {
307
+ element.class += ' ' + m2[3].trim();
308
+ }
309
+ else {
310
+ element.class = m2[3].trim();
311
+ }
312
+ }
313
+ else if (element.attrs[m2[2]] != null) {
314
+ element.attrs[m2[2]] += m2[3];
315
+ }
316
+ else {
317
+ element.attrs[m2[2]] = m2[3];
318
+ }
319
+ break;
320
+ }
321
+ directive1.lastIndex = 0;
322
+ m2 = m1[3] != null
323
+ ? null
324
+ : directive1.exec(m1[0]);
325
+ if (m2 != null) {
326
+ const indent = (m2[1]?.length ?? 0) / 2;
327
+ if (element.tag != null || textIndent != null) {
328
+ applyIndent(indent);
329
+ }
330
+ debug(indent, 'd', m2[2], m2[3]);
331
+ switch (m2[2]) {
332
+ case 'doctype': {
333
+ fragment.html += `<!doctype ${m2[3] ?? 'html'}>`;
334
+ break;
335
+ }
336
+ case 'xml': {
337
+ fragment.html += `<?xml ${m2[3] ?? 'version="1.0" encoding="UTF-8"'}?>`;
338
+ break;
339
+ }
340
+ case 'template': {
341
+ let indented = false;
342
+ fragment.template = indent === 0;
343
+ templateLinesRe.lastIndex = sniffTestRe.lastIndex;
344
+ while ((m2 = templateLinesRe.exec(doc))) {
345
+ if (m2[1] == null && !indented && fragment.id == null) {
346
+ id1.lastIndex = 0;
347
+ m3 = id1.exec(m2[0]);
348
+ if (m3 != null)
349
+ fragment.id = m3[3];
350
+ fragment.html += m2[0];
351
+ }
352
+ else if (m2[1] == null && indented) {
353
+ sniffTestRe.lastIndex = templateLinesRe.lastIndex - m2[0].length;
354
+ break;
355
+ }
356
+ else {
357
+ fragment.html += '\n' + m2[0];
358
+ if (m2[1] != null)
359
+ indented = true;
360
+ }
361
+ }
362
+ applyIndent(0);
363
+ break;
364
+ }
365
+ case 'mount': {
366
+ if (m2[3] == null) {
367
+ throw new Error('Mount points must have a name');
368
+ }
369
+ else if (fragment.type !== 'root') {
370
+ throw new Error('Mounting is only allowed on a root element');
371
+ }
372
+ fragment.mountable = true;
373
+ element.mount = m2[3].trim();
374
+ break;
375
+ }
376
+ }
377
+ break;
378
+ }
249
379
  }
250
- } else if (element.attrs[m2[2]] != null) {
251
- element.attrs[m2[2]] += m2[3];
252
- } else {
253
- element.attrs[m2[2]] = m2[3];
254
- }
255
- break;
256
- }
257
- directive1.lastIndex = 0;
258
- m2 = m1[3] != null ? null : directive1.exec(m1[0]);
259
- if (m2 != null) {
260
- const indent = ((_i = (_h = m2[1]) == null ? void 0 : _h.length) != null ? _i : 0) / 2;
261
- if (element.tag != null || textIndent != null) {
262
- applyIndent(indent);
263
- }
264
- debug(indent, "d", m2[2], m2[3]);
265
- switch (m2[2]) {
266
- case "doctype": {
267
- fragment.html += `<!doctype ${(_j = m2[3]) != null ? _j : "html"}>`;
268
- break;
380
+ default: {
381
+ m2 = text1.exec(m1[0]);
382
+ if (m2 == null) {
383
+ break;
384
+ }
385
+ const indent = m2[1].length / 2;
386
+ const tx = m2[2].trim();
387
+ debug(indent, 't', m2[2]);
388
+ if (element.tag != null) {
389
+ applyIndent(indent);
390
+ fragment.html += tx;
391
+ }
392
+ else if (fragment.type === 'text' && fragment.html === '') {
393
+ fragment.html += tx;
394
+ }
395
+ else {
396
+ fragment.html += ' ' + tx;
397
+ }
398
+ textIndent = indent;
399
+ while ((m2 = refRe.exec(tx))) {
400
+ const start = fragment.html.length + m2.index - tx.length;
401
+ fragment.refs.push({
402
+ id: m2[1],
403
+ start,
404
+ end: start + m2[0].length,
405
+ });
406
+ }
407
+ break;
269
408
  }
270
- case "xml": {
271
- fragment.html += `<?xml ${(_k = m2[3]) != null ? _k : 'version="1.0" encoding="UTF-8"'}?>`;
272
- break;
409
+ }
410
+ }
411
+ applyIndent(0);
412
+ const arr = Array.from(parsed.values());
413
+ function flatten(fragment) {
414
+ // work backwards so we don't change the html string length
415
+ // for the later replacements
416
+ for (let j = fragment.refs.length - 1; j >= 0; j--) {
417
+ const ref = fragment.refs[j];
418
+ if (claimed.has(ref.id) || !parsed.has(ref.id)) {
419
+ fragment.html = fragment.html.slice(0, ref.start)
420
+ + fragment.html.slice(ref.end);
273
421
  }
274
- case "template": {
275
- let indented = false;
276
- fragment.template = indent === 0;
277
- templateLinesRe.lastIndex = sniffTestRe.lastIndex;
278
- while (m2 = templateLinesRe.exec(doc)) {
279
- if (m2[1] == null && !indented && fragment.id == null) {
280
- id1.lastIndex = 0;
281
- m3 = id1.exec(m2[0]);
282
- if (m3 != null) fragment.id = m3[3];
283
- fragment.html += m2[0];
284
- } else if (m2[1] == null && indented) {
285
- sniffTestRe.lastIndex = templateLinesRe.lastIndex - m2[0].length;
286
- break;
287
- } else {
288
- fragment.html += "\n" + m2[0];
289
- if (m2[1] != null) indented = true;
422
+ else {
423
+ const child = flatten(parsed.get(ref.id));
424
+ fragment.html = fragment.html.slice(0, ref.start)
425
+ + child.html
426
+ + fragment.html.slice(ref.end);
427
+ if (child.type === 'embed') {
428
+ claimed.add(child.id);
290
429
  }
291
- }
292
- applyIndent(0);
293
430
  }
294
- }
295
- break;
296
431
  }
297
- }
298
- default: {
299
- m2 = text1.exec(m1[0]);
300
- if (m2 == null) {
301
- break;
432
+ fragment.refs = [];
433
+ return fragment;
434
+ }
435
+ if (root?.mountable) {
436
+ output.mountable = true;
437
+ output.tail = root.html;
438
+ output.mountPoints = root.mountPoints;
439
+ return output;
440
+ }
441
+ for (let i = 0; i < parsed.size + 1; i++) {
442
+ let fragment;
443
+ if (i === 0 && root == null) {
444
+ continue;
302
445
  }
303
- const indent = m2[1].length / 2;
304
- const tx = m2[2].trim();
305
- debug(indent, "t", m2[2]);
306
- if (element.tag != null) {
307
- applyIndent(indent);
308
- fragment.html += tx;
309
- } else if (fragment.type === "text" && fragment.html === "") {
310
- fragment.html += tx;
311
- } else {
312
- fragment.html += " " + tx;
446
+ else if (i === 0) {
447
+ fragment = root;
313
448
  }
314
- textIndent = indent;
315
- while (m2 = refRe.exec(tx)) {
316
- const start = fragment.html.length + m2.index - tx.length;
317
- fragment.refs.push({
318
- id: m2[1],
319
- start,
320
- end: start + m2[0].length
321
- });
449
+ else {
450
+ fragment = arr[i - 1];
322
451
  }
323
- break;
324
- }
325
- }
326
- }
327
- applyIndent(0);
328
- const arr = Array.from(parsed.values());
329
- function flatten(fragment2) {
330
- for (let j = fragment2.refs.length - 1; j >= 0; j--) {
331
- const ref = fragment2.refs[j];
332
- if (claimed.has(ref.id) || !parsed.has(ref.id)) {
333
- fragment2.html = fragment2.html.slice(0, ref.start) + fragment2.html.slice(ref.end);
334
- } else {
335
- const child = flatten(parsed.get(ref.id));
336
- fragment2.html = fragment2.html.slice(0, ref.start) + child.html + fragment2.html.slice(ref.end);
337
- if (child.type === "embed") {
338
- claimed.add(child.id);
452
+ if (fragment.refs.length === 0) {
453
+ continue;
339
454
  }
340
- }
341
- }
342
- fragment2.refs = [];
343
- return fragment2;
344
- }
345
- for (let i = 0; i < parsed.size + 1; i++) {
346
- let fragment2;
347
- if (i === 0 && root == null) {
348
- continue;
349
- } else if (i === 0) {
350
- fragment2 = root;
351
- } else {
352
- fragment2 = arr[i - 1];
353
- }
354
- if (fragment2.refs.length === 0) {
355
- continue;
455
+ flatten(fragment);
356
456
  }
357
- flatten(fragment2);
358
- }
359
- if ((root == null ? void 0 : root.html) != null) {
360
- output.root = root.html;
361
- output.selector = `[data-lf-root]`;
362
- }
363
- for (let i = 0; i < arr.length; i++) {
364
- let selector;
365
- const fragment2 = arr[i];
366
- if (fragment2 == null || claimed.has(fragment2.id)) {
367
- continue;
457
+ if (root?.html != null) {
458
+ output.root = root.html;
459
+ output.selector = `[data-lf-root]`;
368
460
  }
369
- if (fragment2.type === "embed") {
370
- selector = `[id=${fragment2.id}]`;
371
- } else if (fragment2.type === "bare") {
372
- selector = `[data-lf=${fragment2.id}]`;
373
- } else if (fragment2.type === "range") {
374
- selector = `[data-lf=${fragment2.id}]`;
461
+ for (let i = 0; i < arr.length; i++) {
462
+ let selector;
463
+ const fragment = arr[i];
464
+ if (fragment == null || claimed.has(fragment.id)) {
465
+ continue;
466
+ }
467
+ if (fragment.type === 'embed') {
468
+ selector = `[id=${fragment.id}]`;
469
+ }
470
+ else if (fragment.type === 'bare') {
471
+ selector = `[data-lf=${fragment.id}]`;
472
+ }
473
+ else if (fragment.type === 'range') {
474
+ selector = `[data-lf=${fragment.id}]`;
475
+ }
476
+ output.fragments[fragment.id] = {
477
+ id: fragment.id,
478
+ selector,
479
+ type: fragment.type,
480
+ html: fragment.html,
481
+ };
375
482
  }
376
- output.fragments[fragment2.id] = {
377
- id: fragment2.id,
378
- selector,
379
- type: fragment2.type,
380
- html: fragment2.html
381
- };
382
- }
383
- return output;
483
+ return output;
384
484
  }
385
485
  const templateRe = /(?:#{([\w][\w\-_]*)})|(?:#\[([\w][\w\-_]+)\])/g;
386
- export function processTemplate(template, args, getFragment) {
387
- var _a, _b;
388
- const lf = template.replace(templateRe, (_match, param, ref) => {
389
- if (ref != null) {
390
- const fragment = getFragment(ref);
391
- if (fragment == null) return "";
392
- return fragment;
393
- }
394
- return args[param] != null ? escape(args[param].toString()) : "";
395
- });
396
- return (_b = (_a = Object.values(longform(lf).fragments)[0]) == null ? void 0 : _a.html) != null ? _b : null;
486
+ /**
487
+ * Processes a client side Longform template to HTML fragment string.
488
+ *
489
+ * @param fragment - The fragment identifier.
490
+ * @param args - A record of template arguments.
491
+ * @param getFragment - A function which returns an already processed fragment's HTML string.
492
+ * @returns The processed template.
493
+ */
494
+ function processTemplate(template, args, getFragment) {
495
+ const lf = template.replace(templateRe, (_match, param, ref) => {
496
+ if (ref != null) {
497
+ const fragment = getFragment(ref);
498
+ if (fragment == null)
499
+ return '';
500
+ return fragment;
501
+ }
502
+ return args[param] != null ? escape(args[param].toString()) : '';
503
+ });
504
+ return Object.values(longform(lf).fragments)[0]?.html ?? null;
397
505
  }
506
+
507
+ export { longform, processTemplate };
398
508
  //# sourceMappingURL=longform.js.map