@markuplint/pug-parser 3.12.0 → 4.0.0-alpha.10

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2019 Yusuke Hirao
3
+ Copyright (c) 2017-2024 Yusuke Hirao
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/lib/index.d.ts CHANGED
@@ -1,2 +1 @@
1
- export { parse } from './parse';
2
- export declare const endTag = 'never';
1
+ export { parser } from './parser.js';
package/lib/index.js CHANGED
@@ -1,6 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.endTag = exports.parse = void 0;
4
- var parse_1 = require("./parse");
5
- Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return parse_1.parse; } });
6
- exports.endTag = 'never';
1
+ export { parser } from './parser.js';
@@ -0,0 +1,29 @@
1
+ import type { ASTNode } from './pug-parser/index.js';
2
+ import type { MLASTAttr, MLASTNodeTreeItem, MLASTParentNode } from '@markuplint/ml-ast';
3
+ import type { ChildToken, Token } from '@markuplint/parser-utils';
4
+ import { ParserError, Parser } from '@markuplint/parser-utils';
5
+ declare class PugParser extends Parser<ASTNode> {
6
+ constructor();
7
+ tokenize(): {
8
+ ast: ASTNode[];
9
+ isFragment: boolean;
10
+ };
11
+ parseError(error: any): ParserError;
12
+ nodeize(originNode: ASTNode, parentNode: MLASTParentNode | null, depth: number): readonly MLASTNodeTreeItem[];
13
+ afterFlattenNodes(nodeList: readonly MLASTNodeTreeItem[]): readonly MLASTNodeTreeItem[];
14
+ visitElement(token: ChildToken & {
15
+ readonly nodeName: string;
16
+ readonly namespace: string;
17
+ }, childNodes: readonly ASTNode[], options: {
18
+ readonly overwriteProps: {
19
+ readonly attributes: readonly MLASTAttr[];
20
+ };
21
+ }): MLASTNodeTreeItem[];
22
+ visitAttr(token: Token): (import("@markuplint/ml-ast").MLASTHTMLAttr & {
23
+ __rightText?: string | undefined;
24
+ }) | (import("@markuplint/ml-ast").MLASTSpreadAttr & {
25
+ __rightText?: string | undefined;
26
+ });
27
+ }
28
+ export declare const parser: PugParser;
29
+ export {};
package/lib/parser.js ADDED
@@ -0,0 +1,162 @@
1
+ import { getNamespace, parser as htmlParser } from '@markuplint/html-parser';
2
+ import { ParserError, Parser, AttrState, removeQuote, scriptParser } from '@markuplint/parser-utils';
3
+ import { pugParse } from './pug-parser/index.js';
4
+ class PugParser extends Parser {
5
+ constructor() {
6
+ super({
7
+ endTagType: 'never',
8
+ });
9
+ }
10
+ tokenize() {
11
+ return {
12
+ ast: pugParse(this.rawCode).nodes,
13
+ isFragment: true,
14
+ };
15
+ }
16
+ parseError(error) {
17
+ if (error instanceof Error && 'msg' in error && 'line' in error && 'column' in error && 'src' in error) {
18
+ return new ParserError(error.msg, {
19
+ line: error.line,
20
+ col: error.column,
21
+ raw: error.src,
22
+ });
23
+ }
24
+ return super.parseError(error);
25
+ }
26
+ nodeize(
27
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
28
+ originNode, parentNode, depth) {
29
+ const parentNamespace = parentNode && 'namespace' in parentNode ? parentNode.namespace : 'http://www.w3.org/1999/xhtml';
30
+ const token = this.sliceFragment(originNode.offset, originNode.endOffset);
31
+ switch (originNode.type) {
32
+ case 'Doctype': {
33
+ return this.visitDoctype({
34
+ ...token,
35
+ depth,
36
+ parentNode,
37
+ name: originNode.val ?? '',
38
+ publicId: '',
39
+ systemId: '',
40
+ });
41
+ }
42
+ case 'Text': {
43
+ if (originNode.raw.trim() === '') {
44
+ return [];
45
+ }
46
+ const htmlDoc = htmlParser.parse(originNode.raw, {
47
+ offsetOffset: originNode.offset,
48
+ offsetLine: originNode.line,
49
+ offsetColumn: originNode.column,
50
+ depth,
51
+ });
52
+ return htmlDoc.nodeList;
53
+ }
54
+ case 'Comment': {
55
+ return this.visitComment({
56
+ ...token,
57
+ depth,
58
+ parentNode,
59
+ }, {
60
+ isBogus: false,
61
+ });
62
+ }
63
+ case 'Tag': {
64
+ const namespace = getNamespace(originNode.name, parentNamespace);
65
+ return this.visitElement({
66
+ ...token,
67
+ depth,
68
+ parentNode,
69
+ nodeName: originNode.name,
70
+ namespace,
71
+ }, originNode.block.nodes, {
72
+ overwriteProps: {
73
+ attributes: originNode.attrs.map(attr => {
74
+ const token = this.sliceFragment(attr.offset, attr.endOffset);
75
+ return this.visitAttr(token);
76
+ }),
77
+ },
78
+ });
79
+ }
80
+ default: {
81
+ return this.visitPsBlock({
82
+ ...token,
83
+ depth,
84
+ parentNode,
85
+ nodeName: originNode.type,
86
+ }, 'block' in originNode && originNode.block ? originNode.block.nodes : []);
87
+ }
88
+ }
89
+ }
90
+ afterFlattenNodes(nodeList) {
91
+ return super.afterFlattenNodes(nodeList, {
92
+ exposeInvalidNode: false,
93
+ exposeWhiteSpace: false,
94
+ });
95
+ }
96
+ visitElement(token,
97
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
98
+ childNodes, options) {
99
+ const startTag = {
100
+ ...token,
101
+ ...this.createToken(token),
102
+ ...options.overwriteProps,
103
+ type: 'starttag',
104
+ elementType: this.detectElementType(token.nodeName),
105
+ childNodes: [],
106
+ pairNode: null,
107
+ tagOpenChar: '',
108
+ tagCloseChar: '',
109
+ isGhost: false,
110
+ };
111
+ const siblings = this.visitChildren(childNodes, startTag);
112
+ return [startTag, ...siblings];
113
+ }
114
+ visitAttr(token) {
115
+ if (token.raw[0] === '#' || token.raw[0] === '.') {
116
+ const attr = super.visitAttr(token, {
117
+ startState: AttrState.BeforeValue,
118
+ quoteSet: [],
119
+ quoteInValueChars: [],
120
+ endOfUnquotedValueChars: [],
121
+ });
122
+ if (attr.type === 'spread') {
123
+ return attr;
124
+ }
125
+ this.updateAttr(attr, {
126
+ potentialName: token.raw[0] === '#' ? 'id' : 'class',
127
+ potentialValue: attr.value.raw.slice(1),
128
+ isDuplicatable: attr.potentialName === 'class',
129
+ });
130
+ return attr;
131
+ }
132
+ const attr = super.visitAttr(token, {
133
+ quoteSet: [],
134
+ quoteInValueChars: [],
135
+ endOfUnquotedValueChars: [],
136
+ });
137
+ if (attr.type === 'spread') {
138
+ return attr;
139
+ }
140
+ if (attr.name.raw.toLowerCase() === 'class') {
141
+ this.updateAttr(attr, { isDuplicatable: true });
142
+ }
143
+ const valueCodeTokens = scriptParser(attr.value.raw.trim());
144
+ if (valueCodeTokens.length === 1) {
145
+ const token = valueCodeTokens[0];
146
+ if (token.type === 'Numeric' || token.type === 'Boolean') {
147
+ this.updateAttr(attr, { potentialValue: token.value });
148
+ }
149
+ else if (token.type === 'String' || token.type === 'Template') {
150
+ this.updateAttr(attr, { potentialValue: removeQuote(token.value) });
151
+ }
152
+ else {
153
+ this.updateAttr(attr, { isDynamicValue: true });
154
+ }
155
+ }
156
+ else {
157
+ this.updateAttr(attr, { isDynamicValue: true });
158
+ }
159
+ return attr;
160
+ }
161
+ }
162
+ export const parser = new PugParser();
@@ -1,21 +1,7 @@
1
1
  export declare function pugParse(pug: string): ASTBlock;
