@startupjs/bundler 0.59.0-canary.7 → 0.60.0-canary.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/lib/eliminatorLoader.js +38 -10
- package/lib/startupjsLoader.js +3 -2
- package/metro-babel-transformer.js +4 -7
- package/package.json +8 -34
- package/buildOptions.json +0 -3
- package/helpers.js +0 -4
- package/lib/cssToReactNativeLoader.js +0 -86
- package/lib/rnTransformer.js +0 -42
- package/lib/stylusToCssLoader.js +0 -70
package/lib/eliminatorLoader.js
CHANGED
|
@@ -29,7 +29,6 @@ module.exports = function eliminatorLoader (source) {
|
|
|
29
29
|
|
|
30
30
|
let code = source
|
|
31
31
|
|
|
32
|
-
// STEP 1: convert pug to jsx and auto-load startupjs plugins
|
|
33
32
|
code = babel.transformSync(code, {
|
|
34
33
|
filename,
|
|
35
34
|
babelrc: false,
|
|
@@ -37,22 +36,19 @@ module.exports = function eliminatorLoader (source) {
|
|
|
37
36
|
plugins: [
|
|
38
37
|
// support JSX syntax
|
|
39
38
|
require('@babel/plugin-syntax-jsx'),
|
|
39
|
+
|
|
40
40
|
// transform pug to jsx. This generates a bunch of new AST nodes
|
|
41
41
|
// (it's important to do this first before any dead code elimination runs)
|
|
42
|
-
[require('
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// support calling sub-components in pug (like <Modal.Header />)
|
|
46
|
-
[require('@startupjs/babel-plugin-react-pug-classnames'), {
|
|
47
|
-
classAttribute: 'styleName'
|
|
48
|
-
}],
|
|
42
|
+
[require('cssxjs/babel/plugin-react-pug'), { classAttribute: 'styleName' }],
|
|
43
|
+
|
|
44
|
+
// auto-load startupjs plugins
|
|
49
45
|
// traverse "exports" of package.json and all dependencies to find all startupjs plugins
|
|
50
46
|
// and automatically import them in the main startupjs.config.js file
|
|
51
47
|
[require('@startupjs/babel-plugin-startupjs-plugins'), { useRequireContext }]
|
|
52
48
|
]
|
|
53
49
|
}).code
|
|
54
50
|
|
|
55
|
-
//
|
|
51
|
+
// Remove code related to other envs
|
|
56
52
|
code = babel.transformSync(code, {
|
|
57
53
|
filename,
|
|
58
54
|
babelrc: false,
|
|
@@ -60,6 +56,7 @@ module.exports = function eliminatorLoader (source) {
|
|
|
60
56
|
plugins: [
|
|
61
57
|
// support JSX syntax
|
|
62
58
|
require('@babel/plugin-syntax-jsx'),
|
|
59
|
+
|
|
63
60
|
// run eliminator to remove code targeting other envs.
|
|
64
61
|
// For example, only keep code related to 'client' and 'isomorphic' envs
|
|
65
62
|
// (in which case any code related to 'server' and 'build' envs will be removed)
|
|
@@ -109,9 +106,9 @@ module.exports = function eliminatorLoader (source) {
|
|
|
109
106
|
functionName: 'aggregation',
|
|
110
107
|
magicImports: ['startupjs'],
|
|
111
108
|
requirements: {
|
|
109
|
+
argumentsAmount: 1,
|
|
112
110
|
directNamedExportedAsConst: true
|
|
113
111
|
},
|
|
114
|
-
throwIfRequirementsNotMet: true, // TODO: remove this when the next transformation is implemented
|
|
115
112
|
replaceWith: {
|
|
116
113
|
newFunctionNameFromSameImport: '__aggregationHeader',
|
|
117
114
|
newCallArgumentsTemplate: `[
|
|
@@ -121,6 +118,37 @@ module.exports = function eliminatorLoader (source) {
|
|
|
121
118
|
}
|
|
122
119
|
]`
|
|
123
120
|
}
|
|
121
|
+
}, {
|
|
122
|
+
// export default inside of aggregation() within a separate model/*.$$myAggregation.js files
|
|
123
|
+
// are replaced with aggregationHeader() calls.
|
|
124
|
+
// Filepath is stripped of the extensions and split into sections (by dots and slashes)
|
|
125
|
+
// 'name' is the last section.
|
|
126
|
+
// 'collection' is the section before it.
|
|
127
|
+
//
|
|
128
|
+
// Example:
|
|
129
|
+
//
|
|
130
|
+
// // in model/games/$$active.js
|
|
131
|
+
// export default aggregation(({ gameId }) => ({ gameId }))
|
|
132
|
+
//
|
|
133
|
+
// will be replaced with:
|
|
134
|
+
//
|
|
135
|
+
// __aggregationHeader({ collection: 'games', name: '$$active' })
|
|
136
|
+
//
|
|
137
|
+
functionName: 'aggregation',
|
|
138
|
+
magicImports: ['startupjs'],
|
|
139
|
+
requirements: {
|
|
140
|
+
argumentsAmount: 1,
|
|
141
|
+
directDefaultExported: true
|
|
142
|
+
},
|
|
143
|
+
replaceWith: {
|
|
144
|
+
newFunctionNameFromSameImport: '__aggregationHeader',
|
|
145
|
+
newCallArgumentsTemplate: `[
|
|
146
|
+
{
|
|
147
|
+
collection: %%folderAndFilenameWithoutExtension%%.split(/[\\\\/\\.]/).at(-2),
|
|
148
|
+
name: %%folderAndFilenameWithoutExtension%%.split(/[\\\\/\\.]/).at(-1)
|
|
149
|
+
}
|
|
150
|
+
]`
|
|
151
|
+
}
|
|
124
152
|
}, {
|
|
125
153
|
// TODO: this has to be implemented! It's not actually working yet.
|
|
126
154
|
|
package/lib/startupjsLoader.js
CHANGED
|
@@ -14,10 +14,11 @@ module.exports = function startupjsLoader (source) {
|
|
|
14
14
|
babelrc: false,
|
|
15
15
|
configFile: false,
|
|
16
16
|
presets: [
|
|
17
|
-
[require('babel-preset-startupjs
|
|
17
|
+
[require('babel-preset-startupjs'), {
|
|
18
18
|
platform,
|
|
19
19
|
env
|
|
20
|
-
}]
|
|
20
|
+
}],
|
|
21
|
+
[require('cssxjs/babel'), { platform }]
|
|
21
22
|
]
|
|
22
23
|
}).code
|
|
23
24
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const cssToReactNativeLoader = require('./lib/cssToReactNativeLoader')
|
|
1
|
+
const stylusToCssLoader = require('cssxjs/loaders/stylusToCssLoader')
|
|
2
|
+
const cssToReactNativeLoader = require('cssxjs/loaders/cssToReactNativeLoader')
|
|
4
3
|
const mdxExamplesLoader = require('./lib/mdxExamplesLoader')
|
|
5
4
|
const getMDXLoader = require('./lib/getMDXLoader')
|
|
6
5
|
const eliminatorLoader = require('./lib/eliminatorLoader')
|
|
@@ -13,12 +12,10 @@ module.exports.transform = async function startupjsMetroBabelTransform ({
|
|
|
13
12
|
}) {
|
|
14
13
|
upstreamTransformer ??= getUpstreamTransformer()
|
|
15
14
|
const { platform } = options
|
|
16
|
-
platformSingleton.value = platform
|
|
17
15
|
|
|
18
16
|
// from exotic extensions to js
|
|
19
17
|
if (/\.styl$/.test(filename)) {
|
|
20
|
-
|
|
21
|
-
src = callLoader(stylusToCssLoader, src, filename)
|
|
18
|
+
src = callLoader(stylusToCssLoader, src, filename, { platform })
|
|
22
19
|
src = callLoader(cssToReactNativeLoader, src, filename)
|
|
23
20
|
} else if (/\.css$/.test(filename)) {
|
|
24
21
|
src = callLoader(cssToReactNativeLoader, src, filename)
|
|
@@ -38,7 +35,7 @@ module.exports.transform = async function startupjsMetroBabelTransform ({
|
|
|
38
35
|
clientModel: true
|
|
39
36
|
})
|
|
40
37
|
}
|
|
41
|
-
if ((/\.mdx?$/.test(filename) || /\.[mc]?[jt]sx?$/.test(filename)) && /['"](?:startupjs
|
|
38
|
+
if ((/\.mdx?$/.test(filename) || /\.[mc]?[jt]sx?$/.test(filename)) && /['"](?:startupjs)['"]/.test(src)) {
|
|
42
39
|
src = callLoader(startupjsLoader, src, filename, { platform })
|
|
43
40
|
}
|
|
44
41
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@startupjs/bundler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0-canary.0",
|
|
4
4
|
"description": "Opinionated scripts and configs to develop a react-native-web project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -17,47 +17,21 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/core": "^7.9.0",
|
|
19
19
|
"@babel/plugin-syntax-jsx": "^7.0.0",
|
|
20
|
-
"@babel/polyfill": "^7.8.0",
|
|
21
|
-
"@mdx-js/loader": "^2.3.0",
|
|
22
20
|
"@mdx-js/mdx": "^2.3.0",
|
|
23
|
-
"@
|
|
24
|
-
"@startupjs/babel-plugin-
|
|
25
|
-
"@startupjs/
|
|
26
|
-
"@startupjs/babel-plugin-react-pug-classnames": "^0.59.0-canary.0",
|
|
27
|
-
"@startupjs/babel-plugin-startupjs-plugins": "^0.59.0-canary.0",
|
|
28
|
-
"@startupjs/babel-plugin-transform-react-pug": "^7.0.1-0",
|
|
29
|
-
"@startupjs/css-to-react-native-transform": "^1.9.0-2",
|
|
30
|
-
"@startupjs/server": "^0.59.0-canary.7",
|
|
21
|
+
"@startupjs/babel-plugin-eliminator": "^0.60.0-canary.0",
|
|
22
|
+
"@startupjs/babel-plugin-startupjs-plugins": "^0.60.0-canary.0",
|
|
23
|
+
"@startupjs/server": "^0.60.0-canary.0",
|
|
31
24
|
"@svgr/core": "^8.1.0",
|
|
32
25
|
"@svgr/plugin-jsx": "^8.1.0",
|
|
33
26
|
"@svgr/plugin-svgo": "^8.1.0",
|
|
34
|
-
"
|
|
35
|
-
"assets-webpack-plugin": "^7.1.1",
|
|
36
|
-
"autoprefixer": "^10.4.0",
|
|
37
|
-
"babel-loader": "^8.2.3",
|
|
38
|
-
"babel-preset-startupjs": "^0.59.0-canary.7",
|
|
27
|
+
"babel-preset-startupjs": "^0.60.0-canary.0",
|
|
39
28
|
"connect": "^3.7.0",
|
|
40
|
-
"css-loader": "^6.5.0",
|
|
41
|
-
"css-minimizer-webpack-plugin": "^5.0.0",
|
|
42
|
-
"file-loader": "^6.2.0",
|
|
43
29
|
"lodash": "^4.17.20",
|
|
44
|
-
"
|
|
45
|
-
"moment": "^2.0.0",
|
|
46
|
-
"moment-locales-webpack-plugin": "^1.0.7",
|
|
47
|
-
"postcss": "^8.3.11",
|
|
48
|
-
"postcss-loader": "^7.2.0",
|
|
49
|
-
"process": "^0.11.10",
|
|
50
|
-
"react-native-svg-transformer": "0.20.0",
|
|
51
|
-
"react-refresh": "^0.10.0",
|
|
52
|
-
"remark-gfm": "^1.0.0",
|
|
53
|
-
"style-loader": "^3.3.1",
|
|
54
|
-
"stylus": "0.54.7",
|
|
55
|
-
"stylus-loader": "^6.2.0",
|
|
56
|
-
"terser-webpack-plugin": "^5.2.4",
|
|
57
|
-
"webpack-node-externals": "^3.0.0"
|
|
30
|
+
"remark-gfm": "^1.0.0"
|
|
58
31
|
},
|
|
59
32
|
"peerDependencies": {
|
|
33
|
+
"cssxjs": "*",
|
|
60
34
|
"react-native-svg": "*"
|
|
61
35
|
},
|
|
62
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "4c5baa750402d0beb02921a38413620b348bd374"
|
|
63
37
|
}
|
package/buildOptions.json
DELETED
package/helpers.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
// ref: https://github.com/kristerkari/react-native-css-transformer
|
|
2
|
-
const css2rn = require('@startupjs/css-to-react-native-transform').default
|
|
3
|
-
|
|
4
|
-
const EXPORT_REGEX = /:export\s*\{/
|
|
5
|
-
|
|
6
|
-
module.exports = function cssToReactNative (source) {
|
|
7
|
-
source = escapeExport(source)
|
|
8
|
-
const cssObject = css2rn(source, { parseMediaQueries: true, parsePartSelectors: true })
|
|
9
|
-
for (const key in cssObject.__exportProps || {}) {
|
|
10
|
-
cssObject[key] = parseStylValue(cssObject.__exportProps[key])
|
|
11
|
-
}
|
|
12
|
-
// save hash to use with the caching system of @startupjs/cache
|
|
13
|
-
cssObject.__hash__ = simpleNumericHash(JSON.stringify(cssObject))
|
|
14
|
-
return 'module.exports = ' + JSON.stringify(cssObject)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseStylValue (value) {
|
|
18
|
-
if (typeof value !== 'string') return value
|
|
19
|
-
// strip single quotes (stylus adds it for the topmost value)
|
|
20
|
-
// and parens (stylus adds them for values in a hash)
|
|
21
|
-
// Instead of doing a simple regex replace for both beginning and end,
|
|
22
|
-
// we only find beginning chars and then cut string from both sides.
|
|
23
|
-
// This is needed to prevent false-replacing the paren at the end of
|
|
24
|
-
// values like 'rgba(...)'
|
|
25
|
-
if (/^['"(]/.test(value)) {
|
|
26
|
-
const wrapsLength = value.match(/^['"(]+/)[0].length
|
|
27
|
-
value = value.slice(wrapsLength).slice(0, -wrapsLength)
|
|
28
|
-
}
|
|
29
|
-
// hash
|
|
30
|
-
if (value.charAt(0) === '{') {
|
|
31
|
-
const hash = JSON.parse(value)
|
|
32
|
-
for (const key in hash) {
|
|
33
|
-
hash[key] = parseStylValue(hash[key])
|
|
34
|
-
}
|
|
35
|
-
return hash
|
|
36
|
-
} else if (!isNaN(parseFloat(value))) {
|
|
37
|
-
return parseFloat(value)
|
|
38
|
-
} else {
|
|
39
|
-
return value
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Process :export properties by wrapping their values in quotes
|
|
44
|
-
function escapeExport (source) {
|
|
45
|
-
const match = source.match(EXPORT_REGEX)
|
|
46
|
-
if (!match) return source
|
|
47
|
-
|
|
48
|
-
// 1. find closing bracket of :export { ... }
|
|
49
|
-
const matchIndex = match.index
|
|
50
|
-
const matchStr = match[0]
|
|
51
|
-
const matchLength = matchStr.length
|
|
52
|
-
const start = matchIndex + matchLength
|
|
53
|
-
let openBr = 1 // Count opened brackets, we start from one already opened
|
|
54
|
-
let end
|
|
55
|
-
|
|
56
|
-
for (let i = start; i < source.length; i++) {
|
|
57
|
-
if (source.charAt(i) === '}') {
|
|
58
|
-
--openBr
|
|
59
|
-
} else if (source.charAt(i) === '{') {
|
|
60
|
-
++openBr
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (openBr <= 0) {
|
|
64
|
-
end = i
|
|
65
|
-
break
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (!end) return source
|
|
69
|
-
|
|
70
|
-
// 2. escape all exported values
|
|
71
|
-
const properties = source
|
|
72
|
-
.slice(start, end)
|
|
73
|
-
.split(';')
|
|
74
|
-
.map(line => line.replace(/(:\s+)([^'"].*[^'"])$/, '$1\'$2\''))
|
|
75
|
-
.join(';')
|
|
76
|
-
|
|
77
|
-
source = source.slice(0, start) + properties + source.slice(end)
|
|
78
|
-
|
|
79
|
-
return source
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ref: https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0?permalink_comment_id=2694461#gistcomment-2694461
|
|
83
|
-
function simpleNumericHash (s) {
|
|
84
|
-
for (var i = 0, h = 0; i < s.length; i++) h = Math.imul(31, h) + s.charCodeAt(i) | 0
|
|
85
|
-
return h
|
|
86
|
-
}
|
package/lib/rnTransformer.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
const upstreamTransformer = require('metro-react-native-babel-transformer')
|
|
2
|
-
const svgTransformer = require('react-native-svg-transformer')
|
|
3
|
-
const platformSingleton = require(
|
|
4
|
-
'@startupjs/babel-plugin-rn-stylename-inline/platformSingleton'
|
|
5
|
-
)
|
|
6
|
-
const stylusToCssLoader = require('./stylusToCssLoader')
|
|
7
|
-
const cssToReactNativeLoader = require('./cssToReactNativeLoader')
|
|
8
|
-
const mdxExamplesLoader = require('./mdxExamplesLoader')
|
|
9
|
-
const getMDXLoader = require('./getMDXLoader')
|
|
10
|
-
const eliminatorLoader = require('./eliminatorLoader')
|
|
11
|
-
const callLoader = require('./callLoader')
|
|
12
|
-
|
|
13
|
-
module.exports.transform = async function ({ src, filename, options = {} }) {
|
|
14
|
-
const { platform } = options
|
|
15
|
-
platformSingleton.value = platform
|
|
16
|
-
|
|
17
|
-
if (/\.styl$/.test(filename)) {
|
|
18
|
-
src = callLoader(stylusToCssLoader, src, filename)
|
|
19
|
-
src = callLoader(cssToReactNativeLoader, src, filename)
|
|
20
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
21
|
-
} else if (/\.css$/.test(filename)) {
|
|
22
|
-
src = callLoader(cssToReactNativeLoader, src, filename)
|
|
23
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
24
|
-
} else if (/\.svg$/.test(filename)) {
|
|
25
|
-
return svgTransformer.transform({ src, filename, options })
|
|
26
|
-
} else if (/(?:[./]plugin\.[mc]?[jt]sx?|startupjs\.config\.js)$/.test(filename)) {
|
|
27
|
-
src = callLoader(eliminatorLoader, src, filename, { envs: ['client', 'isomorphic'] })
|
|
28
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
29
|
-
} else if (/\.[cm]?jsx?$/.test(filename) && /['"]startupjs['"]/.test(src)) {
|
|
30
|
-
// TODO: This particular check and transform is probably not needed anymore since default one
|
|
31
|
-
// will handle all .js files anyways no matter whether 'startupjs' library
|
|
32
|
-
// is used inside or not.
|
|
33
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
34
|
-
} else if (/\.mdx?$/.test(filename)) {
|
|
35
|
-
const mdxLoader = await getMDXLoader()
|
|
36
|
-
src = callLoader(mdxExamplesLoader, src, filename)
|
|
37
|
-
src = callLoader(mdxLoader, src, filename)
|
|
38
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
39
|
-
} else {
|
|
40
|
-
return upstreamTransformer.transform({ src, filename, options })
|
|
41
|
-
}
|
|
42
|
-
}
|
package/lib/stylusToCssLoader.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// ref: https://github.com/kristerkari/react-native-stylus-transformer
|
|
2
|
-
// TODO: Refactor `platform` to be just passed externally as an option in metro and in webpack
|
|
3
|
-
const platformSingleton = require(
|
|
4
|
-
'@startupjs/babel-plugin-rn-stylename-inline/platformSingleton'
|
|
5
|
-
)
|
|
6
|
-
const { existsSync } = require('fs')
|
|
7
|
-
const { join } = require('path')
|
|
8
|
-
const stylus = require('stylus')
|
|
9
|
-
|
|
10
|
-
const PROJECT_STYLES_PATH = join(process.cwd(), 'styles/index.styl')
|
|
11
|
-
let UI_STYLES_PATH
|
|
12
|
-
|
|
13
|
-
function renderToCSS (src, filename) {
|
|
14
|
-
let compiled
|
|
15
|
-
const compiler = stylus(src)
|
|
16
|
-
const platform = platformSingleton.value
|
|
17
|
-
compiler.set('filename', filename)
|
|
18
|
-
|
|
19
|
-
if (platform) {
|
|
20
|
-
compiler.define('$PLATFORM', platform)
|
|
21
|
-
compiler.define(`__${platform.toUpperCase()}__`, true)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (checkUiStylesExist()) {
|
|
25
|
-
compiler.import(UI_STYLES_PATH)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// TODO: Make this a setting
|
|
29
|
-
if (checkProjectStylesExist()) {
|
|
30
|
-
compiler.import(PROJECT_STYLES_PATH)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
compiler.render(function (err, res) {
|
|
34
|
-
if (err) {
|
|
35
|
-
throw new Error(err)
|
|
36
|
-
}
|
|
37
|
-
compiled = res
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
return compiled
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = function stylusToReactNative (source) {
|
|
44
|
-
return renderToCSS(source, this.resourcePath)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// check if @startupjs/ui is being used to load styles file from it, cache result for 5 seconds
|
|
48
|
-
let uiStylesExist
|
|
49
|
-
let uiStylesLastChecked = 0
|
|
50
|
-
function checkUiStylesExist () {
|
|
51
|
-
if (uiStylesLastChecked + 5000 > Date.now()) return uiStylesExist
|
|
52
|
-
uiStylesLastChecked = Date.now()
|
|
53
|
-
try {
|
|
54
|
-
UI_STYLES_PATH = join(require.resolve('@startupjs/ui'), '../styles/index.styl')
|
|
55
|
-
uiStylesExist = existsSync(UI_STYLES_PATH)
|
|
56
|
-
} catch {
|
|
57
|
-
uiStylesExist = false
|
|
58
|
-
}
|
|
59
|
-
return uiStylesExist
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// check if project styles file exist, cache result for 5 seconds
|
|
63
|
-
let projectStylesExist
|
|
64
|
-
let projectStylesLastChecked = 0
|
|
65
|
-
function checkProjectStylesExist () {
|
|
66
|
-
if (projectStylesLastChecked + 5000 > Date.now()) return projectStylesExist
|
|
67
|
-
projectStylesLastChecked = Date.now()
|
|
68
|
-
projectStylesExist = existsSync(PROJECT_STYLES_PATH)
|
|
69
|
-
return projectStylesExist
|
|
70
|
-
}
|