tarsec 0.4.6 → 0.5.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.
@@ -16,27 +16,44 @@ export const linkDefinitionParser = seqC(set("type", "link-definition"), char("[
16
16
  export const footnoteDefinitionParser = seqC(set("type", "footnote-definition"), str("[^"), capture(many1WithJoin(noneOf("] \n\t")), "id"), str("]:"), spaces, capture(many1WithJoin(noneOf("\n")), "content"));
17
17
  /* Resolution pass.
18
18
  *
19
- * Walk the AST. Collect link-definitions, then rewrite ref nodes to inline
20
- * links/images and strip the definitions. Id matching is case-insensitive. */
19
+ * Walk the AST. Collect link/footnote definitions (deeply they can now
20
+ * appear nested inside list-item block children), then rewrite ref nodes to
21
+ * inline links/images and strip the definitions everywhere they appear. Id
22
+ * matching is case-insensitive. */
23
+ const CHILD_KEYS = ["content", "items", "rows"];
24
+ const isDef = (n) => isObj(n) &&
25
+ (n.type === "link-definition" ||
26
+ n.type === "footnote-definition");
21
27
  export function resolveReferences(ast) {
22
28
  const linkDefs = new Map();
23
29
  const footnoteDefs = new Map();
24
- for (const node of ast) {
30
+ function collect(node) {
31
+ if (Array.isArray(node)) {
32
+ node.forEach(collect);
33
+ return;
34
+ }
25
35
  if (!isObj(node))
26
- continue;
27
- const t = node.type;
36
+ return;
37
+ const obj = node;
38
+ const t = obj.type;
28
39
  if (t === "link-definition") {
29
- const def = node;
40
+ const def = obj;
30
41
  linkDefs.set(def.id.toLowerCase(), def);
31
42
  }
32
43
  else if (t === "footnote-definition") {
33
- const def = node;
44
+ const def = obj;
34
45
  footnoteDefs.set(def.id.toLowerCase(), def);
35
46
  }
47
+ for (const key of CHILD_KEYS) {
48
+ if (Array.isArray(obj[key]))
49
+ obj[key].forEach(collect);
50
+ }
36
51
  }
52
+ collect(ast);
37
53
  function walk(node) {
38
- if (Array.isArray(node))
39
- return node.map(walk);
54
+ if (Array.isArray(node)) {
55
+ return node.filter((n) => !isDef(n)).map(walk);
56
+ }
40
57
  if (!isObj(node))
41
58
  return node;
42
59
  const obj = node;
@@ -75,21 +92,17 @@ export function resolveReferences(ast) {
75
92
  }
76
93
  return { type: "inline-text", content: `[^${obj.id}]` };
77
94
  }
78
- // recurse into known child-bearing fields
95
+ // Recurse into known child-bearing fields. The array path through `walk`
96
+ // also strips nested link/footnote definitions, so list items, blockquotes,
97
+ // etc. all get the same treatment as the top-level array.
79
98
  const out = Object.assign({}, obj);
80
- for (const key of ["content", "items", "rows"]) {
99
+ for (const key of CHILD_KEYS) {
81
100
  if (Array.isArray(obj[key]))
82
- out[key] = obj[key].map(walk);
101
+ out[key] = walk(obj[key]);
83
102
  }
84
- if (obj.sublist)
85
- out.sublist = walk(obj.sublist);
86
103
  return out;
87
104
  }
88
- return ast
89
- .filter((n) => !(isObj(n) &&
90
- (n.type === "link-definition" ||
91
- n.type === "footnote-definition")))
92
- .map(walk);
105
+ return walk(ast);
93
106
  }
94
107
  function isObj(v) {
95
108
  return typeof v === "object" && v !== null;
@@ -76,11 +76,13 @@ export type InlineRefImage = {
76
76
  id: string;
77
77
  };
78
78
  export type ListItem = {
79
- content: InlineMarkdown[];
80
- sublist?: List;
79
+ content: Block[];
81
80
  /** GFM task-list state: `true` for `[x]`/`[X]`, `false` for `[ ]`, absent for plain items. */
82
81
  checked?: boolean;
83
82
  };
83
+ export type Block = Paragraph | Heading | CodeBlock | List | BlockQuote | HorizontalRule | Table | HTMLBlock | Image | LinkDef | FootnoteDef;
84
+ /** Top-level node in the markdown AST (optionally prefixed by frontmatter). */
85
+ export type MarkdownNode = Block | Frontmatter;
84
86
  export type List = {
85
87
  type: "list";
86
88
  ordered: boolean;
package/dist/parsers.d.ts CHANGED
@@ -47,6 +47,18 @@ export declare function noneOf(chars: string): Parser<string>;
47
47
  * ```
48
48
  */
49
49
  export type CharPredicate = (code: number) => boolean;
50
+ /**
51
+ * Compile a string of allowed characters or a user-supplied predicate
52
+ * into a fast `CharPredicate`. For string inputs whose characters are
53
+ * all ASCII (code points < 128), the result is a single 128-byte
54
+ * `Uint8Array` lookup — one array read per character test. Non-ASCII
55
+ * characters in the string fall back to a `Set<number>` check.
56
+ * Predicates pass through unchanged.
57
+ *
58
+ * @param charsOrPred - a string of allowed characters or a predicate function
59
+ * @returns - a `CharPredicate` suitable for use in tight scanning loops
60
+ */
61
+ export declare function compileCharPredicate(charsOrPred: string | CharPredicate): CharPredicate;
50
62
  /**
51
63
  * A faster version of many/ manyWithJoin for character-class scanning.
52
64
  *
package/dist/parsers.js CHANGED
@@ -104,7 +104,7 @@ export function noneOf(chars) {
104
104
  * @param charsOrPred - a string of allowed characters or a predicate function
105
105
  * @returns - a `CharPredicate` suitable for use in tight scanning loops
106
106
  */
107
- function compileCharPredicate(charsOrPred) {
107
+ export function compileCharPredicate(charsOrPred) {
108
108
  if (typeof charsOrPred === "function")
109
109
  return charsOrPred;
110
110
  const chars = charsOrPred;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tarsec",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "description": "A parser combinator library for TypeScript, inspired by Parsec.",
5
5
  "homepage": "https://github.com/egonSchiele/tarsec",
6
6
  "scripts": {
@@ -24,6 +24,11 @@
24
24
  "import": "./dist/parsers/markdown/index.js",
25
25
  "require": "./dist/parsers/markdown/index.js",
26
26
  "types": "./dist/parsers/markdown/index.d.ts"
27
+ },
28
+ "./parsers/bash": {
29
+ "import": "./dist/parsers/bash/index.js",
30
+ "require": "./dist/parsers/bash/index.js",
31
+ "types": "./dist/parsers/bash/index.d.ts"
27
32
  }
28
33
  },
29
34
  "type": "module",