@markuplint/pug-parser 4.6.22 → 4.18.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.
@@ -3,6 +3,15 @@ import lexer from 'pug-lexer';
3
3
  import parser from 'pug-parser';
4
4
  import { getOffsetFromLineAndCol } from '../utils/get-offset-from-line-and-col.js';
5
5
  import { getOffsetsFromCode } from '@markuplint/parser-utils/location';
6
+ /**
7
+ * Parses a Pug template string into an optimized AST with computed offsets
8
+ * and location data by lexing with pug-lexer, parsing with pug-parser,
9
+ * and then enriching each node with raw source, offsets, and end positions.
10
+ *
11
+ * @param pug - The raw Pug template source code
12
+ * @param useOffset - Whether to strip indent/outdent tokens (used when parsing at a non-zero offset)
13
+ * @returns The optimized Pug AST block containing enriched nodes
14
+ */
6
15
  export function pugParse(pug, useOffset = false) {
7
16
  let lexOrigin = lexer(pug);
8
17
  /**
@@ -23,6 +32,13 @@ export function pugParse(pug, useOffset = false) {
23
32
  const ast = optimizeAST(originAst, lex, pug);
24
33
  return ast;
25
34
  }
35
+ /**
36
+ * Computes the cumulative character offset at the end of each line
37
+ * in the given source string.
38
+ *
39
+ * @param pug - The raw Pug template source code
40
+ * @returns An array where each index corresponds to a line and the value is the cumulative offset
41
+ */
26
42
  function getOffsetsFromLines(pug) {
27
43
  const lines = pug.split(/\n/);
28
44
  let chars = 0;
@@ -32,6 +48,14 @@ function getOffsetsFromLines(pug) {
32
48
  });
33
49
  return result;
34
50
  }
51
+ /**
52
+ * Merges consecutive Text nodes into a single Text node, combining
53
+ * their raw source and extending the end location of the first node.
54
+ *
55
+ * @param nodes - The array of AST nodes to process
56
+ * @param pug - The raw Pug template source code
57
+ * @returns A new array with adjacent Text nodes merged together
58
+ */
35
59
  function mergeTextNode(
36
60
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
37
61
  nodes, pug) {
@@ -50,10 +74,14 @@ nodes, pug) {
50
74
  return baseNodes;
51
75
  }
52
76
  /**
77
+ * Transforms the raw pug-parser AST into an optimized AST by computing
78
+ * accurate source offsets, raw text slices, and end positions for each node.
79
+ * Recursively processes child blocks and merges adjacent text nodes.
53
80
  *
54
- * @param originalAST
55
- * @param tokens Lexed token list
56
- * @param pug Raw code
81
+ * @param originalAST - The raw AST block from pug-parser, or null
82
+ * @param tokens - The lexed token list from pug-lexer
83
+ * @param pug - The raw Pug template source code
84
+ * @returns The optimized AST block with enriched location data
57
85
  */
58
86
  function optimizeAST(
59
87
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
@@ -471,6 +499,17 @@ tokens, pug) {
471
499
  line: originalAST.line,
472
500
  };
473
501
  }
502
+ /**
503
+ * Recursively processes conditional node chains (`else if` / `else`) in the Pug AST,
504
+ * computing location data for each alternate branch.
505
+ *
506
+ * @param node - The Pug conditional AST node with potential alternate branches
507
+ * @param tokens - The lexed token list from pug-lexer
508
+ * @param pug - The raw Pug template source code
509
+ * @param offsets - Precomputed line offset array
510
+ * @param depth - The current recursion depth for tracking nested conditionals
511
+ * @returns An array of optimized conditional nodes for the alternate branches
512
+ */
474
513
  function optimizeASTOfConditionalNode(
475
514
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
476
515
  node,
@@ -548,6 +587,17 @@ tokens, pug, offsets, depth) {
548
587
  }
549
588
  return altNodes;
550
589
  }
