@podlite/schema 0.0.37 → 0.0.39

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.
Files changed (44) hide show
  1. package/CHANGELOG.podlite +26 -0
  2. package/README.md +61 -4
  3. package/esm/blocks-helpers.d.ts +2 -2
  4. package/esm/blocks-helpers.js +11 -4
  5. package/esm/blocks-helpers.js.map +1 -1
  6. package/esm/exportHtml.js +57 -6
  7. package/esm/exportHtml.js.map +1 -1
  8. package/esm/exportMarkdown.js +52 -6
  9. package/esm/exportMarkdown.js.map +1 -1
  10. package/esm/grammar.js +442 -215
  11. package/esm/grammar.js.map +1 -1
  12. package/esm/grammarfc.js +1819 -1459
  13. package/esm/grammarfc.js.map +1 -1
  14. package/esm/helpers/config.d.ts +1 -0
  15. package/esm/helpers/config.js +8 -0
  16. package/esm/helpers/config.js.map +1 -1
  17. package/esm/index.d.ts +2 -0
  18. package/esm/index.js +1 -0
  19. package/esm/index.js.map +1 -1
  20. package/esm/plugin-tables.d.ts +0 -3
  21. package/esm/plugin-tables.js +425 -45
  22. package/esm/plugin-tables.js.map +1 -1
  23. package/esm/selectors.d.ts +18 -0
  24. package/esm/selectors.js +158 -0
  25. package/esm/selectors.js.map +1 -0
  26. package/esm/types.d.ts +9 -7
  27. package/lib/blocks-helpers.d.ts +2 -2
  28. package/lib/blocks-helpers.js +13 -6
  29. package/lib/exportHtml.js +57 -6
  30. package/lib/exportMarkdown.js +52 -6
  31. package/lib/grammar.js +442 -215
  32. package/lib/grammarfc.js +1819 -1459
  33. package/lib/helpers/config.d.ts +1 -0
  34. package/lib/helpers/config.js +8 -0
  35. package/lib/index.d.ts +2 -0
  36. package/lib/index.js +4 -1
  37. package/lib/plugin-tables.d.ts +0 -3
  38. package/lib/plugin-tables.js +425 -45
  39. package/lib/selectors.d.ts +18 -0
  40. package/lib/selectors.js +163 -0
  41. package/lib/types.d.ts +9 -7
  42. package/package.json +2 -2
  43. package/schema/AstTree.json +6 -3
  44. package/schema/PodliteDocument.json +6 -3
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSelector = exports.parseSelector = void 0;
4
+ const index_1 = require("./index");
5
+ const parseSelector = (selector) => {
6
+ const trimmed = selector.trim();
7
+ if (!trimmed)
8
+ return undefined;
9
+ // Split on the first '|' — left is source, right is blocks selector
10
+ const pipeIdx = trimmed.indexOf('|');
11
+ const sourcePart = (pipeIdx === -1 ? trimmed : trimmed.slice(0, pipeIdx)).trim();
12
+ const filterPart = pipeIdx === -1 ? '' : trimmed.slice(pipeIdx + 1).trim();
13
+ const blockFilters = filterPart
14
+ ? filterPart
15
+ .split(',')
16
+ .map(s => s.trim())
17
+ .filter(Boolean)
18
+ : [];
19
+ // Source: scheme:path or scheme:path#anchor
20
+ const sourceMatch = sourcePart.match(/^([^:]+):([^#]+)(?:#(.+))?$/);
21
+ if (sourceMatch) {
22
+ return {
23
+ scheme: sourceMatch[1],
24
+ document: sourceMatch[2].trim(),
25
+ anchor: sourceMatch[3],
26
+ blockFilters,
27
+ };
28
+ }
29
+ if (blockFilters.length > 0) {
30
+ return { blockFilters };
31
+ }
32
+ return undefined;
33
+ };
34
+ exports.parseSelector = parseSelector;
35
+ // Normalize a path for loose suffix comparison:
36
+ // 'src/foo.podlite' ~= 'foo.podlite'
37
+ // './includes/x.podlite' ~= 'includes/x.podlite'
38
+ const normalizePath = (p) => p.replace(/\\/g, '/').replace(/^\.\//, '');
39
+ const isGlobPattern = (s) => /[*?[]/.test(s);
40
+ // Convert a glob pattern to an anchored RegExp.
41
+ // **/ → (?:.*/)? zero or more directory segments (lets **/foo match root-level foo)
42
+ // ** → .* any characters, crosses /
43
+ // * → [^/]* any characters within a single segment
44
+ // ? → [^/] single character within a segment
45
+ // Other regex meta characters are escaped.
46
+ const globRegexCache = new Map();
47
+ const globToRegex = (glob) => {
48
+ const cached = globRegexCache.get(glob);
49
+ if (cached)
50
+ return cached;
51
+ let re = '';
52
+ let i = 0;
53
+ while (i < glob.length) {
54
+ const c = glob[i];
55
+ const next = glob[i + 1];
56
+ if (c === '*' && next === '*' && glob[i + 2] === '/') {
57
+ re += '(?:.*/)?';
58
+ i += 3;
59
+ }
60
+ else if (c === '*' && next === '*') {
61
+ re += '.*';
62
+ i += 2;
63
+ }
64
+ else if (c === '*') {
65
+ re += '[^/]*';
66
+ i += 1;
67
+ }
68
+ else if (c === '?') {
69
+ re += '[^/]';
70
+ i += 1;
71
+ }
72
+ else if (/[\\^$.()+|{}[\]]/.test(c)) {
73
+ re += '\\' + c;
74
+ i += 1;
75
+ }
76
+ else {
77
+ re += c;
78
+ i += 1;
79
+ }
80
+ }
81
+ const compiled = new RegExp(`^${re}$`);
82
+ globRegexCache.set(glob, compiled);
83
+ return compiled;
84
+ };
85
+ const filePathMatches = (docFile, target) => {
86
+ const a = normalizePath(docFile);
87
+ const b = normalizePath(target);
88
+ if (isGlobPattern(b)) {
89
+ const rx = globToRegex(b);
90
+ if (rx.test(a))
91
+ return true;
92
+ // Suffix-tolerant match: allow any parent prefix (consistent with
93
+ // non-glob suffix matching, so 'src/00-foo/x.pod' matches '00-foo/x.pod').
94
+ const body = rx.source.slice(1, -1);
95
+ const rxSuffix = new RegExp(`^(?:.*/)${body}$`);
96
+ return rxSuffix.test(a);
97
+ }
98
+ return a === b || a.endsWith('/' + b) || b.endsWith('/' + a);
99
+ };
100
+ const getDocIDs = (doc) => {
101
+ const ids = [];
102
+ (0, index_1.getFromTree)(doc.node, 'NAME', 'TITLE').forEach(block => {
103
+ const conf = (0, index_1.makeAttrs)(block, {});
104
+ const title = (0, index_1.getTextContentFromNode)(block).trim();
105
+ if (conf.exists('id')) {
106
+ const id = conf.getFirstValue('id');
107
+ if (id)
108
+ ids.push(id);
109
+ }
110
+ ids.push(title);
111
+ });
112
+ return ids;
113
+ };
114
+ function getMapIDsBlocks(srcNode) {
115
+ const idsMap = new Map();
116
+ (0, index_1.getFromTree)(srcNode, { type: 'block' }).forEach(i => {
117
+ const id = (0, index_1.getNodeId)(i, {});
118
+ if (id)
119
+ idsMap.set(id, i);
120
+ });
121
+ return idsMap;
122
+ }
123
+ const runSelector = (selector, docs) => {
124
+ const parsed = (0, exports.parseSelector)(selector);
125
+ if (!parsed)
126
+ return [];
127
+ const { scheme, document, anchor, blockFilters } = parsed;
128
+ let matchedDocs = docs;
129
+ if (scheme === 'doc' && document) {
130
+ matchedDocs = docs.filter(doc => getDocIDs(doc).includes(document));
131
+ }
132
+ else if (scheme === 'file' && document) {
133
+ matchedDocs = docs.filter(doc => filePathMatches(doc.file, document));
134
+ }
135
+ else if (scheme && scheme !== 'doc' && scheme !== 'file') {
136
+ return [];
137
+ }
138
+ // Anchor takes precedence — single-block-by-id lookup
139
+ if (anchor) {
140
+ const collectedBlocks = [];
141
+ for (const d of matchedDocs) {
142
+ const idsMap = getMapIDsBlocks(d.node);
143
+ const block = idsMap.get(anchor);
144
+ if (block)
145
+ collectedBlocks.push(block);
146
+ }
147
+ return collectedBlocks;
148
+ }
149
+ // Block filters — extract blocks by name across matched docs
150
+ if (blockFilters.length > 0) {
151
+ const collectedBlocks = [];
152
+ for (const d of matchedDocs) {
153
+ for (const name of blockFilters) {
154
+ collectedBlocks.push(...(0, index_1.getFromTree)(d.node, name));
155
+ }
156
+ }
157
+ return collectedBlocks;
158
+ }
159
+ // No anchor, no filter — return whole docs
160
+ return matchedDocs.map(d => d.node);
161
+ };
162
+ exports.runSelector = runSelector;
163
+ //# sourceMappingURL=selectors.js.map
package/lib/types.d.ts CHANGED
@@ -24,7 +24,9 @@ export interface RulesStrict {
24
24
  'D<>': RuleHandler<FormattingCodeD>;
25
25
  'E<>': RuleHandler<FormattingCodeE>;
26
26
  'F<>': RuleHandler<FormattingCodeF>;
27
+ 'H<>': RuleHandler<FormattingCodeAny>;
27
28
  'I<>': RuleHandler<FormattingCodeI>;
29
+ 'J<>': RuleHandler<FormattingCodeAny>;
28
30
  'K<>': RuleHandler<FormattingCodeAny>;
29
31
  'R<>': RuleHandler<FormattingCodeAny>;
30
32
  'T<>': RuleHandler<FormattingCodeAny>;
@@ -35,7 +37,7 @@ export interface RulesStrict {
35
37
  'L<>': RuleHandler<FormattingCodeL>;
36
38
  'U<>': RuleHandler<FormattingCodeAny>;
37
39
  'Z<>': RuleHandler<FormattingCodeAny>;
38
- 'Delete<>': RuleHandler<FormattingCodeAny>;
40
+ 'O<>': RuleHandler<FormattingCodeAny>;
39
41
  pod: RuleHandler<Para>;
40
42
  root: RuleHandler<RootBlock>;
41
43
  ':para': RuleHandler<Para>;
@@ -68,9 +70,8 @@ export interface RulesStrict {
68
70
  'table:block': RuleHandler<BlockTable>;
69
71
  table: RuleHandler<BlockTable>;
70
72
  ':separator': RuleHandler<Separator>;
71
- table_row: RuleHandler<TableRow>;
72
- table_cell: RuleHandler<TableCell>;
73
- table_head: RuleHandler<TableHead>;
73
+ row: RuleHandler<TableRow>;
74
+ cell: RuleHandler<TableCell>;
74
75
  toc: RuleHandler<BlockToc>;
75
76
  ':toc': RuleHandler<Toc>;
76
77
  ':toc-list': RuleHandler<TocList>;
@@ -100,6 +101,7 @@ export interface Image {
100
101
  export interface Toc {
101
102
  type: 'toc';
102
103
  title?: string;
104
+ folded?: boolean;
103
105
  foldedLevels?: Record<number, boolean>;
104
106
  content: TocList;
105
107
  }
@@ -342,17 +344,17 @@ export interface BlockTable extends Omit<Block, 'content'> {
342
344
  text?: string;
343
345
  }
344
346
  export interface TableCell {
345
- name: 'table_cell';
347
+ name: 'cell';
346
348
  type: 'block';
347
349
  content: Array<string>;
348
350
  }
349
351
  export interface TableRow {
350
- name: 'table_row';
352
+ name: 'row';
351
353
  type: 'block';
352
354
  content: Array<TableCell>;
353
355
  }
354
356
  export interface TableHead {
355
- name: 'table_head';
357
+ name: 'row';
356
358
  type: 'block';
357
359
  content: Array<TableCell>;
358
360
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podlite/schema",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "AST tools and schema for Podlite markup language — validate, traverse, and transform document trees",
5
5
  "main": "lib/index.js",
6
6
  "homepage": "https://podlite.org",
@@ -68,7 +68,7 @@
68
68
  "@types/node": "^17.0.7",
69
69
  "glob": "^7.2.0",
70
70
  "npm-run-all": "^4.1.5",
71
- "pegmill": "0.1.0",
71
+ "pegmill": "0.1.2",
72
72
  "ts-node": "^9.1.1",
73
73
  "typescript": "4.5.5",
74
74
  "typescript-json-schema": "0.53.0"
@@ -1521,7 +1521,7 @@
1521
1521
  "name": {
1522
1522
  "type": "string",
1523
1523
  "enum": [
1524
- "table_row"
1524
+ "row"
1525
1525
  ]
1526
1526
  },
1527
1527
  "type": {
@@ -1549,7 +1549,7 @@
1549
1549
  "name": {
1550
1550
  "type": "string",
1551
1551
  "enum": [
1552
- "table_cell"
1552
+ "cell"
1553
1553
  ]
1554
1554
  },
1555
1555
  "type": {
@@ -1577,7 +1577,7 @@
1577
1577
  "name": {
1578
1578
  "type": "string",
1579
1579
  "enum": [
1580
- "table_head"
1580
+ "row"
1581
1581
  ]
1582
1582
  },
1583
1583
  "type": {
@@ -2688,6 +2688,9 @@
2688
2688
  "title": {
2689
2689
  "type": "string"
2690
2690
  },
2691
+ "folded": {
2692
+ "type": "boolean"
2693
+ },
2691
2694
  "foldedLevels": {
2692
2695
  "type": "object",
2693
2696
  "additionalProperties": false,
@@ -1521,7 +1521,7 @@
1521
1521
  "name": {
1522
1522
  "type": "string",
1523
1523
  "enum": [
1524
- "table_row"
1524
+ "row"
1525
1525
  ]
1526
1526
  },
1527
1527
  "type": {
@@ -1549,7 +1549,7 @@
1549
1549
  "name": {
1550
1550
  "type": "string",
1551
1551
  "enum": [
1552
- "table_cell"
1552
+ "cell"
1553
1553
  ]
1554
1554
  },
1555
1555
  "type": {
@@ -1577,7 +1577,7 @@
1577
1577
  "name": {
1578
1578
  "type": "string",
1579
1579
  "enum": [
1580
- "table_head"
1580
+ "row"
1581
1581
  ]
1582
1582
  },
1583
1583
  "type": {
@@ -2688,6 +2688,9 @@
2688
2688
  "title": {
2689
2689
  "type": "string"
2690
2690
  },
2691
+ "folded": {
2692
+ "type": "boolean"
2693
+ },
2691
2694
  "foldedLevels": {
2692
2695
  "type": "object",
2693
2696
  "additionalProperties": false,