@valbuild/server 0.20.1 → 0.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.
@@ -246,99 +246,6 @@ function analyzeValModule(sourceFile) {
246
246
  return analysis;
247
247
  }
248
248
 
249
- /* eslint-disable @typescript-eslint/no-explicit-any */
250
-
251
- const HeaderRegEx = /^h([\d+])$/;
252
- function richTextToTaggedStringTemplate(source) {
253
- const texts = [""];
254
- const nodes = [];
255
- let didAppendNewLines = false;
256
- let listContext = null;
257
- function rec(node) {
258
- if (typeof node === "string") {
259
- texts[texts.length - 1] += node;
260
- } else if ("tag" in node && node.tag) {
261
- var _node$children, _node$tag;
262
- if (node.tag === "h1" || node.tag === "h2" || node.tag === "h3" || node.tag === "h4" || node.tag === "h5" || node.tag === "h6") {
263
- var _node$tag$match;
264
- const depth = Number((_node$tag$match = node.tag.match(HeaderRegEx)) === null || _node$tag$match === void 0 ? void 0 : _node$tag$match[1]);
265
- if (Number.isNaN(depth)) {
266
- throw new Error("Invalid header depth");
267
- }
268
- for (let i = 0; i < Number(depth); i++) {
269
- texts[texts.length - 1] += "#";
270
- }
271
- texts[texts.length - 1] += " ";
272
- } else if (node.tag === "p") ; else if (node.tag === "ul") {
273
- listContext = "ul";
274
- texts[texts.length - 1] += "\n";
275
- } else if (node.tag === "ol") {
276
- listContext = "ol";
277
- texts[texts.length - 1] += "\n";
278
- } else if (node.tag === "li") {
279
- if (listContext === "ul") {
280
- texts[texts.length - 1] += "\n- ";
281
- } else if (listContext === "ol") {
282
- texts[texts.length - 1] += "\n1. ";
283
- } else {
284
- throw new Error("Unexpected list context");
285
- }
286
- } else if (node.tag === "span") {
287
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
288
- texts[texts.length - 1] += "**";
289
- }
290
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
291
- texts[texts.length - 1] += "*";
292
- }
293
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
294
- texts[texts.length - 1] += "***";
295
- }
296
- if (node.classes.includes("line-through")) {
297
- texts[texts.length - 1] += "~~";
298
- }
299
- } else {
300
- //exhaustive match
301
- const exhaustiveCheck = node.tag;
302
- throw new Error("Unexpected node tag: " + JSON.stringify(node, exhaustiveCheck, 2));
303
- }
304
- (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.forEach(rec);
305
- didAppendNewLines = false;
306
- if (node.tag === "span") {
307
- if (node.classes.includes("line-through")) {
308
- texts[texts.length - 1] += "~~";
309
- }
310
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
311
- texts[texts.length - 1] += "***";
312
- }
313
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
314
- texts[texts.length - 1] += "*";
315
- }
316
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
317
- texts[texts.length - 1] += "**";
318
- }
319
- } else if (node.tag === "p") {
320
- didAppendNewLines = true;
321
- texts[texts.length - 1] += "\n\n";
322
- } else if (node.tag === "ul" || node.tag === "ol") {
323
- listContext = null;
324
- texts[texts.length - 1] += "\n";
325
- } else if ((_node$tag = node.tag) !== null && _node$tag !== void 0 && _node$tag.startsWith("h")) {
326
- didAppendNewLines = true;
327
- texts[texts.length - 1] += "\n\n";
328
- }
329
- } else {
330
- nodes.push(node); // ImageSource
331
- texts.push("\n");
332
- }
333
- }
334
- source.children.forEach(rec);
335
- if (texts[texts.length - 1] && didAppendNewLines) {
336
- // remove last \n\n
337
- texts[texts.length - 1] = texts[texts.length - 1].slice(0, -2);
338
- }
339
- return [texts, nodes];
340
- }
341
-
342
249
  function isValidIdentifier(text) {
343
250
  if (text.length === 0) {
344
251
  return false;
@@ -363,11 +270,20 @@ function createValFileReference(value) {
363
270
  }
364
271
  return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("file")), undefined, args);
365
272
  }
273
+ function createValLink(value) {
274
+ const args = [ts__default["default"].factory.createStringLiteral(value.children[0]), toExpression({
275
+ href: value.href
276
+ })];
277
+ return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("link")), undefined, args);
278
+ }
366
279
  function createValRichTextTaggedStringTemplate(value) {
367
- const [[head, ...others], nodes] = richTextToTaggedStringTemplate(value);
280
+ const {
281
+ templateStrings: [head, ...others],
282
+ exprs
283
+ } = value;
368
284
  const tag = ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("richtext"));