590
+ /**
591
+ * Finds the matching lexer token for a node at the given position and returns
592
+ * its end location and length.
593
+ *
594
+ * @param offset - The character offset of the node's start
595
+ * @param line - The 1-based line number of the node
596
+ * @param column - The 1-based column number of the node
597
+ * @param tokens - The lexed token list from pug-lexer
598
+ * @param tokenType - Optional token type(s) to filter by
599
+ * @returns An object with endLine, endColumn, endOffset, and length
600
+ */
551
601
  function getLocationFromToken(offset, line, column,
552
602
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
553
603
  tokens, tokenType) {
@@ -572,6 +622,17 @@ tokens, tokenType) {
572
622
  length,
573
623
  };
574
624
  }
625
+ /**
626
+ * Extracts and enriches attribute data from the original Pug AST attributes
627
+ * by correlating each attribute with its corresponding lexer token to compute
628
+ * accurate offsets and raw source slices.
629
+ *
630
+ * @param originalAttrs - The original attribute list from the Pug AST
631
+ * @param tokens - The lexed token list from pug-lexer
632
+ * @param offsets - Precomputed line offset array
633
+ * @param pug - The raw Pug template source code
634
+ * @returns An array of enriched attribute objects with computed location data
635
+ */
575
636
  function getAttrs(
576
637
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
577
638
  originalAttrs,
@@ -609,6 +670,19 @@ tokens, offsets, pug) {
609
670
  }
610
671
  return attrs;
611
672
  }
673
+ /**
674
+ * Determines the end position of a tag node including its attributes
675
+ * by scanning lexer tokens that follow the tag's position and precede
676
+ * non-attribute tokens.
677
+ *
678
+ * @param nodeName - The tag name of the element
679
+ * @param offset - The character offset of the tag's start
680
+ * @param line - The 1-based line number of the tag
681
+ * @param column - The 1-based column number of the tag
682
+ * @param tokens - The lexed token list from pug-lexer
683
+ * @param offsets - Precomputed line offset array
684
+ * @returns An object with endOffset, endLine, and endColumn
685
+ */
612
686
  function getEndAttributeLocation(nodeName, offset, line, column,
613
687
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
614
688
  tokens, offsets) {
@@ -638,6 +712,15 @@ tokens, offsets) {
638
712
  endColumn: column + nodeName.length,
639
713
  };
640
714
  }
715
+ /**
716
+ * Detects whether a Text node is part of a pipeless text block (indented
717
+ * text content below a tag) and returns its full span if so.
718
+ *
719
+ * @param node - The Pug Text AST node to check
720
+ * @param pug - The raw Pug template source code
721
+ * @param tokens - The lexed token list from pug-lexer
722
+ * @returns Location data for the pipeless text span, or null if not pipeless text
723
+ */
641
724
  function getPipelessText(
642
725
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
643
726
  node, pug,
@@ -674,6 +757,19 @@ tokens) {
674
757
  }
675
758
  return null;
676
759
  }
