@agentshouse/mdmodel 0.1.0-cabd61587647f → 0.1.0-caefdbe3e3d42

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 (127) hide show
  1. package/API.md +161 -116
  2. package/README.md +6 -4
  3. package/dist/blocks.d.ts.map +1 -1
  4. package/dist/blocks.js +29 -7
  5. package/dist/condition.d.ts +43 -13
  6. package/dist/condition.d.ts.map +1 -1
  7. package/dist/condition.js +225 -127
  8. package/dist/definition.d.ts +3 -1
  9. package/dist/definition.d.ts.map +1 -1
  10. package/dist/definition.js +105 -21
  11. package/dist/divide.js +9 -9
  12. package/dist/document.d.ts +4 -4
  13. package/dist/document.d.ts.map +1 -1
  14. package/dist/document.js +41 -41
  15. package/dist/index.d.ts +20 -8
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +12 -6
  18. package/dist/kinds.d.ts +18 -0
  19. package/dist/kinds.d.ts.map +1 -0
  20. package/dist/kinds.js +141 -0
  21. package/dist/links.d.ts +1 -0
  22. package/dist/links.d.ts.map +1 -1
  23. package/dist/links.js +85 -39
  24. package/dist/paths.d.ts +9 -1
  25. package/dist/paths.d.ts.map +1 -1
  26. package/dist/paths.js +28 -2
  27. package/dist/pattern.d.ts +10 -0
  28. package/dist/pattern.d.ts.map +1 -0
  29. package/dist/pattern.js +355 -0
  30. package/dist/project.d.ts.map +1 -1
  31. package/dist/project.js +7 -7
  32. package/dist/query/language.d.ts +218 -0
  33. package/dist/query/language.d.ts.map +1 -0
  34. package/dist/query/language.js +526 -0
  35. package/dist/query/match.d.ts +12 -0
  36. package/dist/query/match.d.ts.map +1 -0
  37. package/dist/query/match.js +118 -0
  38. package/dist/query/rows.d.ts +32 -0
  39. package/dist/query/rows.d.ts.map +1 -0
  40. package/dist/query/rows.js +161 -0
  41. package/dist/query/sql.d.ts +39 -0
  42. package/dist/query/sql.d.ts.map +1 -0
  43. package/dist/query/sql.js +279 -0
  44. package/dist/references.d.ts.map +1 -1
  45. package/dist/references.js +6 -1
  46. package/dist/reserved.d.ts +5 -0
  47. package/dist/reserved.d.ts.map +1 -0
  48. package/dist/reserved.js +20 -0
  49. package/dist/schema.d.ts +1 -0
  50. package/dist/schema.d.ts.map +1 -1
  51. package/dist/schema.js +55 -4
  52. package/dist/types.d.ts +34 -4
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/validate.d.ts +28 -4
  55. package/dist/validate.d.ts.map +1 -1
  56. package/dist/validate.js +302 -75
  57. package/dist/yaml.d.ts.map +1 -1
  58. package/dist/yaml.js +36 -3
  59. package/fixtures/README.md +26 -6
  60. package/fixtures/cases/conditional-section/context.json +1 -0
  61. package/fixtures/cases/conditional-section/expected.json +6 -0
  62. package/fixtures/cases/conditional-section/library/questions/hosting.md +9 -0
  63. package/fixtures/cases/conditional-section/library/questions/payments.md +12 -0
  64. package/fixtures/cases/conditional-section/schema.yaml +14 -0
  65. package/fixtures/cases/cross-room-link/context.json +1 -0
  66. package/fixtures/cases/cross-room-link/expected.json +1 -0
  67. package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
  68. package/fixtures/cases/cross-room-link/schema.yaml +3 -0
  69. package/fixtures/cases/cross-room-reference/context.json +1 -0
  70. package/fixtures/cases/cross-room-reference/expected.json +1 -0
  71. package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
  72. package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
  73. package/fixtures/cases/link-into-a-reserved-name/context.json +1 -0
  74. package/fixtures/cases/link-into-a-reserved-name/expected.json +5 -0
  75. package/fixtures/cases/link-into-a-reserved-name/library/notes/a.md +6 -0
  76. package/fixtures/cases/link-into-a-reserved-name/schema.yaml +3 -0
  77. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/context.json +1 -0
  78. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/expected.json +5 -0
  79. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/library/notes/b.md +5 -0
  80. package/fixtures/cases/member-on-an-untyped-document/context.json +1 -0
  81. package/fixtures/cases/member-on-an-untyped-document/expected.json +6 -0
  82. package/fixtures/cases/member-on-an-untyped-document/library/note.md +4 -0
  83. package/fixtures/cases/member-on-another-type/context.json +1 -0
  84. package/fixtures/cases/member-on-another-type/expected.json +6 -0
  85. package/fixtures/cases/member-on-another-type/library/note.md +4 -0
  86. package/fixtures/cases/member-on-another-type/schema.yaml +7 -0
  87. package/fixtures/cases/reference-into-a-reserved-name/context.json +1 -0
  88. package/fixtures/cases/reference-into-a-reserved-name/expected.json +6 -0
  89. package/fixtures/cases/reference-into-a-reserved-name/library/notes/a.md +4 -0
  90. package/fixtures/cases/reference-into-a-reserved-name/library/settings/brief.md +1 -0
  91. package/fixtures/cases/reference-into-a-reserved-name/schema.yaml +3 -0
  92. package/fixtures/cases/room-md-declares-a-type/context.json +1 -0
  93. package/fixtures/cases/room-md-declares-a-type/expected.json +6 -0
  94. package/fixtures/cases/room-md-declares-a-type/library/ROOM.md +5 -0
  95. package/fixtures/cases/typed-path-names-another-type/context.json +11 -0
  96. package/fixtures/cases/typed-path-names-another-type/expected.json +6 -0
  97. package/fixtures/cases/typed-path-names-another-type/library/settings/prefs/one.md +3 -0
  98. package/fixtures/cases/typed-path-names-another-type/schema.yaml +6 -0
  99. package/fixtures/cases/typed-path-names-its-type/context.json +11 -0
  100. package/fixtures/cases/typed-path-names-its-type/expected.json +3 -0
  101. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/deeper/two.md +1 -0
  102. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/one.md +4 -0
  103. package/fixtures/cases/typed-path-names-its-type/schema.yaml +6 -0
  104. package/fixtures/cases/typed-path-names-no-type/context.json +11 -0
  105. package/fixtures/cases/typed-path-names-no-type/expected.json +6 -0
  106. package/fixtures/cases/typed-path-names-no-type/library/settings/prefs/one.md +1 -0
  107. package/fixtures/cases/typed-path-names-no-type/schema.yaml +6 -0
  108. package/fixtures/cases/unnamed-typed-path-checks-its-fields/context.json +11 -0
  109. package/fixtures/cases/unnamed-typed-path-checks-its-fields/expected.json +6 -0
  110. package/fixtures/cases/unnamed-typed-path-checks-its-fields/library/rooms/team/tasks/plan.md +4 -0
  111. package/fixtures/cases/unnamed-typed-path-checks-its-fields/schema.yaml +5 -0
  112. package/fixtures/cases/unnamed-typed-path-names-a-type/context.json +11 -0
  113. package/fixtures/cases/unnamed-typed-path-names-a-type/expected.json +6 -0
  114. package/fixtures/cases/unnamed-typed-path-names-a-type/library/rooms/team/tasks/plan.md +6 -0
  115. package/fixtures/cases/unnamed-typed-path-names-a-type/schema.yaml +5 -0
  116. package/fixtures/cases/unnamed-typed-path-reads-its-type/context.json +11 -0
  117. package/fixtures/cases/unnamed-typed-path-reads-its-type/expected.json +3 -0
  118. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/plan.md +1 -0
  119. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/tasks/plan.md +5 -0
  120. package/fixtures/cases/unnamed-typed-path-reads-its-type/schema.yaml +5 -0
  121. package/fixtures/cases/unnamed-typed-path-without-a-body/context.json +11 -0
  122. package/fixtures/cases/unnamed-typed-path-without-a-body/expected.json +5 -0
  123. package/fixtures/cases/unnamed-typed-path-without-a-body/library/rooms/team/tasks/plan.md +5 -0
  124. package/fixtures/cases/unnamed-typed-path-without-a-body/schema.yaml +5 -0
  125. package/fixtures/division.json +26 -26
  126. package/fixtures/queries.json +913 -0
  127. package/package.json +7 -2