369
- if (nodes.length > 0) {
370
- return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createTemplateExpression(ts__default["default"].factory.createTemplateHead(head, head), others.map((s, i) => ts__default["default"].factory.createTemplateSpan(toExpression(nodes[i]), i < others.length - 1 ? ts__default["default"].factory.createTemplateMiddle(s, s) : ts__default["default"].factory.createTemplateTail(s, s)))));
285
+ if (exprs.length > 0) {
286
+ return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createTemplateExpression(ts__default["default"].factory.createTemplateHead(head, head), others.map((s, i) => ts__default["default"].factory.createTemplateSpan(toExpression(exprs[i]), i < others.length - 1 ? ts__default["default"].factory.createTemplateMiddle(s, s) : ts__default["default"].factory.createTemplateTail(s, s)))));
371
287
  }
372
288
  return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createNoSubstitutionTemplateLiteral(head, head));
373
289
  }
@@ -386,6 +302,8 @@ function toExpression(value) {
386
302
  } else if (typeof value === "object") {
387
303
  if (isValFileValue(value)) {
388
304
  return createValFileReference(value);
305
+ } else if (isValLinkValue(value)) {
306
+ return createValLink(value);
389
307
  } else if (isValRichTextValue(value)) {
390
308
  return createValRichTextTaggedStringTemplate(value);
391
309
  }
@@ -620,8 +538,11 @@ function isValFileValue(value) {
620
538
  // value[VAL_EXTENSION] === "file" &&
621
539
  core.FILE_REF_PROP in value && typeof value[core.FILE_REF_PROP] === "string");
622
540
  }
541
+ function isValLinkValue(value) {
542
+ return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "link");
543
+ }
623
544
  function isValRichTextValue(value) {
624
- return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "richtext" && "children" in value && typeof value.children === "object" && Array.isArray(value.children));
545
+ return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "richtext" && "templateStrings" in value && typeof value.templateStrings === "object" && Array.isArray(value.templateStrings));
625
546
  }
626
547
  function addToNode(document, node, key, value) {
627
548
  if (ts__default["default"].isArrayLiteralExpression(node)) {
@@ -246,99 +246,6 @@ function analyzeValModule(sourceFile) {
246
246
  return analysis;
247
247
  }
248
248
 
249
- /* eslint-disable @typescript-eslint/no-explicit-any */
250
-
251
- const HeaderRegEx = /^h([\d+])$/;
252
- function richTextToTaggedStringTemplate(source) {
253
- const texts = [""];
254
- const nodes = [];
255
- let didAppendNewLines = false;
256
- let listContext = null;
257
- function rec(node) {
258
- if (typeof node === "string") {
259
- texts[texts.length - 1] += node;
260
- } else if ("tag" in node && node.tag) {
261
- var _node$children, _node$tag;
262
- if (node.tag === "h1" || node.tag === "h2" || node.tag === "h3" || node.tag === "h4" || node.tag === "h5" || node.tag === "h6") {
263
- var _node$tag$match;
264
- const depth = Number((_node$tag$match = node.tag.match(HeaderRegEx)) === null || _node$tag$match === void 0 ? void 0 : _node$tag$match[1]);
265
- if (Number.isNaN(depth)) {
266
- throw new Error("Invalid header depth");
267
- }
268
- for (let i = 0; i < Number(depth); i++) {
269
- texts[texts.length - 1] += "#";
270
- }
271
- texts[texts.length - 1] += " ";
272
- } else if (node.tag === "p") ; else if (node.tag === "ul") {
273
- listContext = "ul";
274
- texts[texts.length - 1] += "\n";
275
- } else if (node.tag === "ol") {
276
- listContext = "ol";
277
- texts[texts.length - 1] += "\n";
278
- } else if (node.tag === "li") {
279
- if (listContext === "ul") {
280
- texts[texts.length - 1] += "\n- ";
281
- } else if (listContext === "ol") {
282
- texts[texts.length - 1] += "\n1. ";
283
- } else {
284
- throw new Error("Unexpected list context");
285
- }
286
- } else if (node.tag === "span") {
287
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
288
- texts[texts.length - 1] += "**";
289
- }
290
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
291
- texts[texts.length - 1] += "*";
292
- }
293
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
294
- texts[texts.length - 1] += "***";
295
- }
296
- if (node.classes.includes("line-through")) {
297
- texts[texts.length - 1] += "~~";
298
- }
299
- } else {
300
- //exhaustive match
301
- const exhaustiveCheck = node.tag;
302
- throw new Error("Unexpected node tag: " + JSON.stringify(node, exhaustiveCheck, 2));
303
- }
304
- (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.forEach(rec);
305
- didAppendNewLines = false;
306
- if (node.tag === "span") {
307
- if (node.classes.includes("line-through")) {
308
- texts[texts.length - 1] += "~~";
309
- }
310
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
311
- texts[texts.length - 1] += "***";
312
- }
313
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
314
- texts[texts.length - 1] += "*";
315
- }
316
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
317
- texts[texts.length - 1] += "**";
318
- }
319
- } else if (node.tag === "p") {
320
- didAppendNewLines = true;
321
- texts[texts.length - 1] += "\n\n";
322
- } else if (node.tag === "ul" || node.tag === "ol") {
323
- listContext = null;
324
- texts[texts.length - 1] += "\n";
325
- } else if ((_node$tag = node.tag) !== null && _node$tag !== void 0 && _node$tag.startsWith("h")) {
326
- didAppendNewLines = true;
327
- texts[texts.length - 1] += "\n\n";
328
- }
329
- } else {
330
- nodes.push(node); // ImageSource
331
- texts.push("\n");
332
- }
333
- }
334
- source.children.forEach(rec);
335
- if (texts[texts.length - 1] && didAppendNewLines) {
336
- // remove last \n\n
337
- texts[texts.length - 1] = texts[texts.length - 1].slice(0, -2);
338
- }
339
- return [texts, nodes];
340
- }
341
-
342
249
  function isValidIdentifier(text) {
343
250
  if (text.length === 0) {
344
251
  return false;
@@ -363,11 +270,20 @@ function createValFileReference(value) {
363
270
  }
364
271
  return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("file")), undefined, args);