760
+ /**
761
+ * Extracts raw text content and computes accurate end locations for a Text node
762
+ * by walking through lexer tokens from the node's start position. Handles
763
+ * multi-line text, piped text detection, and indentation tracking.
764
+ *
765
+ * @param val - The text value from the Pug AST node
766
+ * @param offset - The character offset where the text starts
767
+ * @param line - The 1-based start line number
768
+ * @param column - The 1-based start column number
769
+ * @param tokens - The lexed token list from pug-lexer
770
+ * @param pug - The raw Pug template source code
771
+ * @returns An array of ASTText nodes with computed location data
772
+ */
677
773
  function getRawTextAndLocationEnd(val, offset, line, column,
678
774
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
679
775
  tokens, pug) {
package/lib/types.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Additional location and raw source data that is computed during AST optimization
3
+ * and appended to the original Pug AST node types.
4
+ */
1
5
  export type AdditionalASTData = {
2
6
  raw: string;
3
7
  offset: number;
@@ -5,59 +9,84 @@ export type AdditionalASTData = {
5
9
  endLine: number;
6
10
  endColumn: number;
7
11
  };
12
+ /** Union of all optimized Pug AST node types that the parser can produce. */
8
13
  export type ASTNode = ASTDoctype | ASTComment | ASTBlockComment | ASTText | ASTTag | ASTInterpolatedTag | ASTCode | ASTConditional | ASTCase | ASTWhen | ASTWhile | ASTEach | ASTMixin | ASTMixinBlock | ASTYieldBlock | ASTFileReference | ASTInclude | ASTRawInclude | ASTIncludeFilter | ASTExtends | ASTNamedBlock | ASTFilter;
14
+ /** Represents a Pug block containing an ordered list of child nodes. */
9
15
  export type ASTBlock = {
10
16
  type: 'Block';
11
17
  nodes: readonly ASTNode[];
12
18
  line: number;
13
19
  };
20
+ /** An optimized Pug doctype node with computed location data. */
14
21
  export type ASTDoctype = PugAST.Doctype & AdditionalASTData;
22
+ /** An optimized Pug single-line comment node with computed location data. */
15
23
  export type ASTComment = PugAST.Comments.Comment & AdditionalASTData;
24
+ /** An optimized Pug block comment node with computed location data and an optimized child block. */
16
25
  export type ASTBlockComment = Omit<PugAST.Comments.BlockComment, 'block'> & {
17
26
  block: ASTBlock | null;
18
27
  } & AdditionalASTData;
28
+ /** An optimized Pug text node with computed location data. */
19
29
  export type ASTText = PugAST.Text & AdditionalASTData;
30
+ /** An optimized Pug tag node with computed attributes and child block. */
20
31
  export type ASTTag = Omit<PugAST.Tag, 'attrs' | 'block'> & {
21
32
  attrs: readonly ASTAttr[];
22
33
  block: ASTBlock | null;
23
34
  } & AdditionalASTData;
35
+ /** An optimized Pug interpolated tag node with computed child block. */
24
36
  export type ASTInterpolatedTag = Omit<PugAST.InterpolatedTag, 'block'> & {
25
37
  block: ASTBlock | null;
26
38
  } & AdditionalASTData;
39
+ /** An optimized Pug code node (unbuffered/buffered JavaScript) with computed child block. */
27
40
  export type ASTCode = Omit<PugAST.Code, 'block'> & {
28
41
  block: ASTBlock | null;
29
42
  } & AdditionalASTData;
43
+ /** An optimized Pug conditional (`if`/`else if`/`else`) node with computed child block. */
30
44
  export type ASTConditional = Omit<PugAST.CodeHelpers.Conditional, 'consequent' | 'alternate'> & {
31
45
  block: ASTBlock | null;
32
46
  } & AdditionalASTData;
47
+ /** An optimized Pug `case` node with computed child block. */
33
48
  export type ASTCase = Omit<PugAST.CodeHelpers.CaseWhen.Case, 'block'> & {
34
49
  block: ASTBlock | null;
35
50
  } & AdditionalASTData;
51
+ /** An optimized Pug `when` node with computed child block. */
36
52
  export type ASTWhen = Omit<PugAST.CodeHelpers.CaseWhen.When, 'block'> & {
37
53
  block: ASTBlock | null;
38
54
  } & AdditionalASTData;
55
+ /** An optimized Pug `while` loop node with computed location data. */
39
56
  export type ASTWhile = PugAST.While & AdditionalASTData;
57
+ /** An optimized Pug `each` iteration node with computed child block. */
40
58
  export type ASTEach = Omit<PugAST.Each, 'block' | 'alternate'> & {
41
59
  block: ASTBlock | null;
42
60
  } & AdditionalASTData;
61
+ /** An optimized Pug mixin (definition or call) node with computed child block. */
43
62
  export type ASTMixin = Omit<PugAST.Mixin, 'block'> & {
44
63
  block: ASTBlock | null;
45
64
  } & AdditionalASTData;
65
+ /** An optimized Pug `block` placeholder inside a mixin definition. */
46
66
  export type ASTMixinBlock = PugAST.MixinBlock & AdditionalASTData;
67
+ /** An optimized Pug `yield` block placeholder. */
47
68
  export type ASTYieldBlock = PugAST.YieldBlock & AdditionalASTData;
69
+ /** An optimized Pug file reference node with computed location data. */
48
70
  export type ASTFileReference = PugAST.FileOperations.FileReference & AdditionalASTData;
71
+ /** An optimized Pug `include` node with computed child block. */
49
72
  export type ASTInclude = Omit<PugAST.FileOperations.Include, 'block'> & {
50
73
  block: ASTBlock | null;
51
74
  } & AdditionalASTData;
75
+ /** An optimized Pug raw `include` node with computed location data. */
52
76
  export type ASTRawInclude = PugAST.FileOperations.RawInclude & AdditionalASTData;
77
+ /** An optimized Pug include filter node with computed location data. */
53
78
  export type ASTIncludeFilter = PugAST.FileOperations.IncludeFilter & AdditionalASTData;
79
+ /** An optimized Pug `extends` node with computed location data. */
54
80
  export type ASTExtends = PugAST.FileOperations.Extends & AdditionalASTData;
81
+ /** An optimized Pug named block node with computed child nodes. */
55
82
  export type ASTNamedBlock = Omit<PugAST.FileOperations.NamedBlock, 'nodes'> & {
56
83
  nodes: readonly ASTNode[];
57
84
  } & AdditionalASTData;
85
+ /** An optimized Pug filter node with computed child block. */
58
86
  export type ASTFilter = Omit<PugAST.Filter, 'block'> & {
59
87
  block: ASTBlock | null;
60
88
  } & AdditionalASTData;
89
+ /** An optimized Pug attribute with computed location and raw source data. */
61
90
  export type ASTAttr = PugAST.AbstractNodeTypes.Attribute & AdditionalASTData;
62
91
  export declare namespace PugAST {
63
92
  /**
@@ -1 +1,11 @@
1
+ /**
2
+ * Calculates the character offset in a string from a 1-based line number
3
+ * and 1-based column number. Handles multi-byte characters correctly
4
+ * by splitting lines into individual characters.
5
+ *
6
+ * @param str - The source string to compute the offset within
7
+ * @param line - The 1-based line number
8
+ * @param col - The 1-based column number
9
+ * @returns The 0-based character offset corresponding to the given line and column
10
+ */
1
11
  export declare function getOffsetFromLineAndCol(str: string, line: number, col: number): number;
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Calculates the character offset in a string from a 1-based line number
3
+ * and 1-based column number. Handles multi-byte characters correctly
4
+ * by splitting lines into individual characters.
5
+ *
6
+ * @param str - The source string to compute the offset within
7
+ * @param line - The 1-based line number
8
+ * @param col - The 1-based column number
9
+ * @returns The 0-based character offset corresponding to the given line and column
10
+ */
1
11
  export function getOffsetFromLineAndCol(str, line, col) {
2
12
  const lines = str.split('\n').slice(0, line);
3
13
  const lastLine = lines.pop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/pug-parser",
3
- "version": "4.6.22",
3
+ "version": "4.18.0",
4
4
  "description": "Pug parser for markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -21,11 +21,11 @@
21
21
  "clean": "tsc --build --clean tsconfig.build.json"
22
22
  },
23
23
  "dependencies": {
24
- "@markuplint/html-parser": "4.6.22",
25
- "@markuplint/ml-ast": "4.4.10",
26
- "@markuplint/parser-utils": "4.8.10",
24
+ "@markuplint/html-parser": "4.18.0",
25
+ "@markuplint/ml-ast": "4.18.0",
26
+ "@markuplint/parser-utils": "4.18.0",
27
27
  "pug-lexer": "5.0.1",
28
28
  "pug-parser": "6.0.0"
29
29
  },
30
- "gitHead": "6213ea30269ef404f030e67bbcc7fc7443ec1060"
30
+ "gitHead": "1885af6349def3f19df975b9e9c399dd47361de1"
31
31
  }