@nuasite/cms 0.38.0 → 0.39.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.
- package/dist/editor.js +11483 -11444
- package/package.json +1 -1
- package/src/dev-middleware.ts +51 -6
- package/src/editor/components/markdown-editor-overlay.tsx +2 -0
- package/src/editor/constants.ts +2 -0
- package/src/editor/editor.ts +24 -7
- package/src/editor/index.tsx +11 -6
- package/src/editor/markdown-api.ts +9 -0
- package/src/editor/signals.ts +113 -7
- package/src/editor/storage.ts +172 -196
- package/src/editor/types.ts +2 -0
- package/src/handlers/api-routes.ts +27 -14
- package/src/handlers/request-utils.ts +10 -1
- package/src/index.ts +21 -10
- package/src/source-finder/search-index.ts +48 -5
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ComponentNode, ElementNode, Node as AstroNode, TextNode } from '@astrojs/compiler/types'
|
|
2
|
+
import { parse as parseBabel } from '@babel/parser'
|
|
3
|
+
import type { Expression } from '@babel/types'
|
|
2
4
|
import fs from 'node:fs/promises'
|
|
3
5
|
import path from 'node:path'
|
|
4
6
|
|
|
@@ -622,6 +624,42 @@ function parseMapInvocations(fullText: string): MapInvocation[] {
|
|
|
622
624
|
return maps
|
|
623
625
|
}
|
|
624
626
|
|
|
627
|
+
const BARE_IDENTIFIER = /^[A-Za-z_$][\w$]*$/
|
|
628
|
+
|
|
629
|
+
function walkAccessor(node: Expression): { base: string; suffix: string } | null {
|
|
630
|
+
if (node.type === 'Identifier') {
|
|
631
|
+
return { base: node.name, suffix: '' }
|
|
632
|
+
}
|
|
633
|
+
if (node.type === 'MemberExpression' || node.type === 'OptionalMemberExpression') {
|
|
634
|
+
if (node.object.type === 'Super') return null
|
|
635
|
+
const inner = walkAccessor(node.object)
|
|
636
|
+
if (!inner) return null
|
|
637
|
+
const { property, computed } = node
|
|
638
|
+
let part: string
|
|
639
|
+
if (!computed && property.type === 'Identifier') {
|
|
640
|
+
part = `.${property.name}`
|
|
641
|
+
} else if (computed && property.type === 'NumericLiteral') {
|
|
642
|
+
part = `[${property.value}]`
|
|
643
|
+
} else {
|
|
644
|
+
return null
|
|
645
|
+
}
|
|
646
|
+
return { base: inner.base, suffix: inner.suffix + part }
|
|
647
|
+
}
|
|
648
|
+
return null
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function parseAccessorChain(exprText: string): { base: string; suffix: string } | null {
|
|
652
|
+
if (BARE_IDENTIFIER.test(exprText)) return { base: exprText, suffix: '' }
|
|
653
|
+
try {
|
|
654
|
+
const file = parseBabel(exprText, { sourceType: 'module', plugins: ['typescript'] })
|
|
655
|
+
const stmt = file.program.body[0]
|
|
656
|
+
if (!stmt || stmt.type !== 'ExpressionStatement') return null
|
|
657
|
+
return walkAccessor(stmt.expression)
|
|
658
|
+
} catch {
|
|
659
|
+
return null
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
625
663
|
/**
|
|
626
664
|
* Resolve a `.map()` callback parameter back to the source array path.
|
|
627
665
|
*
|
|
@@ -632,6 +670,8 @@ function parseMapInvocations(fullText: string): MapInvocation[] {
|
|
|
632
670
|
* → `{ arrayPath: "categories[*].images", leafSuffix: "" }`
|
|
633
671
|
* `links.map(({ label, href }) => …)` looking for `label`
|
|
634
672
|
* → `{ arrayPath: "links", leafSuffix: ".label" }`
|
|
673
|
+
* `services.map((service) => …)` looking for `service.image`
|
|
674
|
+
* → `{ arrayPath: "services", leafSuffix: ".image" }`
|
|
635
675
|
*
|
|
636
676
|
* Returns null when the name doesn't appear as a parameter or destructured binding.
|
|
637
677
|
*/
|
|
@@ -639,13 +679,16 @@ export function resolveMapChain(exprTexts: string[], paramName: string): Resolve
|
|
|
639
679
|
const maps = parseMapInvocations(exprTexts.join(''))
|
|
640
680
|
if (maps.length === 0) return null
|
|
641
681
|
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
|
|
682
|
+
const access = parseAccessorChain(paramName)
|
|
683
|
+
const baseName = access?.base ?? paramName
|
|
684
|
+
const memberSuffix = access?.suffix ?? ''
|
|
685
|
+
|
|
686
|
+
const directMap = maps.find((m) => m.param === baseName)
|
|
687
|
+
?? maps.find((m) => m.destructured.includes(baseName))
|
|
645
688
|
if (!directMap) return null
|
|
646
689
|
|
|
647
|
-
const isDestructured = directMap.param !==
|
|
648
|
-
const leafSuffix = isDestructured ? `.${
|
|
690
|
+
const isDestructured = directMap.param !== baseName
|
|
691
|
+
const leafSuffix = (isDestructured ? `.${baseName}` : '') + memberSuffix
|
|
649
692
|
|
|
650
693
|
// Resolve the array expression by substituting outer .map() params (chained / nested loops).
|
|
651
694
|
let arrayPath = directMap.arrayExpr
|