365
272
  }
273
+ function createValLink(value) {
274
+ const args = [ts__default["default"].factory.createStringLiteral(value.children[0]), toExpression({
275
+ href: value.href
276
+ })];
277
+ return ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("link")), undefined, args);
278
+ }
366
279
  function createValRichTextTaggedStringTemplate(value) {
367
- const [[head, ...others], nodes] = richTextToTaggedStringTemplate(value);
280
+ const {
281
+ templateStrings: [head, ...others],
282
+ exprs
283
+ } = value;
368
284
  const tag = ts__default["default"].factory.createPropertyAccessExpression(ts__default["default"].factory.createIdentifier("val"), ts__default["default"].factory.createIdentifier("richtext"));
369
- if (nodes.length > 0) {
370
- return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createTemplateExpression(ts__default["default"].factory.createTemplateHead(head, head), others.map((s, i) => ts__default["default"].factory.createTemplateSpan(toExpression(nodes[i]), i < others.length - 1 ? ts__default["default"].factory.createTemplateMiddle(s, s) : ts__default["default"].factory.createTemplateTail(s, s)))));
285
+ if (exprs.length > 0) {
286
+ return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createTemplateExpression(ts__default["default"].factory.createTemplateHead(head, head), others.map((s, i) => ts__default["default"].factory.createTemplateSpan(toExpression(exprs[i]), i < others.length - 1 ? ts__default["default"].factory.createTemplateMiddle(s, s) : ts__default["default"].factory.createTemplateTail(s, s)))));
371
287
  }
372
288
  return ts__default["default"].factory.createTaggedTemplateExpression(tag, undefined, ts__default["default"].factory.createNoSubstitutionTemplateLiteral(head, head));
373
289
  }
@@ -386,6 +302,8 @@ function toExpression(value) {
386
302
  } else if (typeof value === "object") {
387
303
  if (isValFileValue(value)) {
388
304
  return createValFileReference(value);
305
+ } else if (isValLinkValue(value)) {
306
+ return createValLink(value);
389
307
  } else if (isValRichTextValue(value)) {
390
308
  return createValRichTextTaggedStringTemplate(value);
391
309
  }
@@ -620,8 +538,11 @@ function isValFileValue(value) {
620
538
  // value[VAL_EXTENSION] === "file" &&
621
539
  core.FILE_REF_PROP in value && typeof value[core.FILE_REF_PROP] === "string");
622
540
  }
541
+ function isValLinkValue(value) {
542
+ return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "link");
543
+ }
623
544
  function isValRichTextValue(value) {
624
- return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "richtext" && "children" in value && typeof value.children === "object" && Array.isArray(value.children));
545
+ return !!(typeof value === "object" && value && core.VAL_EXTENSION in value && value[core.VAL_EXTENSION] === "richtext" && "templateStrings" in value && typeof value.templateStrings === "object" && Array.isArray(value.templateStrings));
625
546
  }
