@geonosis/oxlint-plugin-biological-architecture 0.2.1 → 0.4.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/corpus/.oxlintrc.json +1 -0
- package/corpus/admin/order-widget.tsx +13 -0
- package/corpus/atoms-discovery/generic-only.tsx +9 -0
- package/corpus/atoms-discovery/html-attributes-select.tsx +15 -0
- package/corpus/atoms-discovery/icon-check.tsx +7 -0
- package/corpus/atoms-discovery/label.tsx +3 -0
- package/corpus/atoms-discovery/props-button.tsx +27 -0
- package/corpus/atoms-discovery/props-without-ref-textarea.tsx +11 -0
- package/corpus/atoms-discovery/react-namespaced-input.tsx +13 -0
- package/corpus/atoms-discovery/slot-anchor.stories.tsx +9 -0
- package/corpus/atoms-discovery/slot-anchor.tsx +15 -0
- package/corpus/emits/bad-no-options.ts +7 -0
- package/corpus/emits/bad-priority-only.ts +11 -0
- package/corpus/emits/bad-single-attempt.ts +8 -0
- package/corpus/emits/good-retry-budget.ts +9 -0
- package/corpus/emits/good-shared-constant.ts +10 -0
- package/corpus/emits/retry.ts +3 -0
- package/corpus/features/invoice/cells/bad-relative-cross-feature-store.tsx +9 -0
- package/corpus/features/invoice/cells/good-relative-own-store.tsx +8 -0
- package/corpus/features/invoice/organelles/bad-relative-cross-feature-organelle.tsx +11 -0
- package/corpus/features/invoice/organelles/good-relative-same-feature-organelle.tsx +11 -0
- package/corpus/manifest.json +1 -0
- package/corpus/molecules/raw-button.tsx +10 -0
- package/dist/{chunk-HXBZSOIU.js → chunk-55NK7NJN.js} +1 -1
- package/dist/discover-atoms.d.ts +12 -0
- package/dist/discover-atoms.js +197 -5
- package/dist/index.js +407 -528
- package/dist/presets.js +1 -1
- package/package.json +2 -2
package/corpus/.oxlintrc.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// A file in no tier folder at all — a Medusa admin widget, a Next route, a one-off surface. The
|
|
2
|
+
// atom exists there too, so no-raw-html-atoms still has something to say.
|
|
3
|
+
import { Card } from '@kit/ui/atoms/card'
|
|
4
|
+
|
|
5
|
+
export function OrderWidget({ onRefresh }: { onRefresh: () => void }) {
|
|
6
|
+
return (
|
|
7
|
+
<Card>
|
|
8
|
+
<button onClick={onRefresh} type="button">
|
|
9
|
+
Refresh
|
|
10
|
+
</button>
|
|
11
|
+
</Card>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
|
|
3
|
+
const weights: Record<string, number> = { bold: 700, regular: 400 }
|
|
4
|
+
|
|
5
|
+
export function Spacer({ weight = 'regular' }: { weight?: string }) {
|
|
6
|
+
const value = useMemo<number>(() => weights[weight] ?? 400, [weight])
|
|
7
|
+
|
|
8
|
+
return <div style={{ fontWeight: value }} />
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react'
|
|
2
|
+
|
|
3
|
+
interface NativeSelectProps extends Omit<HTMLAttributes<HTMLSelectElement>, 'onChange'> {
|
|
4
|
+
onPick?: (value: string) => void
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function NativeSelect({ onPick, children, ...props }: NativeSelectProps) {
|
|
8
|
+
return (
|
|
9
|
+
<div className="relative">
|
|
10
|
+
<select onChange={(event) => onPick?.(event.target.value)} {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</select>
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
2
|
+
import { Slot } from 'radix-ui'
|
|
3
|
+
import type { ComponentProps, Ref } from 'react'
|
|
4
|
+
|
|
5
|
+
const buttonVariants = cva('inline-flex', {
|
|
6
|
+
variants: { size: { medium: 'px-7', small: 'px-5' } },
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
type ButtonSize = NonNullable<VariantProps<typeof buttonVariants>['size']>
|
|
10
|
+
|
|
11
|
+
const labels: Record<string, string> = { medium: 'Medium', small: 'Small' }
|
|
12
|
+
|
|
13
|
+
interface ButtonProps extends ComponentProps<'button'>, VariantProps<typeof buttonVariants> {
|
|
14
|
+
asChild?: boolean
|
|
15
|
+
ref?: Ref<HTMLButtonElement>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Button({ asChild = false, size, children, ...props }: ButtonProps) {
|
|
19
|
+
const Comp = asChild ? Slot.Root : 'button'
|
|
20
|
+
const resolved: ButtonSize = size ?? 'medium'
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Comp aria-label={labels[resolved]} {...props}>
|
|
24
|
+
{children}
|
|
25
|
+
</Comp>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from 'react'
|
|
2
|
+
|
|
3
|
+
type TextAreaProps = ComponentPropsWithoutRef<'textarea'> & { invalid?: boolean }
|
|
4
|
+
|
|
5
|
+
export function TextArea({ invalid = false, ...props }: TextAreaProps) {
|
|
6
|
+
return (
|
|
7
|
+
<div className="relative">
|
|
8
|
+
<textarea data-invalid={invalid} {...props} />
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
4
|
+
invalid?: boolean
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function TextInput({ invalid = false, ...props }: TextInputProps) {
|
|
8
|
+
return (
|
|
9
|
+
<div className="relative">
|
|
10
|
+
<input data-invalid={invalid} {...props} />
|
|
11
|
+
</div>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Slot } from 'radix-ui'
|
|
2
|
+
|
|
3
|
+
import { cn } from '#lib/utils'
|
|
4
|
+
|
|
5
|
+
interface LinkAtomProps {
|
|
6
|
+
asChild?: boolean
|
|
7
|
+
children?: unknown
|
|
8
|
+
className?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function LinkAtom({ asChild = false, children, className }: LinkAtomProps) {
|
|
12
|
+
const Comp = asChild ? Slot.Root : 'a'
|
|
13
|
+
|
|
14
|
+
return <Comp className={cn('underline', className)}>{children}</Comp>
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EventPriority } from '@medusajs/framework/utils'
|
|
2
|
+
import { emitEventStep } from '@medusajs/medusa/core-flows'
|
|
3
|
+
|
|
4
|
+
// An options bag that names a priority and no attempts: configured to the eye, droppable to the
|
|
5
|
+
// worker, which reads only `attempts > 1` as "a retry was asked for".
|
|
6
|
+
export const emitSampleRequested = (data: { order_id: string }) =>
|
|
7
|
+
emitEventStep({
|
|
8
|
+
data,
|
|
9
|
+
eventName: 'sample.requested',
|
|
10
|
+
options: { priority: EventPriority.CRITICAL },
|
|
11
|
+
}).config({ name: 'emit-sample-requested' })
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EventPriority } from '@medusajs/framework/utils'
|
|
2
|
+
import { emitEventStep } from '@medusajs/medusa/core-flows'
|
|
3
|
+
|
|
4
|
+
export const emitOrderPlaced = (data: { id: string }) =>
|
|
5
|
+
emitEventStep({
|
|
6
|
+
data,
|
|
7
|
+
eventName: 'order.placed',
|
|
8
|
+
options: { attempts: 3, priority: EventPriority.CRITICAL },
|
|
9
|
+
}).config({ name: 'emit-order-placed' })
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { emitEventStep } from '@medusajs/medusa/core-flows'
|
|
2
|
+
|
|
3
|
+
import { RETRY_BACKGROUND } from './retry'
|
|
4
|
+
|
|
5
|
+
export const emitProofReady = (data: { proof_id: string }) =>
|
|
6
|
+
emitEventStep({
|
|
7
|
+
data,
|
|
8
|
+
eventName: 'proof.ready',
|
|
9
|
+
options: { attempts: RETRY_BACKGROUND.attempts },
|
|
10
|
+
})
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The same breach as bad-cross-feature-store.tsx, written the way a file two directories away
|
|
2
|
+
// writes it. The source names no feature until it is resolved against THIS file — which is exactly
|
|
3
|
+
// what no-cross-feature-stores used to be blind to.
|
|
4
|
+
import { useBillingStore } from '../../billing/stores/billing-store'
|
|
5
|
+
|
|
6
|
+
export function BadRelativeCrossFeatureStore() {
|
|
7
|
+
const total = useBillingStore((state) => state.total)
|
|
8
|
+
return <span>{total}</span>
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// A relative import of this feature's OWN store — allowed, and it must stay allowed once relative
|
|
2
|
+
// sources are resolved.
|
|
3
|
+
import { useInvoiceStore } from '../stores/invoice-store'
|
|
4
|
+
|
|
5
|
+
export function GoodRelativeOwnStore() {
|
|
6
|
+
const total = useInvoiceStore((state) => state.total)
|
|
7
|
+
return <span>{total}</span>
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// A relative climb out of this feature into ANOTHER feature's organelle. organelle-dependency must
|
|
2
|
+
// fire: where the import LANDS is the fact, not how it was spelled.
|
|
3
|
+
import { BillingTotals } from '../../billing/organelles/billing-totals'
|
|
4
|
+
|
|
5
|
+
export function BadRelativeCrossFeatureOrganelle() {
|
|
6
|
+
return (
|
|
7
|
+
<section>
|
|
8
|
+
<BillingTotals />
|
|
9
|
+
</section>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// A sub-organelle in the SAME feature — the nucleolus in the nucleus. Allowed, and it must stay
|
|
2
|
+
// allowed once relative sources are resolved.
|
|
3
|
+
import { InvoiceLines } from './invoice-lines'
|
|
4
|
+
|
|
5
|
+
export function GoodRelativeSameFeatureOrganelle() {
|
|
6
|
+
return (
|
|
7
|
+
<section>
|
|
8
|
+
<InvoiceLines />
|
|
9
|
+
</section>
|
|
10
|
+
)
|
|
11
|
+
}
|
package/corpus/manifest.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"biological-architecture/document-sagas-are-generic",
|
|
14
14
|
"biological-architecture/documents-share-one-table",
|
|
15
15
|
"biological-architecture/effect-hook-naming",
|
|
16
|
+
"biological-architecture/emit-declares-attempts",
|
|
16
17
|
"biological-architecture/layer-walls",
|
|
17
18
|
"biological-architecture/max-comment-density",
|
|
18
19
|
"biological-architecture/molecule-atoms-only",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// A molecule hand-rolling the element an atom already wraps: level 2, where the rule bites.
|
|
2
|
+
import { Icon } from '../atoms/icon'
|
|
3
|
+
|
|
4
|
+
export function IconAction({ onPress }: { onPress: () => void }) {
|
|
5
|
+
return (
|
|
6
|
+
<button onClick={onPress} type="button">
|
|
7
|
+
<Icon name="plus" />
|
|
8
|
+
</button>
|
|
9
|
+
)
|
|
10
|
+
}
|
|
@@ -52,7 +52,7 @@ var BACKEND_WORKFLOWS = [
|
|
|
52
52
|
];
|
|
53
53
|
var BACKEND_D1 = ["no-d1-transaction", "worker-handles-are-scoped"];
|
|
54
54
|
var BACKEND_SAGAFLOW_CF = ["step-opens-its-own-cell"];
|
|
55
|
-
var BACKEND_MEDUSA = ["store-route-scopes-tenant-data"];
|
|
55
|
+
var BACKEND_MEDUSA = ["emit-declares-attempts", "store-route-scopes-tenant-data"];
|
|
56
56
|
var TENANT_SCOPING = [
|
|
57
57
|
"queries-require-org-scope",
|
|
58
58
|
"store-route-scopes-tenant-data",
|
package/dist/discover-atoms.d.ts
CHANGED
|
@@ -34,6 +34,18 @@ declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?:
|
|
|
34
34
|
* Variants are kept as alternatives in the error message.
|
|
35
35
|
*/
|
|
36
36
|
declare function scanAtomMappings(atomsDir: string): AtomMapping[];
|
|
37
|
+
/**
|
|
38
|
+
* The native element an atom wraps, read from the one place every atom says so: its props type.
|
|
39
|
+
*
|
|
40
|
+
* `ComponentProps<'button'>`, `ComponentPropsWithoutRef<'textarea'>`,
|
|
41
|
+
* `HTMLAttributes<HTMLSelectElement>` and `React.ButtonHTMLAttributes<HTMLButtonElement>` all name
|
|
42
|
+
* the element outright, and an atom that types its props any other way is an atom nobody can
|
|
43
|
+
* compose. The Radix `asChild ? Slot.Root : 'button'` form comes next, and the JSX-tag scan is
|
|
44
|
+
* only the fallback — it was the whole detector once, and on a real tree it returned `string`,
|
|
45
|
+
* `typeof` and `path` while missing every shadcn button in the repo.
|
|
46
|
+
*
|
|
47
|
+
* The name is kept because consumers import it.
|
|
48
|
+
*/
|
|
37
49
|
declare function detectFirstNativeJsxElement(source: string): null | string;
|
|
38
50
|
|
|
39
51
|
export { buildAtomRestrictions, buildAtomRuleRestrictions, detectFirstNativeJsxElement, scanAtomMappings };
|
package/dist/discover-atoms.js
CHANGED
|
@@ -2,6 +2,164 @@
|
|
|
2
2
|
import { readdirSync, readFileSync } from "fs";
|
|
3
3
|
import { basename, join } from "path";
|
|
4
4
|
var GENERIC_ELEMENTS = /* @__PURE__ */ new Set(["div", "span"]);
|
|
5
|
+
var HTML_ELEMENTS = /* @__PURE__ */ new Set([
|
|
6
|
+
"a",
|
|
7
|
+
"abbr",
|
|
8
|
+
"address",
|
|
9
|
+
"area",
|
|
10
|
+
"article",
|
|
11
|
+
"aside",
|
|
12
|
+
"audio",
|
|
13
|
+
"b",
|
|
14
|
+
"bdi",
|
|
15
|
+
"bdo",
|
|
16
|
+
"blockquote",
|
|
17
|
+
"br",
|
|
18
|
+
"button",
|
|
19
|
+
"canvas",
|
|
20
|
+
"caption",
|
|
21
|
+
"cite",
|
|
22
|
+
"code",
|
|
23
|
+
"col",
|
|
24
|
+
"colgroup",
|
|
25
|
+
"data",
|
|
26
|
+
"datalist",
|
|
27
|
+
"dd",
|
|
28
|
+
"del",
|
|
29
|
+
"details",
|
|
30
|
+
"dfn",
|
|
31
|
+
"dialog",
|
|
32
|
+
"div",
|
|
33
|
+
"dl",
|
|
34
|
+
"dt",
|
|
35
|
+
"em",
|
|
36
|
+
"embed",
|
|
37
|
+
"fieldset",
|
|
38
|
+
"figcaption",
|
|
39
|
+
"figure",
|
|
40
|
+
"footer",
|
|
41
|
+
"form",
|
|
42
|
+
"h1",
|
|
43
|
+
"h2",
|
|
44
|
+
"h3",
|
|
45
|
+
"h4",
|
|
46
|
+
"h5",
|
|
47
|
+
"h6",
|
|
48
|
+
"header",
|
|
49
|
+
"hgroup",
|
|
50
|
+
"hr",
|
|
51
|
+
"i",
|
|
52
|
+
"iframe",
|
|
53
|
+
"img",
|
|
54
|
+
"input",
|
|
55
|
+
"ins",
|
|
56
|
+
"kbd",
|
|
57
|
+
"label",
|
|
58
|
+
"legend",
|
|
59
|
+
"li",
|
|
60
|
+
"main",
|
|
61
|
+
"map",
|
|
62
|
+
"mark",
|
|
63
|
+
"menu",
|
|
64
|
+
"meter",
|
|
65
|
+
"nav",
|
|
66
|
+
"noscript",
|
|
67
|
+
"object",
|
|
68
|
+
"ol",
|
|
69
|
+
"optgroup",
|
|
70
|
+
"option",
|
|
71
|
+
"output",
|
|
72
|
+
"p",
|
|
73
|
+
"picture",
|
|
74
|
+
"pre",
|
|
75
|
+
"progress",
|
|
76
|
+
"q",
|
|
77
|
+
"rp",
|
|
78
|
+
"rt",
|
|
79
|
+
"ruby",
|
|
80
|
+
"s",
|
|
81
|
+
"samp",
|
|
82
|
+
"search",
|
|
83
|
+
"section",
|
|
84
|
+
"select",
|
|
85
|
+
"small",
|
|
86
|
+
"source",
|
|
87
|
+
"span",
|
|
88
|
+
"strong",
|
|
89
|
+
"sub",
|
|
90
|
+
"summary",
|
|
91
|
+
"sup",
|
|
92
|
+
"table",
|
|
93
|
+
"tbody",
|
|
94
|
+
"td",
|
|
95
|
+
"template",
|
|
96
|
+
"textarea",
|
|
97
|
+
"tfoot",
|
|
98
|
+
"th",
|
|
99
|
+
"thead",
|
|
100
|
+
"time",
|
|
101
|
+
"tr",
|
|
102
|
+
"track",
|
|
103
|
+
"u",
|
|
104
|
+
"ul",
|
|
105
|
+
"var",
|
|
106
|
+
"video",
|
|
107
|
+
"wbr"
|
|
108
|
+
]);
|
|
109
|
+
var TAG_OF_DOM_INTERFACE = {
|
|
110
|
+
HTMLAnchorElement: "a",
|
|
111
|
+
HTMLAreaElement: "area",
|
|
112
|
+
HTMLAudioElement: "audio",
|
|
113
|
+
HTMLBRElement: "br",
|
|
114
|
+
HTMLButtonElement: "button",
|
|
115
|
+
HTMLCanvasElement: "canvas",
|
|
116
|
+
HTMLDListElement: "dl",
|
|
117
|
+
HTMLDataElement: "data",
|
|
118
|
+
HTMLDataListElement: "datalist",
|
|
119
|
+
HTMLDetailsElement: "details",
|
|
120
|
+
HTMLDialogElement: "dialog",
|
|
121
|
+
HTMLDivElement: "div",
|
|
122
|
+
HTMLEmbedElement: "embed",
|
|
123
|
+
HTMLFieldSetElement: "fieldset",
|
|
124
|
+
HTMLFormElement: "form",
|
|
125
|
+
HTMLHRElement: "hr",
|
|
126
|
+
HTMLIFrameElement: "iframe",
|
|
127
|
+
HTMLImageElement: "img",
|
|
128
|
+
HTMLInputElement: "input",
|
|
129
|
+
HTMLLIElement: "li",
|
|
130
|
+
HTMLLabelElement: "label",
|
|
131
|
+
HTMLLegendElement: "legend",
|
|
132
|
+
HTMLMapElement: "map",
|
|
133
|
+
HTMLMenuElement: "menu",
|
|
134
|
+
HTMLMeterElement: "meter",
|
|
135
|
+
HTMLOListElement: "ol",
|
|
136
|
+
HTMLObjectElement: "object",
|
|
137
|
+
HTMLOptGroupElement: "optgroup",
|
|
138
|
+
HTMLOptionElement: "option",
|
|
139
|
+
HTMLOutputElement: "output",
|
|
140
|
+
HTMLParagraphElement: "p",
|
|
141
|
+
HTMLPictureElement: "picture",
|
|
142
|
+
HTMLPreElement: "pre",
|
|
143
|
+
HTMLProgressElement: "progress",
|
|
144
|
+
HTMLSelectElement: "select",
|
|
145
|
+
HTMLSourceElement: "source",
|
|
146
|
+
HTMLSpanElement: "span",
|
|
147
|
+
HTMLTableCaptionElement: "caption",
|
|
148
|
+
HTMLTableColElement: "col",
|
|
149
|
+
HTMLTableElement: "table",
|
|
150
|
+
HTMLTableRowElement: "tr",
|
|
151
|
+
HTMLTextAreaElement: "textarea",
|
|
152
|
+
HTMLTimeElement: "time",
|
|
153
|
+
HTMLTrackElement: "track",
|
|
154
|
+
HTMLUListElement: "ul",
|
|
155
|
+
HTMLVideoElement: "video"
|
|
156
|
+
};
|
|
157
|
+
var TAG_OF_ATTRIBUTES_PREFIX = { anchor: "a" };
|
|
158
|
+
var NOT_AN_ATOM = /\.(?:stories|test|spec)\.tsx$/;
|
|
159
|
+
var COMPONENT_PROPS = /(?:React\.)?ComponentProps(?:WithoutRef|WithRef)?\s*<\s*['"]([a-z][a-z0-9]*)['"]\s*>/g;
|
|
160
|
+
var HTML_ATTRIBUTES = /(?:React\.)?([A-Z][A-Za-z]*?)?HTMLAttributes\s*<\s*(HTML[A-Za-z]*Element)\s*>/g;
|
|
161
|
+
var SLOT_FALLBACK = /Slot(?:\.Root)?\s*:\s*['"]([a-z][a-z0-9]*)['"]/;
|
|
162
|
+
var JSX_TAG = /(?<![A-Za-z0-9_$])<([a-z][a-z0-9]*)(?=[\s/>])/g;
|
|
5
163
|
function buildAtomRestrictions(atomsDir, importPathPrefix = "@kit/ui/atoms") {
|
|
6
164
|
const mappings = scanAtomMappings(atomsDir);
|
|
7
165
|
return mappings.map(({ atomName, nativeElement }) => ({
|
|
@@ -23,6 +181,7 @@ function scanAtomMappings(atomsDir) {
|
|
|
23
181
|
for (const entry of entries) {
|
|
24
182
|
if (!entry.isFile()) continue;
|
|
25
183
|
if (!entry.name.endsWith(".tsx")) continue;
|
|
184
|
+
if (NOT_AN_ATOM.test(entry.name)) continue;
|
|
26
185
|
const atomFile = entry.name;
|
|
27
186
|
const atomName = basename(atomFile, ".tsx");
|
|
28
187
|
const content = readFileSync(join(atomsDir, atomFile), "utf8");
|
|
@@ -42,11 +201,44 @@ function scanAtomMappings(atomsDir) {
|
|
|
42
201
|
return mappings;
|
|
43
202
|
}
|
|
44
203
|
function detectFirstNativeJsxElement(source) {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
204
|
+
const withoutComments = stripComments(source);
|
|
205
|
+
const declared = elementFromPropsType(withoutComments);
|
|
206
|
+
if (declared) return declared;
|
|
207
|
+
const slot = SLOT_FALLBACK.exec(withoutComments)?.[1];
|
|
208
|
+
if (slot && HTML_ELEMENTS.has(slot)) return slot;
|
|
209
|
+
return elementFromJsx(withoutComments);
|
|
210
|
+
}
|
|
211
|
+
function elementFromPropsType(source) {
|
|
212
|
+
const found = [];
|
|
213
|
+
for (const match of source.matchAll(COMPONENT_PROPS)) {
|
|
214
|
+
const element = match[1];
|
|
215
|
+
if (element && HTML_ELEMENTS.has(element)) found.push({ at: match.index, element });
|
|
216
|
+
}
|
|
217
|
+
for (const match of source.matchAll(HTML_ATTRIBUTES)) {
|
|
218
|
+
const element = elementOfAttributes(match[1], match[2]);
|
|
219
|
+
if (element) found.push({ at: match.index, element });
|
|
220
|
+
}
|
|
221
|
+
return found.toSorted((a, b) => a.at - b.at)[0]?.element ?? null;
|
|
222
|
+
}
|
|
223
|
+
function elementOfAttributes(prefix, domInterface) {
|
|
224
|
+
if (prefix !== void 0) {
|
|
225
|
+
const lower = prefix.toLowerCase();
|
|
226
|
+
const named = TAG_OF_ATTRIBUTES_PREFIX[lower] ?? lower;
|
|
227
|
+
if (HTML_ELEMENTS.has(named)) return named;
|
|
228
|
+
}
|
|
229
|
+
const mapped = domInterface === void 0 ? void 0 : TAG_OF_DOM_INTERFACE[domInterface];
|
|
230
|
+
return mapped !== void 0 && HTML_ELEMENTS.has(mapped) ? mapped : null;
|
|
231
|
+
}
|
|
232
|
+
function elementFromJsx(withoutComments) {
|
|
233
|
+
const cleaned = withoutComments.replaceAll(/(["'`])(?:\\.|(?!\1)[^\\])*\1/g, '""');
|
|
234
|
+
for (const match of cleaned.matchAll(JSX_TAG)) {
|
|
235
|
+
const tag = match[1];
|
|
236
|
+
if (tag && HTML_ELEMENTS.has(tag)) return tag;
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
function stripComments(source) {
|
|
241
|
+
return source.replaceAll(/\/\*[\s\S]*?\*\//g, "").replaceAll(/(?<!:)\/\/.*$/gm, "");
|
|
50
242
|
}
|
|
51
243
|
function toPascalCase(kebab) {
|
|
52
244
|
return kebab.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|