package/dist/kinds.js ADDED
@@ -0,0 +1,141 @@
1
+ import { format } from '@cfworker/json-schema';
2
+ import { normalize } from './paths.js';
3
+ export const KINDS = [
4
+ 'string',
5
+ 'number',
6
+ 'integer',
7
+ 'boolean',
8
+ 'date',
9
+ 'date-time',
10
+ 'time',
11
+ 'enum',
12
+ 'reference',
13
+ ];
14
+ const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt\s](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2})(?::?(\d{2}))?)$/u;
15
+ const BEFORE_YEAR_ZERO = 62200000000000000000n;
16
+ const INSTANT_DIGITS = 21;
17
+ export function kindOf(facts) {
18
+ if (facts.reference !== undefined)
19
+ return 'reference';
20
+ if (facts.values !== undefined)
21
+ return 'enum';
22
+ if (facts.type === 'number')
23
+ return 'number';
24
+ if (facts.type === 'integer')
25
+ return 'integer';
26
+ if (facts.type === 'boolean')
27
+ return 'boolean';
28
+ if (facts.type !== 'string')
29
+ return null;
30
+ if (facts.format === 'date')
31
+ return 'date';
32
+ if (facts.format === 'date-time')
33
+ return 'date-time';
34
+ if (facts.format === 'time')
35
+ return 'time';
36
+ return 'string';
37
+ }
38
+ export function fitsKind(kind, facts, value) {
39
+ if (kind === 'enum')
40
+ return (facts.values ?? []).includes(value);
41
+ if (kind === 'number')
42
+ return typeof value === 'number' && Number.isFinite(value);
43
+ if (kind === 'integer')
44
+ return Number.isSafeInteger(value);
45
+ if (kind === 'boolean')
46
+ return typeof value === 'boolean';
47
+ if (typeof value !== 'string')
48
+ return false;
49
+ if (kind === 'reference')
50
+ return value !== '' && normalize(value) === value;
51
+ if (kind === 'date')
52
+ return dated(value);
53
+ if (kind === 'date-time')
54
+ return instant(value) !== undefined;
55
+ if (kind === 'time')
56
+ return format.time(value);
57
+ return true;
58
+ }
59
+ export function dated(value) {
60
+ return typeof value === 'string' && format.date(value);
61
+ }
62
+ export function instant(value) {
63
+ if (typeof value !== 'string' || !format['date-time'](value))
64
+ return undefined;
65
+ const parts = DATE_TIME.exec(value);
66
+ const [year, month, day, hour, minute, second, offsetHours, offsetMinutes] = [
67
+ 1, 2, 3, 4, 5, 6, 9, 10,
68
+ ].map((at) => Number(parts[at] ?? 0));
69
+ const at = new Date(0);
70
+ at.setUTCFullYear(year, month - 1, day);
71
+ at.setUTCHours(hour, minute, second);
72
+ const offset = (parts[8] === '-' ? -1 : 1) * (offsetHours * 60 + offsetMinutes);
73
+ const fraction = (parts[7] ?? '').padEnd(9, '0').slice(0, 9);
74
+ return (BigInt(at.getTime()) - BigInt(offset) * 60000n) * 1000000n + BigInt(fraction);
75
+ }
76
+ export function instantKey(value) {
77
+ const at = instant(value);
78
+ return at === undefined ? null : (at + BEFORE_YEAR_ZERO).toString().padStart(INSTANT_DIGITS, '0');
79
+ }
80
+ function rank(value) {
81
+ if (typeof value === 'boolean' || typeof value === 'number')
82
+ return 1;
83
+ if (typeof value === 'string')
84
+ return 2;
85
+ return Array.isArray(value) ? 3 : 4;
86
+ }
87
+ function unit(code) {
88
+ if (code >= 0xd800 && code < 0xe000)
89
+ return code + 0x2000;
90
+ return code >= 0xe000 ? code - 0x800 : code;
91
+ }
92
+ export function byCodePoint(left, right) {
93
+ for (let at = 0; at < Math.min(left.length, right.length); at += 1) {
94
+ const ours = left.charCodeAt(at);
95
+ const theirs = right.charCodeAt(at);
96
+ if (ours !== theirs)
97
+ return unit(ours) - unit(theirs);
98
+ }
99
+ return left.length - right.length;
100
+ }
101
+ function ascending(left, right, ordering) {
102
+ if (left == null && right == null)
103
+ return 0;
104
+ if (left == null)
105
+ return ordering.nulls === 'first' ? -1 : 1;
106
+ if (right == null)
107
+ return ordering.nulls === 'first' ? 1 : -1;
108
+ const ranked = rank(left) - rank(right);
109
+ if (ranked !== 0)
110
+ return ranked;
111
+ if (typeof left === 'string' && typeof right === 'string') {
112
+ return ordering.stringSort === 'locale'
113
+ ? left.localeCompare(right, ordering.locale, ordering.localeOptions)
114
+ : byCodePoint(left, right);
115
+ }
116
+ if (Array.isArray(left) && Array.isArray(right)) {
117
+ for (let at = 0; at < Math.min(left.length, right.length); at += 1) {
118
+ const result = ascending(left[at], right[at], ordering);
119
+ if (result !== 0)
120
+ return result;
121
+ }
122
+ return left.length - right.length;
123
+ }
124
+ if (typeof left === 'object')
125
+ return 0;
126
+ const held = left;
127
+ const other = right;
128
+ if (held < other)
129
+ return -1;
130
+ if (held > other)
131
+ return 1;
132
+ return 0;
133
+ }
134
+ export function compared(left, right, ordering) {
135
+ if (ordering.direction === 'asc')
136
+ return ascending(left, right, ordering);
137
+ return ascending(right, left, {
138
+ ...ordering,
139
+ nulls: ordering.nulls === 'first' ? 'last' : 'first',
140
+ });
141
+ }
package/dist/links.d.ts CHANGED
@@ -24,5 +24,6 @@ export type LinkInventory = {
24
24
  };