626
547
  function addToNode(document, node, key, value) {
627
548
  if (ts__default["default"].isArrayLiteralExpression(node)) {
@@ -215,99 +215,6 @@ function analyzeValModule(sourceFile) {
215
215
  return analysis;
216
216
  }
217
217
 
218
- /* eslint-disable @typescript-eslint/no-explicit-any */
219
-
220
- const HeaderRegEx = /^h([\d+])$/;
221
- function richTextToTaggedStringTemplate(source) {
222
- const texts = [""];
223
- const nodes = [];
224
- let didAppendNewLines = false;
225
- let listContext = null;
226
- function rec(node) {
227
- if (typeof node === "string") {
228
- texts[texts.length - 1] += node;
229
- } else if ("tag" in node && node.tag) {
230
- var _node$children, _node$tag;
231
- if (node.tag === "h1" || node.tag === "h2" || node.tag === "h3" || node.tag === "h4" || node.tag === "h5" || node.tag === "h6") {
232
- var _node$tag$match;
233
- const depth = Number((_node$tag$match = node.tag.match(HeaderRegEx)) === null || _node$tag$match === void 0 ? void 0 : _node$tag$match[1]);
234
- if (Number.isNaN(depth)) {
235
- throw new Error("Invalid header depth");
236
- }
237
- for (let i = 0; i < Number(depth); i++) {
238
- texts[texts.length - 1] += "#";
239
- }
240
- texts[texts.length - 1] += " ";
241
- } else if (node.tag === "p") ; else if (node.tag === "ul") {
242
- listContext = "ul";
243
- texts[texts.length - 1] += "\n";
244
- } else if (node.tag === "ol") {
245
- listContext = "ol";
246
- texts[texts.length - 1] += "\n";
247
- } else if (node.tag === "li") {
248
- if (listContext === "ul") {
249
- texts[texts.length - 1] += "\n- ";
250
- } else if (listContext === "ol") {
251
- texts[texts.length - 1] += "\n1. ";
252
- } else {
253
- throw new Error("Unexpected list context");
254
- }
255
- } else if (node.tag === "span") {
256
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
257
- texts[texts.length - 1] += "**";
258
- }
259
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
260
- texts[texts.length - 1] += "*";
261
- }
262
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
263
- texts[texts.length - 1] += "***";
264
- }
265
- if (node.classes.includes("line-through")) {
266
- texts[texts.length - 1] += "~~";
267
- }
268
- } else {
269
- //exhaustive match
270
- const exhaustiveCheck = node.tag;
271
- throw new Error("Unexpected node tag: " + JSON.stringify(node, exhaustiveCheck, 2));
272
- }
273
- (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.forEach(rec);
274
- didAppendNewLines = false;
275
- if (node.tag === "span") {
276
- if (node.classes.includes("line-through")) {
277
- texts[texts.length - 1] += "~~";
278
- }
279
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
280
- texts[texts.length - 1] += "***";
281
- }
282
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
283
- texts[texts.length - 1] += "*";
284
- }
285
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
286
- texts[texts.length - 1] += "**";
287
- }
288
- } else if (node.tag === "p") {
289
- didAppendNewLines = true;
290
- texts[texts.length - 1] += "\n\n";
291
- } else if (node.tag === "ul" || node.tag === "ol") {
292
- listContext = null;
293
- texts[texts.length - 1] += "\n";
294
- } else if ((_node$tag = node.tag) !== null && _node$tag !== void 0 && _node$tag.startsWith("h")) {
295
- didAppendNewLines = true;
296
- texts[texts.length - 1] += "\n\n";
297
- }
298
- } else {
299
- nodes.push(node); // ImageSource
300
- texts.push("\n");
301
- }
302
- }
303
- source.children.forEach(rec);
304
- if (texts[texts.length - 1] && didAppendNewLines) {
305
- // remove last \n\n
306
- texts[texts.length - 1] = texts[texts.length - 1].slice(0, -2);
307
- }
308
- return [texts, nodes];
309
- }
310
-
311
218
  function isValidIdentifier(text) {
312
219
  if (text.length === 0) {
313
220
  return false;
@@ -332,11 +239,20 @@ function createValFileReference(value) {
332
239
  }
333
240
  return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("val"), ts.factory.createIdentifier("file")), undefined, args);
334
241
  }
242
+ function createValLink(value) {
243
+ const args = [ts.factory.createStringLiteral(value.children[0]), toExpression({
244
+ href: value.href
245
+ })];
246
+ return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("val"), ts.factory.createIdentifier("link")), undefined, args);
247
+ }
335
248
  function createValRichTextTaggedStringTemplate(value) {
336
- const [[head, ...others], nodes] = richTextToTaggedStringTemplate(value);
249
+ const {
250
+ templateStrings: [head, ...others],
251
+ exprs
252
+ } = value;
337
253
  const tag = ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("val"), ts.factory.createIdentifier("richtext"));
338
- if (nodes.length > 0) {
339
- return ts.factory.createTaggedTemplateExpression(tag, undefined, ts.factory.createTemplateExpression(ts.factory.createTemplateHead(head, head), others.map((s, i) => ts.factory.createTemplateSpan(toExpression(nodes[i]), i < others.length - 1 ? ts.factory.createTemplateMiddle(s, s) : ts.factory.createTemplateTail(s, s)))));
254
+ if (exprs.length > 0) {
255
+ return ts.factory.createTaggedTemplateExpression(tag, undefined, ts.factory.createTemplateExpression(ts.factory.createTemplateHead(head, head), others.map((s, i) => ts.factory.createTemplateSpan(toExpression(exprs[i]), i < others.length - 1 ? ts.factory.createTemplateMiddle(s, s) : ts.factory.createTemplateTail(s, s)))));
340
256
  }
341
257
  return ts.factory.createTaggedTemplateExpression(tag, undefined, ts.factory.createNoSubstitutionTemplateLiteral(head, head));
342
258
  }
