@invisibleloop/pulse 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invisibleloop/pulse",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "AI-first frontend framework. The spec is the source of truth.",
6
6
  "license": "MIT",
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
package/scripts/build.js CHANGED
@@ -51,11 +51,48 @@ function stripServerOnlyKeys(source) {
51
51
  * from a JS source string. Uses a character-level scanner to correctly handle
52
52
  * nested structures, string literals, template literals, and function expressions.
53
53
  */
54
+ /**
55
+ * Returns true if `pos` in `source` falls inside a string or template literal.
56
+ * Used to avoid stripping keys that appear inside code-example strings in docs pages.
57
+ */
58
+ function isInsideString(source, pos) {
59
+ let i = 0
60
+ const stack = [] // stack of open delimiters: '"' | "'" | '`' | '{' ('{' = template expression)
61
+ while (i < pos) {
62
+ const c = source[i]
63
+ const top = stack[stack.length - 1]
64
+ if (top === '"' || top === "'") {
65
+ if (c === '\\') { i += 2; continue }
66
+ if (c === top) { stack.pop() }
67
+ i++; continue
68
+ }
69
+ if (top === '`') {
70
+ if (c === '\\') { i += 2; continue }
71
+ if (c === '`') { stack.pop(); i++; continue }
72
+ if (c === '$' && source[i + 1] === '{') { stack.push('{'); i += 2; continue }
73
+ i++; continue
74
+ }
75
+ if (top === '{') {
76
+ // inside a template expression — track nested braces
77
+ if (c === '{') { stack.push('{'); i++; continue }
78
+ if (c === '}') { stack.pop(); i++; continue }
79
+ if (c === '"' || c === "'" || c === '`') { stack.push(c); i++; continue }
80
+ i++; continue
81
+ }
82
+ // top-level
83
+ if (c === '"' || c === "'" || c === '`') { stack.push(c) }
84
+ i++
85
+ }
86
+ return stack.length > 0
87
+ }
88
+
54
89
  function removeObjectKey(source, key) {
55
90
  const keyRe = new RegExp(`^([ \\t]*)(${key})([ \\t]*:)`, 'gm')
56
91
  let match
57
92
 
58
93
  while ((match = keyRe.exec(source)) !== null) {
94
+ if (isInsideString(source, match.index)) { continue }
95
+
59
96
  const removeStart = match.index // start of indentation
60
97
  const afterColon = match.index + match[0].length // character after ':'
61
98
 
@@ -14,10 +14,40 @@ function stripServerOnlyKeys(source) {
14
14
  return source
15
15
  }
16
16
 
17
+ function isInsideString(source, pos) {
18
+ let i = 0
19
+ const stack = []
20
+ while (i < pos) {
21
+ const c = source[i]
22
+ const top = stack[stack.length - 1]
23
+ if (top === '"' || top === "'") {
24
+ if (c === '\\') { i += 2; continue }
25
+ if (c === top) { stack.pop() }
26
+ i++; continue
27
+ }
28
+ if (top === '`') {
29
+ if (c === '\\') { i += 2; continue }
30
+ if (c === '`') { stack.pop(); i++; continue }
31
+ if (c === '$' && source[i + 1] === '{') { stack.push('{'); i += 2; continue }
32
+ i++; continue
33
+ }
34
+ if (top === '{') {
35
+ if (c === '{') { stack.push('{'); i++; continue }
36
+ if (c === '}') { stack.pop(); i++; continue }
37
+ if (c === '"' || c === "'" || c === '`') { stack.push(c); i++; continue }
38
+ i++; continue
39
+ }
40
+ if (c === '"' || c === "'" || c === '`') { stack.push(c) }
41
+ i++
42
+ }
43
+ return stack.length > 0
44
+ }
45
+
17
46
  function removeObjectKey(source, key) {
18
47
  const keyRe = new RegExp(`^([ \\t]*)(${key})([ \\t]*:)`, 'gm')
19
48
  let match
20
49
  while ((match = keyRe.exec(source)) !== null) {
50
+ if (isInsideString(source, match.index)) { continue }
21
51
  const removeStart = match.index
22
52
  const afterColon = match.index + match[0].length
23
53
  let pos = afterColon
@@ -181,6 +211,16 @@ test('server with deeply nested template literal in view is not affected',
181
211
  'export default {\n view: (s, srv) => `<ul>${srv.items.map(i => `<li>${i}</li>`).join(\'\')}</ul>`\n}'
182
212
  )
183
213
 
214
+ test('render: inside a template literal string (docs code example) is not stripped',
215
+ 'export default {\n route: \'/auth\',\n view: () => `${highlight(`export default {\n render: (ctx) => ctx.user\n}`)}`\n}',
216
+ 'export default {\n route: \'/auth\',\n view: () => `${highlight(`export default {\n render: (ctx) => ctx.user\n}`)}`\n}'
217
+ )
218
+
219
+ test('server: inside a double-quoted string is not stripped',
220
+ 'export default {\n route: \'/docs\',\n view: () => "<pre>server: { data: async () => {} }</pre>"\n}',
221
+ 'export default {\n route: \'/docs\',\n view: () => "<pre>server: { data: async () => {} }</pre>"\n}'
222
+ )
223
+
184
224
  // ---------------------------------------------------------------------------
185
225
 
186
226
  console.log(`\n${pass + fail} tests: ${pass} passed, ${fail} failed\n`)