@wuchale/astro 0.2.4 → 0.2.6

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.
@@ -6,16 +6,18 @@ import { Transformer } from 'wuchale/adapter-vanilla';
6
6
  export declare function parseExpr(content: string): [Estree.Expression, Estree.Comment[][]];
7
7
  type MixedAstroNodes = Node;
8
8
  export declare class AstroTransformer extends Transformer {
9
+ byteArray: Uint8Array;
9
10
  currentElement?: string;
10
11
  inCompoundText: boolean;
11
12
  frontMatterStart?: number;
12
13
  mixedVisitor: MixedVisitor<MixedAstroNodes>;
13
- correctedExprRanges: WeakMap<Node, {
14
+ correctedExprRanges: WeakMap<Node | AttributeNode, {
14
15
  start: number;
15
16
  end: number;
16
17
  }>;
17
18
  constructor(content: string, filename: string, index: IndexTracker, heuristic: HeuristicFunc, patterns: CodePattern[], catalogExpr: CatalogExpr, rtConf: RuntimeConf, matchUrl: UrlMatcher);
18
- _saveCorrectedExprRanges: (nodes: Node[], containerEnd: number) => void;
19
+ _byteOffsetToIndex: (offset?: number) => number;
20
+ _saveCorrectedRanges: (nodes: Node[], containerEnd: number) => void;
19
21
  getRange: (node: Node | AttributeNode) => {
20
22
  start: number;
21
23
  end: number;
@@ -9,10 +9,12 @@ export function parseExpr(content) {
9
9
  const [opts, comments] = scriptParseOptionsWithComments();
10
10
  return [ExprParser.parseExpressionAt(content, 0, opts), comments];
11
11
  }
12
- // Astro nodes that can have children
13
- const nodesWithChildren = ['element', 'component', 'custom-element', 'fragment'];
12
+ const tagNodes = ['element', 'component', 'custom-element'];
13
+ const nodesWithChildren = [...tagNodes, 'fragment'];
14
14
  const rtRenderFunc = '_w_Tx_';
15
+ const u8decoder = new TextDecoder();
15
16
  export class AstroTransformer extends Transformer {
17
+ byteArray;
16
18
  // state
17
19
  currentElement;
18
20
  inCompoundText = false;
@@ -23,38 +25,52 @@ export class AstroTransformer extends Transformer {
23
25
  constructor(content, filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl) {
24
26
  // trim() is VERY important, without it offset positions become wrong due to astro's parser
25
27
  super(content.trim(), filename, index, heuristic, patterns, catalogExpr, rtConf, matchUrl);
28
+ this.byteArray = new Uint8Array(Buffer.from(this.content));
26
29
  this.heuristciDetails.insideProgram = false;
27
30
  }
28
- _saveCorrectedExprRanges = (nodes, containerEnd) => {
31
+ _byteOffsetToIndex = (offset) => {
32
+ // this is necessary because offsets come from astro's go parser, which works with bytes
33
+ // and that can cause misalignments when there are unicode characters
34
+ if (offset === undefined) {
35
+ return -1;
36
+ }
37
+ return u8decoder.decode(this.byteArray.slice(0, offset)).length;
38
+ };
39
+ _saveCorrectedRanges = (nodes, containerEnd) => {
29
40
  for (const [i, child] of nodes.entries()) {
30
- if (child.type !== 'expression') {
41
+ const isExpr = child.type === 'expression';
42
+ const isTag = tagNodes.includes(child.type);
43
+ if (!(isExpr || isTag)) {
31
44
  continue;
32
45
  }
46
+ let start = this._byteOffsetToIndex(child.position?.start?.offset);
47
+ if (isExpr) {
48
+ start = this.content.indexOf('{', start);
49
+ }
33
50
  const nextChild = nodes[i + 1];
34
- let actualEnd;
51
+ let end = this._byteOffsetToIndex(child.position?.end?.offset);
35
52
  if (nextChild != null) {
36
- actualEnd = nextChild.position?.start?.offset ?? 0;
53
+ end = this._byteOffsetToIndex(nextChild.position?.start?.offset);
37
54
  if (nextChild.type === 'expression') {
38
- actualEnd = this.content.indexOf('{', actualEnd);
55
+ end = this.content.indexOf('{', end);
39
56
  }
40
57
  }
41
58
  else {
42
- actualEnd = this.content.lastIndexOf('}', containerEnd) + 1;
59
+ const lookFor = isExpr ? '}' : '>';
60
+ end = this.content.lastIndexOf(lookFor, containerEnd) + lookFor.length;
43
61
  }
44
- this.correctedExprRanges.set(child, {
45
- start: this.content.indexOf('{', child.position?.start?.offset ?? 0),
46
- end: actualEnd,
47
- });
62
+ this.correctedExprRanges.set(child, { start, end });
48
63
  }
49
64
  };
50
65
  getRange = (node) => {
51
- if (node.type === 'expression') {
52
- return this.correctedExprRanges.get(node) ?? { start: -1, end: -1 };
66
+ const corrected = this.correctedExprRanges.get(node);
67
+ if (corrected) {
68
+ return corrected;
53
69
  }
54
70
  const { start, end } = node.position ?? {};
55
71
  return {
56
- start: start?.offset ?? -1,
57
- end: end?.offset ?? -1,
72
+ start: this._byteOffsetToIndex(start?.offset),
73
+ end: this._byteOffsetToIndex(end?.offset),
58
74
  };
59
75
  };
60
76
  initMixedVisitor = () => new MixedVisitor({
@@ -119,8 +135,14 @@ export class AstroTransformer extends Transformer {
119
135
  return msgs;
120
136
  };
121
137
  visitexpression = (node) => {
138
+ if (!node.children?.length) {
139
+ // can be undefined!
140
+ return [];
141
+ }
122
142
  let expr = '';
123
143
  const msgs = [];
144
+ const { start, end } = this.getRange(node);
145
+ this._saveCorrectedRanges(node.children, end);
124
146
  for (const part of node.children) {
125
147
  if (part.type === 'text') {
126
148
  expr += part.value;
@@ -128,9 +150,10 @@ export class AstroTransformer extends Transformer {
128
150
  }
129
151
  msgs.push(...this.visitAs(part));
130
152
  const { start, end } = this.getRange(part);
153
+ if (end == -1)
154
+ console.log(part, node);
131
155
  expr += `"${' '.repeat(end - start)}"`;
132
156
  }
133
- const { start } = this.getRange(node);
134
157
  msgs.push(...this._parseAndVisitExpr(expr, start + 1));
135
158
  return msgs;
136
159
  };
@@ -150,7 +173,8 @@ export class AstroTransformer extends Transformer {
150
173
  for (const attrib of node.attributes) {
151
174
  msgs.push(...this.visitAs(attrib));
152
175
  }
153
- this._saveCorrectedExprRanges(node.children, node.position?.end?.offset ?? 0);
176
+ const { end } = this.getRange(node);
177
+ this._saveCorrectedRanges(node.children, end);
154
178
  msgs.push(...this._visitChildren(node.children));
155
179
  this.currentElement = currentElement;
156
180
  return msgs;
@@ -208,7 +232,10 @@ export class AstroTransformer extends Transformer {
208
232
  this.frontMatterStart = this.content.indexOf('---', start) + 3;
209
233
  return this._parseAndVisitExpr(node.value, this.frontMatterStart, true);
210
234
  };
211
- visitroot = (node) => this._visitChildren(node.children ?? []); // can be undefined!
235
+ visitroot = (node) => {
236
+ this._saveCorrectedRanges(node.children, this.content.length);
237
+ return this._visitChildren(node.children ?? []); // can be undefined!
238
+ };
212
239
  visitAs = (node) => this.visit(node);
213
240
  transformAs = async () => {
214
241
  const { ast } = await parse(this.content);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuchale/astro",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Wuchale i18n adapter for Astro files",
5
5
  "scripts": {
6
6
  "dev": "tsc --watch",