25
25
  export declare function fenceSpans(text: string): readonly (readonly [number, number])[];
26
26
  export declare function linkInventory(body: string): LinkInventory;
27
+ export declare function destinations(inventory: LinkInventory): readonly HrefOccurrence[];
27
28
  export declare function hrefOccurrences(body: string): readonly HrefOccurrence[];
28
29
  //# sourceMappingURL=links.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAkhBA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE5D;AAyLD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GAC5C,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAOvC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CAC7C,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAe/E;AAYD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CA6DzD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAIvE"}
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAgiBA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE5D;AAyLD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GAC5C,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAOvC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CAC7C,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAe/E;AA+CD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAmEzD;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,cAAc,EAAE,CAIhF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAEvE"}
package/dist/links.js CHANGED
@@ -17,17 +17,28 @@ const HTML_TAG_LINE = /^(?:<[A-Za-z][A-Za-z0-9-]*(?:[ \t\v\f]+[A-Za-z_:][A-Za-z0
17
17
  const ORDERED = /^(\d{1,9})[.)]/;
18
18
  const LABEL_LENGTH = 999;
19
19
  const PUNCTUATION = /^[!-/:-@[-`{-~]$/;
20
- const INLINE_RAW = new RegExp([
20
+ const INLINE_TAG = new RegExp([
21
21
  '<[A-Za-z][A-Za-z0-9-]*(?:[ \\t\\n\\v\\f\\r]+[A-Za-z_:][A-Za-z0-9_.:-]*(?:[ \\t\\n\\v\\f\\r]*=[ \\t\\n\\v\\f\\r]*(?:[^ \\t\\n\\v\\f\\r"\'=<>`]+|\'[^\']*\'|"[^"]*"))?)*[ \\t\\n\\v\\f\\r]*\\/?>',
22
22
  '<\\/[A-Za-z][A-Za-z0-9-]*[ \\t\\n\\v\\f\\r]*>',
23
23
  '<!--(?!-?>)(?:-?[^-])*-->',
24
- '<\\?[\\s\\S]*?\\?>',
25
- '<![A-Z]+[ \\t\\n\\v\\f\\r]+[^>]*>',
26
- '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>',
24
+ ].join('|'), 'y');
25
+ const AUTOLINK = new RegExp([
27
26
  '<[A-Za-z][A-Za-z0-9+.-]{1,31}:[^\\x00-\\x20<>]*>',
28
27
  "<[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*>",
29
28
  ].join('|'), 'y');
30
- const DELIMITER_ROW = /^\|?[ \t]*:?-+:?[ \t]*(?:\|[ \t]*:?-+:?[ \t]*)*\|?[ \t]*$/;
29
+ const DECLARATION = /<![A-Z]+[ \t\n\v\f\r]/y;
30
+ const INSTRUCTION = '<?';
31
+ const CDATA = '<![CDATA[';
32
+ const BACKSLASH = 0x5c;
33
+ const BACKTICK = 0x60;
34
+ const LINE_FEED = 0x0a;
35
+ const CARRIAGE_RETURN = 0x0d;
36
+ const LESS_THAN = 0x3c;
37
+ const OPEN_BRACKET = 0x5b;
38
+ const CLOSE_BRACKET = 0x5d;
39
+ const EXCLAMATION = 0x21;
40
+ const OPEN_PAREN = 0x28;
41
+ const DELIMITER_ROW = /^\|?[ \t]*:?-+:?(?:[ \t]*\|[ \t]*:?-+:?)*(?:[ \t]*\|)?[ \t]*$/;
31
42
  const GAP = /^[ \t\v\f]+/;
32
43
  function endOfLine(text, from) {
33
44
  const nl = text.indexOf('\n', from);
@@ -164,10 +175,10 @@ function skipInlineCode(text, index, joins, unclosed) {
164
175
  const runs = new Map();
165
176
  let i = index + ticks;
166
177
  while (i < text.length) {
167
- const ch = text[i];
168
- if (ch === '`') {
178
+ const code = text.charCodeAt(i);
179
+ if (code === BACKTICK) {
169
180
  let run = 0;
170
- while (text[i + run] === '`')
181
+ while (text.charCodeAt(i + run) === BACKTICK)
171
182
  run += 1;
172
183
  if (run === ticks)
173
184
  return i + run;
@@ -175,9 +186,9 @@ function skipInlineCode(text, index, joins, unclosed) {
175
186
  i += run;
176
187
  continue;
177
188
  }
178
- if (ch === '\r' && text[i + 1] !== '\n')
189
+ if (code === CARRIAGE_RETURN && text.charCodeAt(i + 1) !== LINE_FEED)
179
190
  break;
180
- if (ch === '\n' && !joins.has(i))
191
+ if (code === LINE_FEED && !joins.has(i))
181
192
  break;
182
193
  i += 1;
183
194
  }
@@ -200,21 +211,21 @@ function skipInlineSpace(text, start, joins) {
200
211
  return afterIndent(text, readLine(text, i + 1, endOfLine(text, i + 1)));
201
212
  }
202
213
  function closeEnd(text, start, open, joins) {
203
- const close = open === '(' ? ')' : open;
214
+ const close = (open === '(' ? ')' : open).charCodeAt(0);
204
215
  let i = start;
205
216
  while (i < text.length) {
206
- const ch = text[i];
217
+ const code = text.charCodeAt(i);
207
218
  if (escapes(text, i)) {
208
219
  i += 2;
209
220
  continue;
210
221
  }
211
- if (ch === close)
222
+ if (code === close)
212
223
  return i + 1;
213
- if (open === '(' && ch === '(')
224
+ if (open === '(' && code === OPEN_PAREN)
214
225
  return null;
215
- if (ch === '\r' && text[i + 1] !== '\n')
226
+ if (code === CARRIAGE_RETURN && text.charCodeAt(i + 1) !== LINE_FEED)
216
227
  return null;
217
- if (ch === '\n' && !joins.has(i))
228
+ if (code === LINE_FEED && !joins.has(i))
218
229
  return null;
219
230
  i += 1;
220
231
  }
@@ -511,23 +522,23 @@ function structure(text) {
511
522
  return { joins, raw };
512
523
  }
513
524
  export function escapes(text, index) {
514
- return text[index] === '\\' && PUNCTUATION.test(text[index + 1] ?? '');
525
+ return text.charCodeAt(index) === BACKSLASH && PUNCTUATION.test(text[index + 1] ?? '');
515
526
  }
516
527
  function referenceEnd(text, start, joins) {
517
528
  let i = start;
518
529
  while (i < text.length) {
519
- const ch = text[i];
530
+ const code = text.charCodeAt(i);
520
531
  if (escapes(text, i)) {
521
532
  i += 2;
522
533
  continue;
523
534
  }
524
- if (ch === ']')
535
+ if (code === CLOSE_BRACKET)
525
536
  return i + 1;
526
- if (ch === '[')
537
+ if (code === OPEN_BRACKET)
527
538
  return -1;
528
- if (ch === '\r' && text[i + 1] !== '\n')
539
+ if (code === CARRIAGE_RETURN && text.charCodeAt(i + 1) !== LINE_FEED)
529
540
  return -1;
530
- if (ch === '\n' && !joins.has(i))
541
+ if (code === LINE_FEED && !joins.has(i))
531
542
  return -1;
532
543
  i += 1;
533
544
  }
@@ -702,14 +713,45 @@ export function fenceSpans(text) {
702
713
  function paragraphEnd(text, from, joins) {
703
714
  let i = from;
704
715
  while (i < text.length) {
705
- if (text[i] === '\n' && !joins.has(i))
716
+ const code = text.charCodeAt(i);
717
+ if (code === LINE_FEED && !joins.has(i))
706
718
  return i;
707
- if (text[i] === '\r' && text[i + 1] !== '\n')
719
+ if (code === CARRIAGE_RETURN && text.charCodeAt(i + 1) !== LINE_FEED)
708
720
  return i;
709
721
  i += 1;
710
722
  }
711
723
  return i;
712
724
  }
725
+ function closerAt(text, closer, from, closers) {
726
+ const held = closers.get(closer);
727
+ if (held !== undefined && from >= held[0] && (held[1] === -1 || from <= held[1]))
728
+ return held[1];
729
+ const at = text.indexOf(closer, from);
730
+ closers.set(closer, [from, at]);
731
+ return at;
732
+ }
733
+ function closedAfter(text, closer, from, closers) {
734
+ const at = closerAt(text, closer, from, closers);
735
+ return at === -1 ? -1 : at + closer.length;
736
+ }
737
+ function stuck(pattern, text, at) {
738
+ pattern.lastIndex = at;
739
+ return pattern.test(text) ? pattern.lastIndex : -1;
740
+ }
741
+ function markupEnd(text, at, closers) {
742
+ if (text.startsWith(INSTRUCTION, at))
743
+ return closedAfter(text, '?>', at + INSTRUCTION.length, closers);
744
+ if (text.startsWith(CDATA, at))
745
+ return closedAfter(text, ']]>', at + CDATA.length, closers);
746
+ const declared = stuck(DECLARATION, text, at);
747
+ if (declared !== -1)
748
+ return closedAfter(text, '>', declared, closers);
749
+ return stuck(INLINE_TAG, text, at);
750
+ }
751
+ function inlineRawEnd(text, at, closers) {
752
+ const end = markupEnd(text, at, closers);
753
+ return end === -1 ? stuck(AUTOLINK, text, at) : end;
754
+ }
713
755
  export function linkInventory(body) {
714
756
  const { raw, definitions, blocks, joins } = scanBlocks(body);
715
757
  const rawEnd = spanCursor(raw);
@@ -717,7 +759,7 @@ export function linkInventory(body) {
717
759
  const uses = [];
718
760
  const openers = [];
719
761
  const unclosed = { stop: 0, runs: new Map() };
720
- let paragraph = { start: 0, end: -1, text: '' };
762
+ let paragraph = { start: 0, end: -1, text: '', closers: new Map() };
721
763
  let i = 0;
722
764
  while (i < body.length) {
723
765
  const skipEnd = rawEnd(i) ?? blockEnd(i);
@@ -726,39 +768,40 @@ export function linkInventory(body) {
726
768
  i = skipEnd;
727
769
  continue;
728
770
  }
729
- const ch = body[i];
771
+ const code = body.charCodeAt(i);
730
772
  if (escapes(body, i)) {
731
773
  i += 2;
732
774
  continue;
733
775
  }
734
- if (ch === '`') {
776
+ if (code === BACKTICK) {
735
777
  i = skipInlineCode(body, i, joins, unclosed);
736
778
  continue;
737
779
  }
738
- if (ch === '<') {
780
+ if (code === LESS_THAN) {
739
781
  if (i >= paragraph.end) {
740
782
  const end = paragraphEnd(body, i, joins);
741
- paragraph = { start: i, end, text: body.slice(i, end) };
783
+ paragraph = { start: i, end, text: body.slice(i, end), closers: new Map() };
742
784
  }
743
- INLINE_RAW.lastIndex = i - paragraph.start;
744
- const raw = INLINE_RAW.exec(paragraph.text);
745
- if (raw !== null) {
746
- i += raw[0].length;
785
+ const raw = inlineRawEnd(paragraph.text, i - paragraph.start, paragraph.closers);
786
+ if (raw !== -1) {
787
+ i = paragraph.start + raw;
747
788
  continue;
748
789
  }
749
790
  }
750
- if ((ch === '\n' && !joins.has(i)) || (ch === '\r' && body[i + 1] !== '\n'))
791
+ if ((code === LINE_FEED && !joins.has(i)) ||
792
+ (code === CARRIAGE_RETURN && body.charCodeAt(i + 1) !== LINE_FEED))
751
793
  openers.length = 0;
752
- if (ch === '[' || (ch === '!' && body[i + 1] === '[')) {
794
+ if (code === OPEN_BRACKET ||
795
+ (code === EXCLAMATION && body.charCodeAt(i + 1) === OPEN_BRACKET)) {
753
796
  const previous = openers.at(-1);
754
797
  if (previous !== undefined)
755
798
  previous.bracketAfter = true;
756
- const image = ch === '!';
799
+ const image = code === EXCLAMATION;
757
800
  openers.push({ at: image ? i + 1 : i, start: i, image, active: true, bracketAfter: false });
758
801
  i += image ? 2 : 1;
759
802
  continue;
760
803
  }
761
- if (ch === ']') {
804
+ if (code === CLOSE_BRACKET) {
762
805
  const opener = openers.pop();
763
806
  const use = opener?.active ? closeLink(body, opener, i, definitions, joins) : null;
764
807
  if (opener === undefined || use === null) {
@@ -777,9 +820,12 @@ export function linkInventory(body) {
777
820
  }
778
821
  return { uses, blocks };
779
822
  }
780
- export function hrefOccurrences(body) {
823
+ export function destinations(inventory) {
781
824
  const byStart = new Map();
782
- for (const use of linkInventory(body).uses)
825
+ for (const use of inventory.uses)
783
826
  byStart.set(use.destination.start, use.destination);
784
827
  return [...byStart.values()].sort((left, right) => left.start - right.start);
785
828
  }
829
+ export function hrefOccurrences(body) {
830
+ return destinations(linkInventory(body));
831
+ }
package/dist/paths.d.ts CHANGED
@@ -2,14 +2,22 @@ export declare function dirname(path: string): string;
2
2
  export declare function join(base: string, relative: string): string;
3
3
  export declare function normalize(path: string): string | null;
4
4
  export declare function destinationPath(href: string): string | null;
5
+ export type RoomTarget = {
6
+ readonly handle: string;
7
+ readonly path: string;
8
+ };
5
9
  export declare function classifyHref(from: string, href: string): {
6
10
  kind: 'skip';
7
11
  } | {
8
12
  kind: 'path';
9
13
  path: string;
10
- } | {
14
+ } | ({
15
+ kind: 'room';
16
+ } & RoomTarget) | {
11
17
  kind: 'invalid';
12
18
  };
19
+ export declare function roomTarget(href: string): RoomTarget | null;
20
+ export declare function roomPath(href: string): string | null;
13
21
  export declare function target(from: string, href: string): string | null;
14
22
  export declare function retarget(href: string, to: string): string;
15
23
  export declare function relative(from: string, target: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAoDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW3D;AAgBD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CASzE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvE"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAwDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW3D;AAgBD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAY5E,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAEV;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAAC,GAC/B;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAatB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAG1D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvE"}
package/dist/paths.js CHANGED
@@ -61,7 +61,10 @@ function located(href) {
61
61
  const written = href.trim();
62
62
  const { base, suffix } = unescaped(written);
63
63
  const url = base.replace(/[\t\n\r]/g, '').replace(/^[\u0000-\u0020]+/, '');
64
- return { base: suffix === written.length ? url.replace(/[\u0000-\u0020]+$/, '') : url, suffix };
64
+ return {
65
+ base: suffix === written.length ? url.replace(/(?<![\u0000-\u0020])[\u0000-\u0020]+$/, '') : url,
66
+ suffix,
67
+ };
65
68
  }
66
69
  const ENCODED = /(?:%[0-9a-fA-F]{2})+/g;
67
70
  function decodedRun(run) {
@@ -104,6 +107,17 @@ function written(path) {
104
107
  }
105
108
  return text;
106
109
  }
110
+ function roomTargetOf(path) {
111
+ if (!path.startsWith(SHELL_ROOMS))
112
+ return null;
113
+ const rest = path.slice(SHELL_ROOMS.length);
114
+ const slash = rest.indexOf('/');
115
+ const handle = rest.slice(0, slash);
116
+ if (slash <= 0 || handle === '.' || handle === '..')
117
+ return null;
118
+ const within = normalize(rest.slice(slash + 1));
119
+ return within === null || within === '' ? null : { handle, path: within };
120
+ }
107
121
  export function classifyHref(from, href) {
108
122
  const base = located(href).base;
109
123
  if (base === '')
@@ -111,13 +125,25 @@ export function classifyHref(from, href) {
111
125
  if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(base))
112
126
  return { kind: 'skip' };
113
127
  const path = destinationPath(href);
114
- if (path === null || path.startsWith('/'))
128
+ if (path === null)
115
129
  return { kind: 'invalid' };
130
+ if (path.startsWith('/')) {
131
+ const room = roomTargetOf(path);
132
+ return room === null ? { kind: 'invalid' } : { kind: 'room', ...room };
133
+ }
116
134
  const resolved = normalize(join(dirname(from), path));
117
135
  if (resolved === null || resolved === '')
118
136
  return { kind: 'invalid' };
119
137
  return { kind: 'path', path: resolved };
120
138
  }
139
+ export function roomTarget(href) {
140
+ const path = destinationPath(href);
141
+ return path === null ? null : roomTargetOf(path);
142
+ }
143
+ export function roomPath(href) {
144
+ const room = roomTarget(href);
145
+ return room === null ? null : `${SHELL_ROOMS}${room.handle}/${room.path}`;
146
+ }
121
147
  export function target(from, href) {
122
148
  const resolved = classifyHref(from, href);
123
149
  return resolved.kind === 'path' ? resolved.path : null;
@@ -0,0 +1,10 @@
1
+ export declare const PATTERN_STATES = 1000;
2
+ export declare class PatternTooCostly extends Error {
3
+ }
4
+ export type Pattern = {
5
+ readonly test: (text: string) => boolean;
6
+ };
7
+ export declare function linearPattern(source: string): Pattern | null;
8
+ export declare function withLinearRegExp<T>(run: () => T): T;
9
+ export declare function openPatternBudget(): () => void;
10
+ //# sourceMappingURL=pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern.d.ts","sourceRoot":"","sources":["../src/pattern.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,OAAQ,CAAC;AAMpC,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAQ9C,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,CAAC;AAiUnE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAM5D;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAkBnD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,IAAI,CAM9C"}