11const jsxFilePattern = / \. ( t s x | j s x ) ( \? .* ) ? $ / u
22
3+ /**
4+ * Normalizes a module ID by stripping query parameters.
5+ *
6+ * Vite and other bundlers may append query parameters to module IDs
7+ * (e.g., "src/App.tsx?import" or "src/App.tsx?v=123"). This function
8+ * returns the clean file path without query string.
9+ *
10+ * @param id - Module ID (may include query parameters).
11+ * @returns Clean path without query string.
12+ *
13+ * @pure true
14+ * @invariant ∀ id: normalizeModuleId(id) does not contain '?'
15+ * @complexity O(n) time / O(1) space where n = |id|
16+ */
17+ // CHANGE: centralize query stripping as a pure function in core.
18+ // WHY: unify module ID normalization in one place as requested in issue #18.
19+ // QUOTE(ТЗ): "Вынести stripQuery() (или normalizeModuleId()) в core, использовать в Vite и (при желании) в isJsxFile."
20+ // REF: REQ-18 (issue #18)
21+ // SOURCE: n/a
22+ // FORMAT THEOREM: ∀ id: normalizeModuleId(id) = id.split('?')[0]
23+ // PURITY: CORE
24+ // EFFECT: n/a
25+ // INVARIANT: result contains no query string
26+ // COMPLEXITY: O(n)/O(1)
27+ export const normalizeModuleId = ( id : string ) : string => {
28+ const queryIndex = id . indexOf ( "?" )
29+ return queryIndex === - 1 ? id : id . slice ( 0 , queryIndex )
30+ }
31+
332// CHANGE: rename attribute from "path" to "data-path" for HTML5 compliance.
433// WHY: data-* attributes are standard HTML5 custom data attributes, improving compatibility.
534// QUOTE(issue-14): "Rename attribute path → data-path (breaking change)"
@@ -24,7 +53,7 @@ export const componentPathAttributeName = "data-path"
2453 */
2554// CHANGE: centralize JSX file detection as a pure predicate.
2655// WHY: keep file filtering in the functional core for testability.
27- // QUOTE(TZ): "\u0421\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c app \u043d\u043e \u0432\u043e\u0442 \u0447\u0442\u043e \u0431\u044b \u0435\u0433\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0448 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u043f\u043f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c "
56+ // QUOTE(TZ): "Сам компонент должен быть в текущем app но вот что бы его протестировать надо создать ещё один проект который наш текущий апп будет подключать "
2857// REF: user-2026-01-14-frontend-consumer
2958// SOURCE: n/a
3059// FORMAT THEOREM: forall id in ModuleId: isJsxFile(id) -> matches(id, jsxFilePattern)
@@ -48,7 +77,7 @@ export const isJsxFile = (id: string): boolean => jsxFilePattern.test(id)
4877 */
4978// CHANGE: provide a pure formatter for component location payloads.
5079// WHY: reuse a single, deterministic encoding for UI metadata.
51- // QUOTE(TZ): "\u0421\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c app \u043d\u043e \u0432\u043e\u0442 \u0447\u0442\u043e \u0431\u044b \u0435\u0433\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0448 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u043f\u043f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c "
80+ // QUOTE(TZ): "Сам компонент должен быть в текущем app но вот что бы его протестировать надо создать ещё один проект который наш текущий апп будет подключать "
5281// REF: user-2026-01-14-frontend-consumer
5382// SOURCE: n/a
5483// FORMAT THEOREM: forall p,l,c: formatComponentPathValue(p,l,c) = concat(p, ":", l, ":", c)
0 commit comments