@cssxjs/babel-plugin-rn-stylename-inline 0.2.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/CHANGELOG.md +15 -0
- package/README.md +76 -0
- package/compilers/css.js +13 -0
- package/compilers/helpers.js +3 -0
- package/compilers/index.js +7 -0
- package/compilers/styl.js +14 -0
- package/index.js +126 -0
- package/package.json +38 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# v0.2.0 (Tue Nov 04 2025)
|
|
2
|
+
|
|
3
|
+
#### 🚀 Enhancement
|
|
4
|
+
|
|
5
|
+
- feat: refactor all babel plugins to perform early transformation of all code in Program.enter block ([@cray0000](https://github.com/cray0000))
|
|
6
|
+
- feat: make it work for pure web through a babel plugin [#2](https://github.com/startupjs/cssx/pull/2) ([@cray0000](https://github.com/cray0000))
|
|
7
|
+
- feat: move over styles-related packages from startupjs ([@cray0000](https://github.com/cray0000))
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fix
|
|
10
|
+
|
|
11
|
+
- fix(babel-plugin-rn-stylename-to-stylename-inline): fix import aliases support, update tests ([@cray0000](https://github.com/cray0000))
|
|
12
|
+
|
|
13
|
+
#### Authors: 1
|
|
14
|
+
|
|
15
|
+
- Pavel Zhukov ([@cray0000](https://github.com/cray0000))
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @cssxjs/babel-plugin-rn-stylename-inline
|
|
2
|
+
|
|
3
|
+
Adds support for in-JS template strings `css\`\`` and `styl\`\``
|
|
4
|
+
for CSS styles for react-native.
|
|
5
|
+
|
|
6
|
+
Must be used together with `@cssxjs/babel-plugin-rn-stylename-to-style` library.
|
|
7
|
+
|
|
8
|
+
## Options
|
|
9
|
+
|
|
10
|
+
- `platform` -- what platform the compilation is on. This is passed down to the underlying compiler (for example in Stylus it defines global variables `$PLATFORM = "web"` and `__WEB__ = true`). Example: `"web"` or `"ios"` or `"android"`. Default: `'web'`.
|
|
11
|
+
- `magicImports` -- an array of magic imports to use. Example: `["cssxjs", "startupjs"]`. Default: `["cssxjs"]`.
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
### File-level scope (global to file)
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
import React from 'react'
|
|
19
|
+
import { View } from 'react-native'
|
|
20
|
+
import { css } from 'cssxjs'
|
|
21
|
+
|
|
22
|
+
export default function Card () {
|
|
23
|
+
return <View styleName='card active'><Line /></View>
|
|
24
|
+
}
|
|
25
|
+
function Line () {
|
|
26
|
+
return <View styleName='line' />
|
|
27
|
+
}
|
|
28
|
+
css`
|
|
29
|
+
.card {
|
|
30
|
+
padding: 8px 16px;
|
|
31
|
+
}
|
|
32
|
+
.line {
|
|
33
|
+
margin-top: 16px;
|
|
34
|
+
border-radius: 8px;
|
|
35
|
+
}
|
|
36
|
+
.active {
|
|
37
|
+
background-color: red;
|
|
38
|
+
}
|
|
39
|
+
`
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Local component scope (inside particular react component function)
|
|
43
|
+
|
|
44
|
+
```jsx
|
|
45
|
+
import React from 'react'
|
|
46
|
+
import { View } from 'react-native'
|
|
47
|
+
import { css, styl } from 'cssxjs'
|
|
48
|
+
|
|
49
|
+
export default function Card () {
|
|
50
|
+
return <View styleName='root active'><Line /></View>
|
|
51
|
+
// .root will be scoped only to this specific component
|
|
52
|
+
styl`
|
|
53
|
+
.root
|
|
54
|
+
padding: 8px 16px
|
|
55
|
+
`
|
|
56
|
+
}
|
|
57
|
+
function Line () {
|
|
58
|
+
return <View styleName='root' />
|
|
59
|
+
// .root will be scoped only to this specific component
|
|
60
|
+
css`
|
|
61
|
+
.root {
|
|
62
|
+
margin-top: 16px;
|
|
63
|
+
border-radius: 8px;
|
|
64
|
+
}
|
|
65
|
+
`
|
|
66
|
+
}
|
|
67
|
+
// you can use global- and local- scoped styles together
|
|
68
|
+
styl`
|
|
69
|
+
.active
|
|
70
|
+
background-color red
|
|
71
|
+
`
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT
|
package/compilers/css.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// TODO: Move loaders into standalone libs
|
|
2
|
+
const cssLoader = require('@cssxjs/bundler/lib/cssToReactNativeLoader')
|
|
3
|
+
const callLoader = require('@cssxjs/bundler/lib/callLoader')
|
|
4
|
+
const { stripExport } = require('./helpers')
|
|
5
|
+
|
|
6
|
+
module.exports = function compileCss (src) {
|
|
7
|
+
return stripExport(
|
|
8
|
+
callLoader(
|
|
9
|
+
cssLoader,
|
|
10
|
+
src
|
|
11
|
+
)
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// TODO: Move loaders into standalone libs
|
|
2
|
+
const stylLoader = require('@cssxjs/bundler/lib/stylusToCssLoader')
|
|
3
|
+
const callLoader = require('@cssxjs/bundler/lib/callLoader')
|
|
4
|
+
const compileCss = require('./css')
|
|
5
|
+
|
|
6
|
+
module.exports = function compileStyl (src, filename, options) {
|
|
7
|
+
src = callLoader(
|
|
8
|
+
stylLoader,
|
|
9
|
+
src,
|
|
10
|
+
filename,
|
|
11
|
+
options
|
|
12
|
+
)
|
|
13
|
+
return compileCss(src)
|
|
14
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const { GLOBAL_NAME, LOCAL_NAME } =
|
|
2
|
+
require('@cssxjs/runtime/constants')
|
|
3
|
+
const template = require('@babel/template').default
|
|
4
|
+
const parser = require('@babel/parser')
|
|
5
|
+
const t = require('@babel/types')
|
|
6
|
+
const compilers = require('./compilers')
|
|
7
|
+
const DEFAULT_MAGIC_IMPORTS = ['cssxjs']
|
|
8
|
+
const DEFAULT_PLATFORM = 'web'
|
|
9
|
+
|
|
10
|
+
const buildConst = template(`
|
|
11
|
+
const %%variable%% = %%value%%
|
|
12
|
+
`)
|
|
13
|
+
|
|
14
|
+
module.exports = () => ({
|
|
15
|
+
visitor: {
|
|
16
|
+
Program: {
|
|
17
|
+
enter ($this, state) {
|
|
18
|
+
const usedCompilers = getUsedCompilers($this, state)
|
|
19
|
+
$this.traverse(getVisitor({ $program: $this, usedCompilers }), state)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const getVisitor = ({ $program, usedCompilers }) => ({
|
|
26
|
+
TaggedTemplateExpression: ($this, state) => {
|
|
27
|
+
// 0. process only templates which are in usedCompilers (imported from our library)
|
|
28
|
+
if (!shouldProcess($this, usedCompilers)) return
|
|
29
|
+
|
|
30
|
+
// I. validate template
|
|
31
|
+
validateTemplate($this, usedCompilers)
|
|
32
|
+
|
|
33
|
+
const compiler = usedCompilers[$this.node.tag.name]
|
|
34
|
+
|
|
35
|
+
// II. compile template
|
|
36
|
+
const source = $this.node.quasi.quasis[0]?.value?.raw || ''
|
|
37
|
+
const filename = state.file?.opts?.filename
|
|
38
|
+
const platform = state.opts?.platform || DEFAULT_PLATFORM
|
|
39
|
+
const compiledString = compiler(source, filename, { platform })
|
|
40
|
+
const compiledExpression = parser.parseExpression(compiledString)
|
|
41
|
+
|
|
42
|
+
// III. find parent function or program
|
|
43
|
+
const $function = $this.getFunctionParent()
|
|
44
|
+
|
|
45
|
+
// IV. LOCAL. if parent is function -- handle local
|
|
46
|
+
if ($function) {
|
|
47
|
+
// 1. define a `const` variable at the top of the file
|
|
48
|
+
// with the unique identifier
|
|
49
|
+
const localIdentifier = $program.scope.generateUidIdentifier('localCssInstance')
|
|
50
|
+
insertAfterImports($program, buildConst({
|
|
51
|
+
variable: localIdentifier,
|
|
52
|
+
value: compiledExpression
|
|
53
|
+
}))
|
|
54
|
+
|
|
55
|
+
// 2. reassign this unique identifier to a constant LOCAL_NAME
|
|
56
|
+
// in the scope of current function
|
|
57
|
+
$function.get('body').unshiftContainer('body', buildConst({
|
|
58
|
+
variable: t.identifier(LOCAL_NAME),
|
|
59
|
+
value: localIdentifier
|
|
60
|
+
}))
|
|
61
|
+
|
|
62
|
+
// V. GLOBAL. if parent is program -- handle global
|
|
63
|
+
} else {
|
|
64
|
+
// 1. define a `const` variable at the top of the file
|
|
65
|
+
// with the constant GLOBAL_NAME
|
|
66
|
+
insertAfterImports($program, buildConst({
|
|
67
|
+
variable: t.identifier(GLOBAL_NAME),
|
|
68
|
+
value: compiledExpression
|
|
69
|
+
}))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// VI. Remove template expression after processing
|
|
73
|
+
$this.remove()
|
|
74
|
+
|
|
75
|
+
// TODO: Throw error if global styles were already added or
|
|
76
|
+
// local styles were already added to the same function scope
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
function insertAfterImports ($program, expressionStatement) {
|
|
81
|
+
const lastImport = $program
|
|
82
|
+
.get('body')
|
|
83
|
+
.filter($i => $i.isImportDeclaration())
|
|
84
|
+
.pop()
|
|
85
|
+
|
|
86
|
+
if (lastImport) {
|
|
87
|
+
lastImport.insertAfter(expressionStatement)
|
|
88
|
+
} else {
|
|
89
|
+
$program.unshift(expressionStatement)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function shouldProcess ($template, usedCompilers = {}) {
|
|
94
|
+
if (!$template.get('tag').isIdentifier()) return
|
|
95
|
+
if (!usedCompilers[$template.node.tag.name]) return
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function validateTemplate ($template, usedCompilers = {}) {
|
|
100
|
+
const { node: { quasi } } = $template
|
|
101
|
+
|
|
102
|
+
if (quasi.expressions.length > 0) {
|
|
103
|
+
throw $template.buildCodeFrameError(`
|
|
104
|
+
[@cssxjs/babel-plugin-rn-stylename-inline] Expression interpolations are not supported in css\`\` and styl\`\`.
|
|
105
|
+
`)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getUsedCompilers ($program, state) {
|
|
110
|
+
const res = {}
|
|
111
|
+
const magicImports = state.opts.magicImports || DEFAULT_MAGIC_IMPORTS
|
|
112
|
+
for (const $import of $program.get('body')) {
|
|
113
|
+
if (!$import.isImportDeclaration()) continue
|
|
114
|
+
if (!magicImports.includes($import.node.source.value)) continue
|
|
115
|
+
for (const $specifier of $import.get('specifiers')) {
|
|
116
|
+
if (!$specifier.isImportSpecifier()) continue
|
|
117
|
+
const { local, imported } = $specifier.node
|
|
118
|
+
if (compilers[imported.name]) {
|
|
119
|
+
res[local.name] = compilers[imported.name]
|
|
120
|
+
$specifier.remove()
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if ($import.get('specifiers').length === 0) $import.remove()
|
|
124
|
+
}
|
|
125
|
+
return res
|
|
126
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cssxjs/babel-plugin-rn-stylename-inline",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "Use styleName attributes with inline css and styl template strings",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"babel",
|
|
10
|
+
"babel-plugin",
|
|
11
|
+
"react",
|
|
12
|
+
"lazy",
|
|
13
|
+
"import"
|
|
14
|
+
],
|
|
15
|
+
"main": "index.js",
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "jest"
|
|
18
|
+
},
|
|
19
|
+
"author": "Pavel Zhukov",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/startupjs/startupjs"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@babel/parser": "^7.0.0",
|
|
27
|
+
"@babel/template": "^7.4.0",
|
|
28
|
+
"@babel/types": "^7.0.0",
|
|
29
|
+
"@cssxjs/bundler": "^0.2.0",
|
|
30
|
+
"@cssxjs/runtime": "^0.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@babel/plugin-syntax-jsx": "^7.0.0",
|
|
34
|
+
"babel-plugin-tester": "^9.1.0",
|
|
35
|
+
"jest": "^30.0.4"
|
|
36
|
+
},
|
|
37
|
+
"gitHead": "a80a44b4d14c116871ca03997ce772b6beabf5d8"
|
|
38
|
+
}
|