@@ -355,6 +271,8 @@ function toExpression(value) {
355
271
  } else if (typeof value === "object") {
356
272
  if (isValFileValue(value)) {
357
273
  return createValFileReference(value);
274
+ } else if (isValLinkValue(value)) {
275
+ return createValLink(value);
358
276
  } else if (isValRichTextValue(value)) {
359
277
  return createValRichTextTaggedStringTemplate(value);
360
278
  }
@@ -589,8 +507,11 @@ function isValFileValue(value) {
589
507
  // value[VAL_EXTENSION] === "file" &&
590
508
  FILE_REF_PROP in value && typeof value[FILE_REF_PROP] === "string");
591
509
  }
510
+ function isValLinkValue(value) {
511
+ return !!(typeof value === "object" && value && VAL_EXTENSION in value && value[VAL_EXTENSION] === "link");
512
+ }
592
513
  function isValRichTextValue(value) {
593
- return !!(typeof value === "object" && value && VAL_EXTENSION in value && value[VAL_EXTENSION] === "richtext" && "children" in value && typeof value.children === "object" && Array.isArray(value.children));
514
+ return !!(typeof value === "object" && value && VAL_EXTENSION in value && value[VAL_EXTENSION] === "richtext" && "templateStrings" in value && typeof value.templateStrings === "object" && Array.isArray(value.templateStrings));
594
515
  }