2
2
  export type ASTBlock = PugAST<ASTNode>;
3
- export type ASTNode =
4
- | ASTTagNode
5
- | ASTTextNode
6
- | ASTCodeNode
7
- | ASTComment
8
- | ASTDoctype
9
- | ASTIncludeNode
10
- | ASTMixinNode
11
- | ASTMixinSlotNode
12
- | ASTFilterNode
13
- | ASTEachNode
14
- | ASTConditionalNode
15
- | ASTCaseNode
16
- | ASTCaseWhenNode;
17
- export type ASTTagNode = Omit<PugASTTagNode<ASTAttr, ASTBlock>, 'attributeBlocks' | 'selfClosing' | 'isInline'> &
18
- AdditionalASTData;
3
+ export type ASTNode = ASTTagNode | ASTTextNode | ASTCodeNode | ASTComment | ASTDoctype | ASTIncludeNode | ASTMixinNode | ASTMixinSlotNode | ASTFilterNode | ASTEachNode | ASTConditionalNode | ASTCaseNode | ASTCaseWhenNode;
4
+ export type ASTTagNode = Omit<PugASTTagNode<ASTAttr, ASTBlock>, 'attributeBlocks' | 'selfClosing' | 'isInline'> & AdditionalASTData;
19
5
  export type ASTTextNode = Omit<PugASTTextNode, 'val'> & AdditionalASTData;
