@symbiote-native/vue 0.3.8 → 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.
@@ -1,37 +1,33 @@
1
- // Metro babel transformer that teaches the bundler to read Vue SFCs (.vue). Metro has no
2
- // Vue plugin (unplugin-vue ships vite/webpack/esbuild/rollup adapters, not Metro), so we do
3
- // the single-pass compile here: parse the SFC, compile <script setup> + <template> into one
4
- // component module, then hand the JS to RN's own babel transformer. This is the Metro twin
5
- // of what @vitejs/plugin-vue does for Vite; the 'vue'→runtime-core rewrite is needed because
6
- // a custom, non-DOM renderer needs the compiler helpers from @vue/runtime-core, not from
7
- // vue/runtime-dom.
1
+ // Metro babel transformer that teaches the bundler to read Vue SFCs (.vue). Metro has no Vue
2
+ // plugin (unplugin-vue only ships vite/webpack/esbuild/rollup adapters), so we do the
3
+ // single-pass compile here: parse the SFC, compile <script setup> + <template> into one
4
+ // component module, then hand the JS to RN's own babel transformer - the Metro twin of
5
+ // @vitejs/plugin-vue. Imports get retargeted from 'vue' to @symbiote-native/vue/runtime-helpers
6
+ // (not bare @vue/runtime-core) because that shim also supplies our own `vShow` - compiled
7
+ // v-show imports it by name, and only @vue/runtime-dom's DOM-based version exists otherwise.
8
8
  //
9
- // Retargeted at @symbiote-native/vue/runtime-helpers rather than bare @vue/runtime-core: that shim
10
- // re-exports runtime-core verbatim PLUS supplies our own `vShow` (compiled v-show imports it by
11
- // name, and only @vue/runtime-dom's DOM-based version exists otherwise).
12
- //
13
- // Ships as a package-level export (`@symbiote-native/vue/metro-vue-transformer`) rather than living
14
- // in each consuming app: a consumer's own metro.config.js just points babelTransformerPath at it.
9
+ // Ships as a package-level export (`@symbiote-native/vue/metro-vue-transformer`) rather than
10
+ // living in each consuming app: a consumer's own metro.config.js just points
11
+ // babelTransformerPath at it.
15
12
 
16
13
  const nodeFs = require('fs');
17
14
  const { parse, compileScript, registerTS } = require('@vue/compiler-sfc');
18
15
  const { createCompoundExpression } = require('@vue/compiler-core');
19
16
 
20
- // A bare-specifier type import (`import type { X } from '@symbiote-native/navigation/vue'`, as
21
- // opposed to a relative one) needs real node_modules resolution (package.json exports, pnpm
22
- // symlinks) to turn the specifier into a file path — compileScript's own `fs` option only reads
23
- // paths it's already given, it can't do that resolution. @vue/compiler-sfc's sanctioned hook for
24
- // this is `registerTS`, the same one @vitejs/plugin-vue and vue-tsc call: it hands the compiler a
25
- // lazy loader for the real `typescript` package, which resolves the specifier via
26
- // `ts.resolveModuleName` and self-supplies `ts.sys` as the fs fallback.
17
+ // A bare-specifier type import (`import type { X } from '@symbiote-native/navigation/vue'`) needs
18
+ // real node_modules resolution to turn the specifier into a file path - compileScript's own `fs`
19
+ // option only reads paths it's already given, it can't resolve. registerTS (the same hook
20
+ // @vitejs/plugin-vue and vue-tsc use) hands the compiler a lazy `typescript` loader that resolves
21
+ // via `ts.resolveModuleName` and self-supplies `ts.sys` as the fs fallback.
27
22
  registerTS(() => require('typescript'));