595
516
  function addToNode(document, node, key, value) {
596
517
  if (ts.isArrayLiteralExpression(node)) {
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "./package.json": "./package.json"
13
13
  },
14
14
  "types": "dist/valbuild-server.cjs.d.ts",
15
- "version": "0.20.1",
15
+ "version": "0.21.0",
16
16
  "scripts": {
17
17
  "typecheck": "tsc --noEmit",
18
18
  "test": "jest",
@@ -25,8 +25,8 @@
25
25
  "concurrently": "^7.6.0"
26
26
  },
27
27
  "dependencies": {
28
- "@valbuild/core": "~0.20.1",
29
- "@valbuild/ui": "~0.20.0",
28
+ "@valbuild/core": "~0.21.0",
29
+ "@valbuild/ui": "~0.21.0",
30
30
  "express": "^4.18.2",
31
31
  "image-size": "^1.0.2",
32
32
  "quickjs-emscripten": "^0.21.1",
@@ -422,6 +422,7 @@ export async function enable(
422
422
  res.sendStatus(400);
423
423
  }
424
424
  }
425
+
425
426
  export async function disable(
426
427
  req: express.Request,
427
428
  res: express.Response,
@@ -456,7 +456,8 @@ describe("TSOps", () => {
456
456
  path: [],
457
457
  value: {
458
458
  [VAL_EXTENSION]: "richtext",
459
- children: [{ tag: "p", children: ["Test 2"] }],
459
+ templateStrings: ["Test 2"],
460
+ exprs: [],
460
461
  },
461
462
  expected: result.ok("val.richtext `Test 2`"),
462
463
  },
@@ -466,13 +467,10 @@ describe("TSOps", () => {
466
467
  path: [],
467
468
  value: {
468
469
  [VAL_EXTENSION]: "richtext",
469
- children: [
470
- { tag: "h1", children: ["Title 1"] },
471
- { tag: "p", children: ["Test 2"] },
472
- ],
470
+ templateStrings: ["# Title 1\nTest 2"],
471
+ exprs: [],
473
472
  },
474
473
  expected: result.ok(`val.richtext \`# Title 1
475
-
476
474
  Test 2\``),
477
475
  },
478
476
  {
@@ -481,9 +479,8 @@ Test 2\``),
481
479
  path: [],
482
480
  value: {
483
481
  [VAL_EXTENSION]: "richtext",
484
- children: [
485
- { tag: "h1", children: ["Title 1"] },
486
- { tag: "p", children: ["Test 2"] },
482
+ templateStrings: ["# Title 1\nTest 2\n", ""],
483
+ exprs: [
487
484
  {
488
485
  [VAL_EXTENSION]: "file",
489
486
  [FILE_REF_PROP]: "/public/test",
@@ -492,9 +489,7 @@ Test 2\``),
492
489
  ],
493
490
  },
494
491
  expected: result.ok(`val.richtext \`# Title 1
495
-
496
492
  Test 2
497
-
498
493
  \${val.file("/public/test", { width: 100, height: 100, sha256: "123" })}\``),
499
494
  },
500
495
  {
@@ -503,8 +498,8 @@ Test 2
503
498
  path: [],
504
499
  value: {
505
500
  [VAL_EXTENSION]: "richtext",
506
- children: [
507
- { tag: "h1", children: ["Title 1"] },
501
+ templateStrings: ["# Title 1\n", "\n", "\nTest 2"],
502
+ exprs: [
508
503
  {
509
504
  [VAL_EXTENSION]: "file",
510
505
  [FILE_REF_PROP]: "/public/test1",
@@ -515,14 +510,36 @@ Test 2
515
510
  [FILE_REF_PROP]: "/public/test2",
516
511
  metadata: { width: 100, height: 100, sha256: "123" },
517
512
  },
518
- { tag: "p", children: ["Test 2"] },
519
513
  ],
520
514
  },
521
515
  expected: result.ok(`val.richtext \`# Title 1
522
-
523
516
  \${val.file("/public/test1", { width: 100, height: 100, sha256: "123" })}
524
517
  \${val.file("/public/test2", { width: 100, height: 100, sha256: "123" })}
525
518
  Test 2\``),
519
+ },
520
+ {
521
+ name: "val.richtext link",
522
+ input: "val.richtext`Test`",
523
+ path: [],
524
+ value: {
525
+ [VAL_EXTENSION]: "richtext",
526
+ templateStrings: ["# Title 1\n", "\n", ""],
527
+ exprs: [
528
+ {
529
+ [VAL_EXTENSION]: "link",
530
+ href: "https://example.com",
531
+ children: ["https://example.com"],
532
+ },
533
+ {
534
+ [VAL_EXTENSION]: "file",
535
+ [FILE_REF_PROP]: "/public/test2",
536
+ metadata: { width: 100, height: 100, sha256: "123" },
537
+ },
538
+ ],
539
+ },
540
+ expected: result.ok(`val.richtext \`# Title 1
541
+ \${val.link("https://example.com", { href: "https://example.com" })}
542
+ \${val.file("/public/test2", { width: 100, height: 100, sha256: "123" })}\``),
526
543
  },
527
544
  {
528
545
  name: "val.richtext empty head",
@@ -531,7 +548,8 @@ Test 2\``),
531
548
  path: ["text"],
532
549
  value: {
533
550
  [VAL_EXTENSION]: "richtext",
534
- children: [
551
+ templateStrings: ["", "\n", "\nTest 2"],
552
+ exprs: [
535
553
  {
536
554
  [VAL_EXTENSION]: "file",
537
555
  [FILE_REF_PROP]: "/public/test1",
@@ -542,7 +560,6 @@ Test 2\``),
542
560
  [FILE_REF_PROP]: "/public/test2",
543
561
  metadata: { width: 100, height: 100, sha256: "123" },
544
562
  },
545
- { tag: "p", children: ["Test 2"] },
546
563
  ],
547
564
  },
548
565
  expected:
@@ -26,7 +26,7 @@ import {
26
26
  VAL_EXTENSION,
27
27
  } from "@valbuild/core";
28
28
  import { JsonPrimitive } from "@valbuild/core/src/Json";
29
- import { richTextToTaggedStringTemplate } from "./richtext";
29
+ import { LinkSource } from "@valbuild/core/src/source/link";
30
30
 
31
31
  type TSOpsResult<T> = result.Result<T, PatchError | ValSyntaxErrorTree>;
32
32
 
@@ -85,15 +85,34 @@ function createValFileReference(value: FileSource) {
85
85
  );
86
86
  }
87
87
 
88
+ function createValLink(value: LinkSource) {
89
+ const args: ts.Expression[] = [
90
+ ts.factory.createStringLiteral(value.children[0]),
91
+ toExpression({ href: value.href }),
92
+ ];
93
+
94
+ return ts.factory.createCallExpression(
95
+ ts.factory.createPropertyAccessExpression(
96
+ ts.factory.createIdentifier("val"),
97
+ ts.factory.createIdentifier("link")
98
+ ),
99
+ undefined,
100
+ args
101
+ );
102
+ }
103
+
88
104
  function createValRichTextTaggedStringTemplate(
89
105
  value: RichTextSource<AnyRichTextOptions>
90
106
  ): ts.Expression {
91
- const [[head, ...others], nodes] = richTextToTaggedStringTemplate(value);
107
+ const {
108
+ templateStrings: [head, ...others],
109
+ exprs,
110
+ } = value;
92
111
  const tag = ts.factory.createPropertyAccessExpression(
93
112
  ts.factory.createIdentifier("val"),
94
113
  ts.factory.createIdentifier("richtext")
95
114
  );
96
- if (nodes.length > 0) {
115
+ if (exprs.length > 0) {
97
116
  return ts.factory.createTaggedTemplateExpression(
98
117
  tag,
99
118
  undefined,
@@ -101,7 +120,7 @@ function createValRichTextTaggedStringTemplate(
101
120
  ts.factory.createTemplateHead(head, head),
102
121
  others.map((s, i) =>
103
122
  ts.factory.createTemplateSpan(
104
- toExpression(nodes[i]),
123
+ toExpression(exprs[i]),
105
124
  i < others.length - 1
106
125
  ? ts.factory.createTemplateMiddle(s, s)
107
126
  : ts.factory.createTemplateTail(s, s)
@@ -132,6 +151,8 @@ function toExpression(value: JSONValue): ts.Expression {
132
151
  } else if (typeof value === "object") {
133
152
  if (isValFileValue(value)) {
134
153
  return createValFileReference(value);
154
+ } else if (isValLinkValue(value)) {
155
+ return createValLink(value);
135
156
  } else if (isValRichTextValue(value)) {
136
157
  return createValRichTextTaggedStringTemplate(value);
137
158
  }
@@ -591,7 +612,7 @@ function removeAtPath(
591
612
  );
592
613
  }
593
614
 
594
- function isValFileValue(value: JSONValue): value is FileSource<{
615
+ export function isValFileValue(value: JSONValue): value is FileSource<{
595
616
  [key: string]: JsonPrimitive;
596
617
  }> {
597
618
  return !!(
@@ -604,6 +625,14 @@ function isValFileValue(value: JSONValue): value is FileSource<{
604
625
  typeof value[FILE_REF_PROP] === "string"
605
626
  );
606
627
  }
628
+ function isValLinkValue(value: JSONValue): value is LinkSource {
629
+ return !!(
630
+ typeof value === "object" &&
631
+ value &&
632
+ VAL_EXTENSION in value &&
633
+ value[VAL_EXTENSION] === "link"
634
+ );
635
+ }
607
636
 
608
637
  function isValRichTextValue(
609
638
  value: JSONValue
@@ -613,9 +642,9 @@ function isValRichTextValue(
613
642
  value &&
614
643
  VAL_EXTENSION in value &&
615
644
  value[VAL_EXTENSION] === "richtext" &&
616
- "children" in value &&
617
- typeof value.children === "object" &&
618
- Array.isArray(value.children)
645
+ "templateStrings" in value &&
646
+ typeof value.templateStrings === "object" &&
647
+ Array.isArray(value.templateStrings)
619
648
  );
620
649
  }
621
650
 
@@ -1,100 +0,0 @@
1
- import { initVal } from "@valbuild/core";
2
- import { richTextToTaggedStringTemplate } from "./richtext";
3
-
4
- describe("patch richtext", () => {
5
- test("basic richtext <-> markdown", () => {
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- const input: any = {
8
- _type: "richtext",
9
- children: [
10
- { tag: "h1", children: ["Title 1"] },
11
- {
12
- tag: "p",
13
- children: [
14
- {
15
- tag: "span",
16
- classes: ["bold"],
17
- children: ["Bold text"],
18
- },
19
- ],
20
- },
21
- { _type: "file", _ref: "/public/image.png" },
22
- { tag: "p", children: ["Paragraph 2"] },
23
- ],
24
- };
25
- const r = richTextToTaggedStringTemplate(input);
26
- expect(r).toStrictEqual([
27
- ["# Title 1\n\n**Bold text**\n\n", "\nParagraph 2"],
28
- [{ _type: "file", _ref: "/public/image.png" }],
29
- ]);
30
-
31
- const { val } = initVal();
32
- const r2 = val.richtext(
33
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
34
- // @ts-expect-error
35
- r[0],
36
- ...r[1]
37
- );
38
- expect(r2).toStrictEqual(input);
39
- });
40
-
41
- test("richtext <-> markdown", () => {
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- const input: any = {
44
- _type: "richtext",
45
- children: [
46
- { tag: "h1", children: ["Title 1"] },
47
- { tag: "h2", children: ["Title 2"] },
48
- {
49
- tag: "p",
50
- children: [
51
- "Test 1 2 3. ",
52
- {
53
- tag: "span",
54
- classes: ["bold"],
55
- children: ["Bold text"],
56
- },
57
- ". More text. See image below",
58
- ],
59
- },
60
- { _type: "file", _ref: "/public/image.png" },
61
- { tag: "p", children: ["Paragraph 2"] },
62
- {
63
- tag: "ol",
64
- children: [
65
- { tag: "li", children: ["OL:Item 1"] },
66
- { tag: "li", children: ["OL:Item 2"] },
67
- ],
68
- },
69
- {
70
- tag: "ul",
71
- children: [
72
- { tag: "li", children: ["UL:Item 2"] },
73
- { tag: "li", children: ["UL:Item 3"] },
74
- ],
75
- },
76
- { tag: "h3", children: ["Title 3"] },
77
- {
78
- tag: "ul",
79
- children: [
80
- {
81
- tag: "li",
82
- children: [
83
- { tag: "span", classes: ["bold"], children: ["UL:Item 4"] },
84
- ],
85
- },
86
- ],
87
- },
88
- ],
89
- };
90
- const r = richTextToTaggedStringTemplate(input);
91
- const { val } = initVal();
92
- const r2 = val.richtext(
93
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
94
- // @ts-expect-error
95
- r[0],
96
- ...r[1]
97
- );
98
- expect(r2).toStrictEqual(input);
99
- });
100
- });
@@ -1,113 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import {
3
- AnyRichTextOptions,
4
- RichTextSource,
5
- RichTextSourceNode,
6
- } from "@valbuild/core";
7
-
8
- const HeaderRegEx = /^h([\d+])$/;
9
-
10
- export function richTextToTaggedStringTemplate(
11
- source: RichTextSource<AnyRichTextOptions>
12
- ) {
13
- const texts: string[] = [""];
14
- const nodes: any[] = [];
15
- let didAppendNewLines = false;
16
- let listContext: "ul" | "ol" | null = null;
17
-
18
- function rec(node: RichTextSourceNode<AnyRichTextOptions>) {
19
- if (typeof node === "string") {
20
- texts[texts.length - 1] += node;
21
- } else if ("tag" in node && node.tag) {
22
- if (
23
- node.tag === "h1" ||
24
- node.tag === "h2" ||
25
- node.tag === "h3" ||
26
- node.tag === "h4" ||
27
- node.tag === "h5" ||
28
- node.tag === "h6"
29
- ) {
30
- const depth = Number(node.tag.match(HeaderRegEx)?.[1]);
31
- if (Number.isNaN(depth)) {
32
- throw new Error("Invalid header depth");
33
- }
34
- for (let i = 0; i < Number(depth); i++) {
35
- texts[texts.length - 1] += "#";
36
- }
37
- texts[texts.length - 1] += " ";
38
- } else if (node.tag === "p") {
39
- // Ignore
40
- } else if (node.tag === "ul") {
41
- listContext = "ul";
42
- texts[texts.length - 1] += "\n";
43
- } else if (node.tag === "ol") {
44
- listContext = "ol";
45
- texts[texts.length - 1] += "\n";
46
- } else if (node.tag === "li") {
47
- if (listContext === "ul") {
48
- texts[texts.length - 1] += "\n- ";
49
- } else if (listContext === "ol") {
50
- texts[texts.length - 1] += "\n1. ";
51
- } else {
52
- throw new Error("Unexpected list context");
53
- }
54
- } else if (node.tag === "span") {
55
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
56
- texts[texts.length - 1] += "**";
57
- }
58
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
59
- texts[texts.length - 1] += "*";
60
- }
61
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
62
- texts[texts.length - 1] += "***";
63
- }
64
- if (node.classes.includes("line-through")) {
65
- texts[texts.length - 1] += "~~";
66
- }
67
- } else {
68
- //exhaustive match
69
- const exhaustiveCheck: never = node.tag;
70
- throw new Error(
71
- "Unexpected node tag: " + JSON.stringify(node, exhaustiveCheck, 2)
72
- );
73
- }
74
-
75
- node.children?.forEach(rec);
76
-
77
- didAppendNewLines = false;
78
- if (node.tag === "span") {
79
- if (node.classes.includes("line-through")) {
80
- texts[texts.length - 1] += "~~";
81
- }
82
- if (node.classes.includes("italic") && node.classes.includes("bold")) {
83
- texts[texts.length - 1] += "***";
84
- }
85
- if (node.classes.includes("italic") && !node.classes.includes("bold")) {
86
- texts[texts.length - 1] += "*";
87
- }
88
- if (node.classes.includes("bold") && !node.classes.includes("italic")) {
89
- texts[texts.length - 1] += "**";
90
- }
91
- } else if (node.tag === "p") {
92
- didAppendNewLines = true;
93
- texts[texts.length - 1] += "\n\n";
94
- } else if (node.tag === "ul" || node.tag === "ol") {
95
- listContext = null;
96
- texts[texts.length - 1] += "\n";
97
- } else if (node.tag?.startsWith("h")) {
98
- didAppendNewLines = true;
99
- texts[texts.length - 1] += "\n\n";
100
- }
101
- } else {
102
- nodes.push(node); // ImageSource
103
- texts.push("\n");
104
- }
105
- }
106
- source.children.forEach(rec);
107
-
108
- if (texts[texts.length - 1] && didAppendNewLines) {
109
- // remove last \n\n
110
- texts[texts.length - 1] = texts[texts.length - 1].slice(0, -2);
111
- }
112
- return [texts, nodes];
113
- }