20
6
  export type ASTCodeNode = PugASTCodeNode & AdditionalASTData;
21
7
  export type ASTComment = PugASTCommentNode & AdditionalASTData;
@@ -26,135 +12,135 @@ export type ASTMixinSlotNode = PugASTMixinSlotNode & AdditionalASTData;
26
12
  export type ASTFilterNode = PugASTFilterNode<ASTAttr, ASTBlock> & AdditionalASTData;
27
13
  export type ASTEachNode = PugASTEachNode<ASTBlock> & AdditionalASTData;
28
14
  export type ASTConditionalNode = Omit<PugASTConditionalNode<ASTBlock>, 'consequent' | 'alternate'> & {
29
- block: ASTBlock;
15
+ block: ASTBlock;
30
16
  } & AdditionalASTData;
31
17
  export type ASTCaseNode = PugASTCaseNode<ASTBlock> & AdditionalASTData;
32
18
  export type ASTCaseWhenNode = PugASTCaseWhenNode<ASTBlock> & AdditionalASTData;
33
19
  export type ASTAttr = PugASTAttr & AdditionalASTData;
34
20
  type AdditionalASTData = {
35
- raw: string;
36
- offset: number;
37
- endOffset: number;
38
- endLine: number;
39
- endColumn: number;
21
+ raw: string;
22
+ offset: number;
23
+ endOffset: number;
24
+ endLine: number;
25
+ endColumn: number;
40
26
  };
41
27
  interface PugAST<N> {
42
- type: 'Block';
43
- nodes: N[];
44
- line: number;
28
+ type: 'Block';
29
+ nodes: N[];
30
+ line: number;
45
31
  }
46
32
  type PugASTTagNode<A, B> = {
47
- type: 'Tag';
48
- name: string;
49
- selfClosing: boolean;
50
- attrs: A[];
51
- attributeBlocks: never[];
52
- isInline: boolean;
53
- line: number;
54
- column: number;
55
- block: B;
33
+ type: 'Tag';
34
+ name: string;
35
+ selfClosing: boolean;
36
+ attrs: A[];
37
+ attributeBlocks: never[];
38
+ isInline: boolean;
39
+ line: number;
40
+ column: number;
41
+ block: B;
56
42
  };
57
43
  type PugASTTextNode = {
58
- type: 'Text';
59
- val: string;
60
- isHtml?: true;
61
- line: number;
62
- column: number;
44
+ type: 'Text';
45
+ val: string;
46
+ isHtml?: true;
47
+ line: number;
48
+ column: number;
63
49
  };
64
50
  type PugASTCodeNode = {
65
- type: 'Code';
66
- val: string;
67
- buffer: boolean;
68
- mustEscape: boolean;
69
- isInline: boolean;
70
- line: number;
71
- column: number;
51
+ type: 'Code';
52
+ val: string;
53
+ buffer: boolean;
54
+ mustEscape: boolean;
55
+ isInline: boolean;
56
+ line: number;
57
+ column: number;
72
58
  };
73
59
  type PugASTCommentNode = {
74
- type: 'Comment';
75
- val: string;
76
- buffer: boolean;
77
- line: number;
78
- column: number;
60
+ type: 'Comment';
61
+ val: string;
62
+ buffer: boolean;
63
+ line: number;
64
+ column: number;
79
65
  };
80
66
  type PugASTDoctypeNode = {
81
- type: 'Doctype';
82
- val: string;
83
- line: number;
84
- column: number;
67
+ type: 'Doctype';
68
+ val: string;
69
+ line: number;
70
+ column: number;
85
71
  };