28
- // @symbiote-native/css-parser is a real dependency of THIS package, so requiring it directly here
29
- // (rather than through the ./metro-css-parser public subpath, which exists for CONSUMERS) resolves
30
- // straight from this package's own node_modules under pnpm.
23
+ // Required directly (not via the ./metro-css-parser public subpath, which exists for CONSUMERS)
24
+ // so it resolves from this package's own node_modules under pnpm.
31
25
  const {
26
+ classTokensIn,
32
27
  compile: compilePreprocessor,
33
28
  compileCssFile,
34
29
  globalClassNamesIn,
30
+ globalClassTokensIn,
35
31
  hashFilePath,
36
32
  isStyleFile,
37
33
  kebabToCamel,
@@ -42,14 +38,13 @@ const {
42
38
  const upstreamTransformer = resolveUpstreamTransformer();
43
39
 
44
40
  // compileScript needs file system access to resolve a type-only `defineProps<ISomeProps>()`
45
- // where ISomeProps is imported from another file — without it, Metro's worker process (a real
46
- // Node process, but one @vue/compiler-sfc doesn't auto-detect as Node unless the consumer calls
47
- // its `registerTS` hook) throws "No fs option provided ... in non-Node environment". Wiring
48
- // Node's own `fs` module straight through is simpler than registering the `typescript` package
49
- // as a loader (registerTS), and this file already runs in Node at Metro build time.
41
+ // imported from another file - without it, Metro's worker process (a real Node process, but one
42
+ // @vue/compiler-sfc doesn't auto-detect without registerTS) throws "No fs option provided ...
43
+ // in non-Node environment". Wiring Node's own `fs` straight through is simpler than a second
44
+ // registerTS-style loader.
50
45
  const compileScriptFs = {
51
- fileExists: (file) => nodeFs.existsSync(file),
52
- readFile: (file) => {
46
+ fileExists: file => nodeFs.existsSync(file),
47
+ readFile: file => {
53
48
  try {
54
49
  return nodeFs.readFileSync(file, 'utf-8');
55
50
  } catch {
@@ -58,34 +53,23 @@ const compileScriptFs = {
58
53
  },
59
54
  };
60
55
 
61
- // Rewrites a Vue template AST so every `class`/`:class` binding on an element resolves
62
- // against this file's scoped class names at the compiled call site, via @symbiote-native/engine's
63
- // scopeClassName(value, localNames, scopeId). This runs at the AST level rather than as a
64
- // raw-text regex: Vue itself merges a static `class=`
65
- // and a dynamic `:class=` on the same element into ONE codegen entry, and text substitution
66
- // can't reproduce that merge safely; letting Vue's own transformElement do the merge on our
67
- // already-rewritten nodes reuses that logic instead of reimplementing it).
56
+ // Rewrites a Vue template AST so every `class`/`:class` binding resolves against this file's
57
+ // scoped class names via @symbiote-native/engine's scopeClassName(value, localNames, scopeId).
58
+ // AST-level, not a raw-text regex: Vue merges a static class= and a dynamic :class= on the same
59
+ // element into ONE codegen entry, and text substitution can't reproduce that merge safely -
60
+ // letting Vue's own transformElement do the merge on our rewritten nodes reuses that logic.
68
61
  //
69
- // A static class="foo bar" attribute is a plain AttributeNode (prop.type === 6): its value is
70
- // resolved to the final string directly here, at compile time — no runtime call needed for the
71
- // purely-static case, since every token is already known. Each token is normalized kebab->camel
72
- // FIRST (kebabToCamel) — a template may write class="section-label" (idiomatic CSS) instead of
73
- // class="sectionLabel"; the css-parser always registers the CAMEL form, and localNames (built
74
- // from that same registration) is camelCase-keyed, so the scoping check below only recognizes a
75
- // token once it is in that form. The emitted string is always camelCase, suffixed or not.
62
+ // A static class="foo bar" (AttributeNode, prop.type === 6) resolves to its final string here
63
+ // at compile time - no runtime call needed. Each token is normalized kebab->camel FIRST since
64
+ // css-parser always registers the camel form and localNames is camelCase-keyed.
76
65
  //
77
- // A dynamic :class="expr" is a `bind` DirectiveNode (prop.type === 7) targeting the `class`
78
- // arg. Vue's own transformExpression has ALREADY run by the time our transform sees it (node
79
- // transforms are appended after the built-in preset, per @vue/compiler-core's TransformOptions
80
- // merge order), so prop.exp is usually a COMPOUND_EXPRESSION (type 8, a `children` array mixing
81
- // literal source chunks with resolved identifier nodes), not a plain string — a bare identifier
82
- // binding (`:class="dynamicClass"`) is the one case that stays a SIMPLE_EXPRESSION (type 4).
83
- // Either way, `createCompoundExpression` wraps the ORIGINAL exp node (whichever shape it is) as
84
- // a single child inside `scopeClassName(<original>, __localScopedClassNames, __scopeId)`, so
85
- // codegen emits the call with the original expression source reproduced unchanged inside it —
86
- // this needs no per-shape branching, and correctly defers even a fully opaque runtime value
87
- // (`:class="dynamicClass"`) to scopeClassName's own runtime token-matching, so there is no
88
- // unresolved gap for dynamic scoped classes.
66
+ // A dynamic :class="expr" (bind DirectiveNode, prop.type === 7) targeting `class`: by the time
67
+ // our transform runs, Vue's own transformExpression has already turned prop.exp into either a
68
+ // COMPOUND_EXPRESSION (type 8) or, for a bare identifier binding, a SIMPLE_EXPRESSION (type 4).
69
+ // createCompoundExpression wraps the original exp node as-is inside
70
+ // scopeClassName(<original>, __localScopedClassNames, __scopeId), so codegen reproduces the
71
+ // original expression unchanged - no per-shape branching needed, and a fully opaque runtime
72
+ // value (`:class="dynamicClass"`) still defers correctly to scopeClassName's own token matching.
89
73
  function createScopeClassNodeTransform(localNames, scopeId) {
90
74
  return function scopeClassNodeTransform(node) {
91
75
  if (node.type !== 1 /* NodeTypes.ELEMENT */) return;
@@ -95,7 +79,7 @@ function createScopeClassNodeTransform(localNames, scopeId) {
95
79
  prop.value.content = prop.value.content
96
80
  .split(/\s+/)
97
81
  .filter(Boolean)
98
- .map((token) => {
82
+ .map(token => {
99
83
  const camelToken = kebabToCamel(token);
100
84
  return localNames.has(camelToken) ? `${camelToken}__${scopeId}` : camelToken;
101
85
  })
@@ -120,10 +104,9 @@ function createScopeClassNodeTransform(localNames, scopeId) {
120
104
  };
121
105
  }
122
106
 
123
- // A short, stable id per file, used as the SFC scope id (compileScript wants one regardless of
124
- // whether the file has scoped styles) — Vue's own `data-v-hash` naming convention, built on
125
- // @symbiote-native/css-parser's shared hashFilePath so the algorithm isn't duplicated against the
126
- // standalone .module.css compiler's identical need (metro-css-module.ts).
107
+ // A short, stable id per file, used as the SFC scope id regardless of whether the file has
108
+ // scoped styles - built on css-parser's shared hashFilePath so the algorithm isn't duplicated
109
+ // against the standalone .module.css compiler's identical need.
127
110
  function scopeIdFor(filename) {
128
111
  return 'data-v-' + hashFilePath(filename);
129
112
  }
@@ -139,9 +122,7 @@ const SFC_STYLE_LANG_TO_PREPROCESSOR = new Map([
139
122
  ]);
140
123
 
141
124
  // Reduces one <style> block down to plain CSS text. A lang-less or lang="css" block passes
142
- // through unchanged, exactly as before. Anything outside the four recognized preprocessor langs
143
- // (a typo, or a genuinely unsupported lang) still throws, same message as before this feature
144
- // existed.
125
+ // through unchanged. Anything outside the four recognized preprocessor langs throws.
145
126
  async function compileStyleBlockContent(style, filename) {
146
127
  if (style.lang == null || style.lang === 'css') return style.content;
147
128
 
@@ -170,54 +151,39 @@ async function compileSfc(src, filename) {
170
151
 
171
152
  const scopeId = scopeIdFor(filename);
172
153
 
173
- // `descriptor.styles` is already parsed by @vue/compiler-sfc itself (one entry per <style>
174
- // block, `.content` pre-trimmed, `.scoped` already a plain boolean flag), so there's no need
175
- // to re-extract style blocks with a regex.
154
+ // descriptor.styles is already parsed by @vue/compiler-sfc (one entry per <style> block,
155
+ // content pre-trimmed, scoped as a plain boolean) - no need to re-extract with a regex.
176
156
  //
177
- // A scoped block's classes get their key SUFFIXED with this file's scopeId before
178
- // registration (`card` -> `card__data-v-xxxxxxxx`), so two components can each define their
179
- // own `.card` without colliding in the shared global registry — mirroring what Vue's own
180
- // `data-v-hash` attribute does for DOM targets, just as a name suffix instead of an attribute
181
- // selector (we have neither DOM nor attribute-selector matching). An unscoped block's classes
182
- // register exactly as before: no suffix, globally shared. `:global(...)` selectors inside a
183
- // scoped block are the one exception — @symbiote-native/css-parser already unwraps them to their
184
- // plain class name (`:global(.reset)` parses like `.reset`), so `globalClassNamesIn` re-scans
185
- // the block's own raw text to find which specific keys should be exempted from suffixing.
157
+ // A scoped block's classes get their key SUFFIXED with this file's scopeId (`card` ->
158
+ // `card__data-v-xxxxxxxx`) so two components can each define `.card` without colliding in the
159
+ // shared global registry - our name-suffix equivalent of Vue's `data-v-hash` attribute (we
160
+ // have no DOM/attribute-selector matching). `:global(...)` selectors are exempted from
161
+ // suffixing; globalClassNamesIn re-walks the block's selectors to find which keys to exempt.
186
162
  //
187
- // Cascade multiple blocks last-block-wins, same as CSS — this holds across scoped/unscoped
188
- // blocks too: only each block's OWN css-parser output is scoped independently, then merged.
163
+ // Multiple blocks cascade last-block-wins, same as CSS, after each block is scoped independently.
189
164
  //
190
- // <style module> (CSS Modules) reuses this exact suffixing machinery instead of a separate
191
- // pipeline: `.card` still goes through parseCSS unchanged and still registers via the same
192
- // registerStyles() call, just under a suffixed key — the only new output is a plain name->
193
- // scopedName object (`$style` by default, or the block's `module="name"` value) emitted as a
194
- // preamble const, so `:class="$style.card"` passes the already-scoped string straight to
195
- // resolveClassName's existing exact-match path (no registry changes needed). Unlike `scoped`, a module block's classes are NEVER
196
- // auto-applied to a literal class="..." attribute — CSS Modules is opt-in per usage via
197
- // `$style.x`, so module classes are kept out of `localScopedNames` (the nodeTransform only
198
- // rewrites literal class strings for `scoped` blocks). The registry key gets an extra
199
- // `module` tag (`card__module__<scopeId>`, vs scoped's plain `card__<scopeId>`) so a file
200
- // that happens to mix `<style scoped>` and `<style module>` with the same class name can't
201
- // collide in the shared registry.
165
+ // <style module> (CSS Modules) reuses this same suffixing machinery: `.card` still goes
166
+ // through parseCSS and registerStyles unchanged, just under a suffixed key - the only new
167
+ // output is a name->scopedName object ($style by default) emitted as a preamble const, so
168
+ // `:class="$style.card"` passes the already-scoped string straight to resolveClassName's
169
+ // exact-match path. Unlike `scoped`, module classes are NEVER auto-applied to a literal
170
+ // class="..." (opt-in via $style.x only), so they're kept out of localScopedNames. The
171
+ // registry key gets an extra `module` tag (`card__module__<scopeId>` vs scoped's
172
+ // `card__<scopeId>`) so a file mixing both kinds can't collide.
202
173
  const styles = {};
203
174
  const localScopedNames = new Set();
204
175
  const cssModuleBindings = new Map();
205
176
 
206
177
  for (const style of descriptor.styles) {
207
- // Reduces a preprocessor block down to plain CSS text BEFORE any of the scoping logic
208
- // below runs — that logic is entirely language-agnostic, it only ever sees parseCSS's
209
- // plain-CSS output, same as it always did for a lang-less/lang="css" block. Anything other
210
- // than the four recognized preprocessor langs (a typo, or a genuinely unsupported lang)
211
- // still throws, unchanged from before.
178
+ // Reduces a preprocessor block to plain CSS BEFORE the scoping logic below runs - that
179
+ // logic is language-agnostic, it only ever sees parseCSS's plain-CSS output.
212
180
  const content = await compileStyleBlockContent(style, filename);
213
181
  const parsed = parseCSS(content, { filename });
214
182
 
215
183
  if (style.module) {
216
184
  const bindingName = typeof style.module === 'string' ? style.module : '$style';
217
- // Scanned against the COMPILED content, not style.content: :global(...) isn't native
218
- // SCSS/Less/Stylus syntax (each preprocessor passes an unrecognized selector through
219
- // unchanged), but scanning the compiler's actual output can't drift under nesting/
220
- // interpolation the way assuming source-and-output stay textually identical could.
185
+ // Scanned against the COMPILED content, not style.content, so it can't drift under
186
+ // preprocessor nesting/interpolation.
221
187
  const exemptFromScope = globalClassNamesIn(content);
222
188
  const classMap = cssModuleBindings.get(bindingName) ?? {};
223
189
  for (const [className, props] of Object.entries(parsed)) {
@@ -229,10 +195,25 @@ async function compileSfc(src, filename) {
229
195
  cssModuleBindings.set(bindingName, classMap);
230
196
  } else if (style.scoped) {
231
197
  const exemptFromScope = globalClassNamesIn(content);
198
+ // A compound/descendant selector registers under ONE collapsed key (`.card.big` ->
199
+ // `cardBig`) that never appears in the template - the template writes
200
+ // `class="card big"` - so the nodeTransform must recognize the individual TOKENS, not
201
+ // just the collapsed key.
202
+ const tokensByName = classTokensIn(content, { filename });
203
+ // ...and a token out of a `:global(...)` payload is the one exception to that: in
204
+ // `.card :global(.reset)` the KEY (`cardReset`) is this file's own, because `.card` is,
205
+ // but `reset` was written precisely to name markup this file does not own. Suffixing it
206
+ // along with the rest of its chain scope-mangles the escape hatch into matching nothing.
207
+ const globalTokens = globalClassTokensIn(content, { filename });
232
208
  for (const [className, props] of Object.entries(parsed)) {
233
209
  const isExempt = exemptFromScope.has(className);
234
210
  const registeredName = isExempt ? className : `${className}__${scopeId}`;
235
- if (!isExempt) localScopedNames.add(className);
211
+ if (!isExempt) {
212
+ localScopedNames.add(className);
213
+ for (const token of tokensByName.get(className) ?? []) {
214
+ if (!globalTokens.has(token)) localScopedNames.add(token);
215
+ }
216
+ }
236
217
  styles[registeredName] = { ...styles[registeredName], ...props };
237
218
  }
238
219
  } else {
@@ -242,10 +223,8 @@ async function compileSfc(src, filename) {
242
223
  }
243
224
  }
244
225
 
245
- // The nodeTransform rewrites every class/:class binding's compiled output to route through
246
- // scopeClassName() at the scoped names this file actually defines — skipped entirely (not
247
- // even passed to the compiler) when nothing in this file is scoped, so a .vue with only
248
- // unscoped/no styles compiles exactly as before, zero added runtime cost or behavior change.
226
+ // Skipped entirely (not even passed to the compiler) when nothing in this file is scoped, so
227
+ // a .vue with only unscoped/no styles compiles with zero added runtime cost.
249
228
  const templateOptions =
250
229
  localScopedNames.size > 0
251
230
  ? {
@@ -263,18 +242,17 @@ async function compileSfc(src, filename) {
263
242
  templateOptions,
264
243
  fs: compileScriptFs,
265
244
  });
266
- // Point every Vue import (the compiler's injected helpers AND the user's own
267
- // `import { ref } from 'vue'`) at the runtime-helpers shim, which re-exports the same
268
- // @vue/runtime-core singleton the @symbiote-native/vue adapter builds its custom renderer on, plus
269
- // our own directive implementations. No vue/runtime-dom in a native bundle.
270
- const code = compiled.content.replace(/from\s*(['"])vue\1/g, 'from "@symbiote-native/vue/runtime-helpers"');
245
+ // Retargets every Vue import (compiler-injected helpers AND the user's own `from 'vue'`) at
246
+ // the runtime-helpers shim - no vue/runtime-dom in a native bundle.
247
+ const code = compiled.content.replace(
248
+ /from\s*(['"])vue\1/g,
249
+ 'from "@symbiote-native/vue/runtime-helpers"',
250
+ );
271
251
 
272
252
  if (Object.keys(styles).length === 0) return code;
273
253
 
274
- // Only a scoped file needs scopeClassName + its two per-file constants — the nodeTransform
275
- // above only ever emits calls to `__scopeClass`/`__localScopedClassNames`/`__scopeId` when
276
- // localScopedNames is non-empty, so these stay unimported/undeclared (and absent from the
277
- // bundle) for every non-scoped .vue file.
254
+ // Only a scoped file needs scopeClassName + its two per-file constants, so these stay
255
+ // unimported for every non-scoped .vue file.
278
256
  const engineImports =
279
257
  localScopedNames.size > 0 ? 'registerStyles, scopeClassName as __scopeClass' : 'registerStyles';
280
258
 
@@ -285,49 +263,48 @@ async function compileSfc(src, filename) {
285
263
  `const __scopeId = ${JSON.stringify(scopeId)};`,
286
264
  );
287
265
  }
288
- // Each <style module> binding becomes a plain top-level const holding its name->scopedName
289
- // map. Placed before the compiled `export default {...}`, so it's just a closed-over module
290
- // scope variable inside setup() — same trick registerStyles/__scopeId already rely on — and
291
- // usable both from the inlined template (`:class="$style.card"`) and from <script setup> code
292
- // itself (`$style.card`), no extra wiring needed on either side.
266
+ // Each <style module> binding becomes a top-level const holding its name->scopedName map,
267
+ // placed before the compiled `export default {...}` so it's a closed-over module-scope
268
+ // variable usable both from the inlined template and from <script setup> code itself.
293
269
  for (const [bindingName, classMap] of cssModuleBindings) {
294
270
  preamble.push(`const ${bindingName} = ${JSON.stringify(classMap)};`);
295
271
  }
296
272
 
297
- return [`import { ${engineImports} } from '@symbiote-native/engine';`, ...preamble, code].join('\n') + '\n';
273
+ return (
274
+ [`import { ${engineImports} } from '@symbiote-native/engine';`, ...preamble, code].join('\n') +
275
+ '\n'
276
+ );
298
277
  }
299
278
 
300
279
  // Exported separately from `transform` so tests can assert on the compiled SFC output
301
280
  // (imports, injected `registerStyles` call) without driving the full upstream RN Babel preset.
302
281
  module.exports.compileSfc = compileSfc;
303
282
 
304
- // Async uniformly, including the `.vue` and plain-passthrough branches that never touch a
305
- // preprocessor: compileSfc() itself is async now (a scss/sass/less/stylus <style> block awaits
306
- // preprocessors.ts's compile()), and Metro's own metro-transform-worker already
307
- // `await transformer.transform(...)` before touching the result (confirmed by reading the
308
- // installed metro-transform-worker source), so returning a Promise here is a supported,
309
- // exercised shape, not a hack. A sync fast-path for
310
- // the no-preprocessor branches would fork this function into two shapes to save a single
311
- // microtask on a call that only ever runs at Metro build time, content-hash-cached — not worth
312
- // the duplication.
283
+ // Async uniformly, including branches that never touch a preprocessor: compileSfc() itself is
284
+ // async now (a scss/sass/less/stylus block awaits preprocessors.ts's compile()), and Metro's own
285
+ // metro-transform-worker already awaits transformer.transform(...), so this is a supported
286
+ // shape - not worth forking a sync fast-path to save one microtask on a build-time,
287
+ // content-hash-cached call.
313
288
  module.exports.transform = async function transform(params) {
314
289
  if (params.filename.endsWith('.vue')) {
315
290
  const code = await compileSfc(params.src, params.filename);
316
- // Re-label as .tsx so RN's transformer strips any TS from <script setup lang="ts"> and
317
- // processes the module exactly like app source. Metro tracks the real path separately.
291
+ // Re-label as .tsx so RN's transformer strips TS from <script setup lang="ts">. Metro
292
+ // tracks the real path separately.
318
293
  return upstreamTransformer.transform({
319
294
  ...params,
320
295
  src: code,
321
296
  filename: params.filename + '.tsx',
322
297
  });
323
298
  }
324
- // A standalone style file (as opposed to a `.vue` file's own inline <style> block above) —
325
- // the framework-agnostic path (core/css-parser's compileCssFile), usable from this example's
326
- // .vue files exactly like from any other adapter's example. isStyleFile recognizes
327
- // .css/.scss/.sass/.less/.styl/.stylus (+ each .module.* twin).
299
+ // A standalone style file (not a .vue file's inline <style> block) via the framework-agnostic
300
+ // compileCssFile path. isStyleFile recognizes .css/.scss/.sass/.less/.styl/.stylus (+ .module.* twins).
328
301
  if (isStyleFile(params.filename)) {
329
302
  const { code } = await compileCssFile(params.src, params.filename);
330
- return upstreamTransformer.transform({ ...params, src: code, filename: params.filename + '.js' });
303
+ return upstreamTransformer.transform({
304
+ ...params,
305
+ src: code,
306
+ filename: params.filename + '.js',
307
+ });
331
308
  }
332
309
  return upstreamTransformer.transform(params);
333
310
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/vue",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "SymbioteNative's Vue adapter — a @vue/runtime-core createRenderer driving real native iOS/Android views through the same engine as the React adapter.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,8 +46,8 @@
46
46
  "@vue/compiler-sfc": "^3.5.13",
47
47
  "@vue/runtime-core": "^3.5.13",
48
48
  "typescript": "~6.0.0",
49
- "@symbiote-native/components": "0.3.0",
50
- "@symbiote-native/css-parser": "0.2.3"
49
+ "@symbiote-native/components": "0.4.0",
50
+ "@symbiote-native/css-parser": "0.3.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@symbiote-native/engine": ">=0.1.7",
@@ -55,7 +55,7 @@
55
55
  "react-native": ">=0.86"
56
56
  },
57
57
  "devDependencies": {
58
- "@symbiote-native/engine": "0.1.7",
58
+ "@symbiote-native/engine": "0.2.0",
59
59
  "@symbiote-native/test-utils": "0.1.6"
60
60
  },
61
61
  "scripts": {