86
72
  type PugASTIncludeNode<B> = {
87
- type: 'Include';
88
- file: {
89
- type: 'FileReference';
90
- path: string;
91
- line: number;
92
- column: number;
93
- };
94
- block: B;
95
- line: number;
96
- column: number;
73
+ type: 'Include';
74
+ file: {
75
+ type: 'FileReference';
76
+ path: string;
77
+ line: number;
78
+ column: number;
79
+ };
80
+ block: B;
81
+ line: number;
82
+ column: number;
97
83
  };
98
84
  type PugASTEachNode<B> = {
99
- type: 'Each';
100
- obj: string;
101
- val: string;
102
- key: string | null;
103
- block: B;
104
- line: number;
105
- column: number;
85
+ type: 'Each';
86
+ obj: string;
87
+ val: string;
88
+ key: string | null;
89
+ block: B;
90
+ line: number;
91
+ column: number;
106
92
  };
107
93
  type PugASTMixinNode<A, B> = {
108
- type: 'Mixin';
109
- name: string;
110
- args: string;
111
- call: boolean;
112
- block: B | null;
113
- attrs?: A[];
114
- attributeBlocks: never[];
115
- line: number;
116
- column: number;
94
+ type: 'Mixin';
95
+ name: string;
96
+ args: string;
97
+ call: boolean;
98
+ block: B | null;
99
+ attrs?: A[];
100
+ attributeBlocks: never[];
101
+ line: number;
102
+ column: number;
117
103
  };
118
104
  type PugASTMixinSlotNode = {
119
- type: 'MixinBlock';
120
- line: number;
121
- column: number;
105
+ type: 'MixinBlock';
106
+ line: number;
107
+ column: number;
122
108
  };
123
109
  type PugASTFilterNode<A, B> = {
124
- type: 'Filter';
125
- name: string;
126
- block: B;
127
- attrs: A[];
128
- line: number;
129
- column: number;
110
+ type: 'Filter';
111
+ name: string;
112
+ block: B;
113
+ attrs: A[];
114
+ line: number;
115
+ column: number;
130
116
  };
131
117
  type PugASTConditionalNode<B> = {
132
- type: 'Conditional';
133
- test: string;
134
- consequent: B;
135
- alternate?: B | PugASTConditionalNode<B>;
136
- line: number;
137
- column: number;
118
+ type: 'Conditional';
119
+ test: string;
120
+ consequent: B;
121
+ alternate?: B | PugASTConditionalNode<B>;
122
+ line: number;
123
+ column: number;
138
124
  };
139
125
  type PugASTCaseNode<B> = {
140
- type: 'Case';
141
- expr: string;
142
- block: B;
143
- line: number;
144
- column: number;
126
+ type: 'Case';
127
+ expr: string;
128
+ block: B;
129
+ line: number;
130
+ column: number;
145
131
  };
146
132
  type PugASTCaseWhenNode<B> = {
147
- type: 'When';
148
- expr: string;
149
- block: B;
150
- line: number;
151
- column: number;
133
+ type: 'When';
134
+ expr: string;
135
+ block: B;
136
+ line: number;
137
+ column: number;
152
138
  };
153
139
  type PugASTAttr = {
154
- name: string;
155
- val: string | true;
156
- mustEscape: boolean;
157
- line: number;
158
- column: number;
140
+ name: string;
141
+ val: string | true;
142
+ mustEscape: boolean;
143
+ line: number;
144
+ column: number;
159
145
  };
160
146
  export {};
@@ -1,24 +1,17 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pugParse = void 0;
4
- const tslib_1 = require("tslib");
5
1
  // @ts-ignore
6
- const pug_lexer_1 = tslib_1.__importDefault(require("pug-lexer"));
2
+ import lexer from 'pug-lexer';
7
3
  // @ts-ignore
8
- const pug_parser_1 = tslib_1.__importDefault(require("pug-parser"));
9
- const get_offset_from_line_and_col_1 = require("../utils/get-offset-from-line-and-col");
10
- function pugParse(pug) {
11
- const lexOrigin = (0, pug_lexer_1.default)(pug);
4
+ import parser from 'pug-parser';
5
+ import { getOffsetFromLineAndCol } from '../utils/get-offset-from-line-and-col.js';
6
+ export function pugParse(pug) {
7
+ const lexOrigin = lexer(pug);
12
8
  const lex = JSON.parse(JSON.stringify(lexOrigin));
13
- const originAst = (0, pug_parser_1.default)(lexOrigin);
14
- // console.log(lex);
15
- // console.log(JSON.stringify(originAst, null, 2));
9
+ const originAst = parser(lexOrigin);
16
10
  const ast = optimizeAST(originAst, lex, pug);
17
11
  return ast;
18
12
  }
19
- exports.pugParse = pugParse;
20
13
  function getOffsetsFromLines(pug) {
21
- const lines = pug.split(/\n/g);
14
+ const lines = pug.split(/\n/);
22
15
  let chars = 0;
23
16
  const result = lines.map(line => {
24
17
  chars += line.length + 1;
@@ -29,10 +22,9 @@ function getOffsetsFromLines(pug) {
29
22
  function mergeTextNode(
30
23
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
31
24
  nodes, pug) {
32
- var _a;
33
25
  const baseNodes = [];
34
26
  for (const node of nodes) {
35
- const prevNode = (_a = baseNodes[baseNodes.length - 1]) !== null && _a !== void 0 ? _a : null;
27
+ const prevNode = baseNodes.at(-1) ?? null;
36
28
  if (prevNode && prevNode.type === 'Text' && node.type === 'Text') {
37
29
  prevNode.raw = pug.slice(prevNode.offset, node.endOffset);
38
30
  prevNode.endColumn = node.endColumn;
@@ -55,13 +47,12 @@ function optimizeAST(
55
47
  originalAST,
56
48
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
57
49
  tokens, pug) {
58
- var _a;
59
50
  const nodes = [];
60
51
  for (const node of originalAST.nodes) {
61
52
  const line = node.line;
62
53
  const column = node.column;
63
54
  const offsets = getOffsetsFromLines(pug);
64
- const lineOffset = Math.max((_a = offsets[line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
55
+ const lineOffset = Math.max(offsets[line - 2] ?? 0, 0);
65
56
  const offset = lineOffset + column - 1;
66
57
  const { endLine, endColumn, endOffset } = getLocationFromToken(offset, line, column, tokens);
67
58
  const raw = pug.slice(offset, endOffset);
@@ -299,8 +290,9 @@ tokens, pug) {
299
290
  continue;
300
291
  }
301
292
  default: {
293
+ throw new Error(`Unsupported syntax: The "${
302
294
  // @ts-ignore
303
- throw new Error(`Unsupported syntax: The "${node.type}" node\n${JSON.stringify(node, null, 2)}`);
295
+ node.type}" node\n${JSON.stringify(node, null, 2)}`);
304
296
  }
305
297
  }
306
298
  }
@@ -316,7 +308,6 @@ function optimizeASTOfConditionalNode(
316
308
  node,
317
309
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
318
310
  tokens, pug, offsets, depth) {
319
- var _a, _b;
320
311
  const altNodes = [];
321
312
  let tokenOfCurrentNode = null;
322
313
  for (const token of tokens) {
@@ -327,7 +318,7 @@ tokens, pug, offsets, depth) {
327
318
  }
328
319
  if (tokenOfCurrentNode) {
329
320
  // console.log(JSON.stringify(node, null, 2));
330
- const lineOffset = Math.max((_a = offsets[node.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
321
+ const lineOffset = Math.max(offsets[node.line - 2] ?? 0, 0);
331
322
  const offset = lineOffset + node.column - 1;
332
323
  const length = tokenOfCurrentNode.loc.end.column - tokenOfCurrentNode.loc.start.column;
333
324
  const endOffset = offset + length;
@@ -359,7 +350,7 @@ tokens, pug, offsets, depth) {
359
350
  if (!tokenOfCurrentNode) {
360
351
  return [];
361
352
  }
362
- const lineOffset = Math.max((_b = offsets[tokenOfCurrentNode.loc.start.line - 2]) !== null && _b !== void 0 ? _b : 0, 0);
353
+ const lineOffset = Math.max(offsets[tokenOfCurrentNode.loc.start.line - 2] ?? 0, 0);
363
354
  const offset = lineOffset + tokenOfCurrentNode.loc.start.column - 1;
364
355
  const length = tokenOfCurrentNode.loc.end.column - tokenOfCurrentNode.loc.start.column;
365
356
  const endOffset = offset + length;
@@ -390,7 +381,7 @@ tokens, pug, offsets, depth) {
390
381
  function getLocationFromToken(offset, line, column,
391
382
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
392
383
  tokens, tokenType) {
393
- const tokenTypes = typeof tokenType === 'string' ? (tokenType !== '' ? [tokenType] : null) : tokenType !== null && tokenType !== void 0 ? tokenType : null;
384
+ const tokenTypes = typeof tokenType === 'string' ? (tokenType === '' ? null : [tokenType]) : tokenType ?? null;
394
385
  let tokenOfCurrentNode = null;
395
386
  for (const token of tokens) {
396
387
  if ((tokenTypes == null || tokenTypes.includes(token.type)) &&
@@ -416,10 +407,9 @@ function getAttrs(
416
407
  originalAttrs,
417
408
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
418
409
  tokens, offsets, pug) {
419
- var _a;
420
410
  const attrs = [];
421
411
  for (const attr of originalAttrs) {
422
- const attrLineOffset = (_a = offsets[attr.line - 2]) !== null && _a !== void 0 ? _a : 0;
412
+ const attrLineOffset = offsets[attr.line - 2] ?? 0;
423
413
  const attrOffset = attrLineOffset + attr.column - 1;
424
414
  let tokenOfCurrentAttr = null;
425
415
  for (const token of tokens) {
@@ -452,7 +442,6 @@ tokens, offsets, pug) {
452
442
  function getEndAttributeLocation(nodeName, offset, line, column,
453
443
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
454
444
  tokens, offsets) {
455
- var _a;
456
445
  let beforeNewlineToken = null;
457
446
  for (const token of tokens) {
458
447
  // Searching token after the tag node.
@@ -463,7 +452,7 @@ tokens, offsets) {
463
452
  token.type !== 'end-attributes' &&
464
453
  token.type !== 'id' &&
465
454
  token.type !== 'class') {
466
- const endAttrLineOffset = Math.max((_a = offsets[beforeNewlineToken.loc.end.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
455
+ const endAttrLineOffset = Math.max(offsets[beforeNewlineToken.loc.end.line - 2] ?? 0, 0);
467
456
  const endAttrOffset = endAttrLineOffset + beforeNewlineToken.loc.end.column - 1;
468
457
  return {
469
458
  endOffset: endAttrOffset,
@@ -500,8 +489,8 @@ tokens) {
500
489
  if (startPipelessText.loc.start.line < node.line && node.line < endPipelessText.loc.start.line) {
501
490
  const { line, column } = startPipelessText.loc.start;
502
491
  const { line: endLine, column: endColumn } = endPipelessText.loc.end;
503
- const offset = (0, get_offset_from_line_and_col_1.getOffsetFromLineAndCol)(pug, line, column);
504
- const endOffset = (0, get_offset_from_line_and_col_1.getOffsetFromLineAndCol)(pug, endLine, endColumn);
492
+ const offset = getOffsetFromLineAndCol(pug, line, column);
493
+ const endOffset = getOffsetFromLineAndCol(pug, endLine, endColumn);
505
494
  const raw = pug.slice(offset, endOffset);
506
495
  return {
507
496
  raw,
@@ -518,7 +507,6 @@ tokens) {
518
507
  function getRawTextAndLocationEnd(val, offset, line, column,
519
508
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
520
509
  tokens, offsets, pug) {
521
- var _a;
522
510
  let beforeNewlineToken = null;
523
511
  for (const token of tokens) {
524
512
  // Searching token after the text.
@@ -528,7 +516,7 @@ tokens, offsets, pug) {
528
516
  token.type !== 'text-html' &&
529
517
  token.type !== 'indent' &&
530
518
  token.type !== 'outdent') {
531
- const endAttrLineOffset = Math.max((_a = offsets[beforeNewlineToken.loc.end.line - 2]) !== null && _a !== void 0 ? _a : 0, 0);
519
+ const endAttrLineOffset = Math.max(offsets[beforeNewlineToken.loc.end.line - 2] ?? 0, 0);
532
520
  const endAttrOffset = endAttrLineOffset + beforeNewlineToken.loc.end.column - 1;
533
521
  return {
534
522
  endOffset: endAttrOffset,
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getOffsetFromLineAndCol = void 0;
4
- function getOffsetFromLineAndCol(str, line, col) {
1
+ export function getOffsetFromLineAndCol(str, line, col) {
5
2
  const lines = str.split('\n').slice(0, line);
6
3
  const lastLine = lines.pop();
7
4
  if (lastLine) {
8
- lines.push(lastLine.split('').slice(0, col).join(''));
5
+ lines.push([...lastLine].slice(0, col).join(''));
9
6
  }
10
7
  return lines.join('\n').length;
11
8
  }
12
- exports.getOffsetFromLineAndCol = getOffsetFromLineAndCol;