@magic/css 0.7.39 → 0.7.43
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/README.md +53 -1
- package/package.json +11 -7
- package/src/bin/index.js +96 -0
- package/src/parse/index.mjs +10 -1
- package/src/stringify/fontFaces.mjs +150 -0
- package/src/stringify/index.mjs +24 -1
- package/src/stringify/recurseStringify.mjs +14 -92
package/README.md
CHANGED
|
@@ -29,8 +29,44 @@ parse/stringify/write css in js
|
|
|
29
29
|
npm install --save-exact @magic/css
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
|
|
32
33
|
#### usage:
|
|
33
34
|
|
|
35
|
+
##### cli:
|
|
36
|
+
|
|
37
|
+
@magic/css includes a cli script that can handle most usecases the internal javascript api allows.
|
|
38
|
+
|
|
39
|
+
to use this cli from any directory,
|
|
40
|
+
`npm install -g @magic.css` is a useful shortcut.
|
|
41
|
+
after the global install, you can just call `mcss` from anywhere in your terminal.
|
|
42
|
+
|
|
43
|
+
after installation, add:
|
|
44
|
+
`"mcss": "mcss"`
|
|
45
|
+
to your package.json "scripts" section and then
|
|
46
|
+
`npm run mcss`
|
|
47
|
+
to see the help output below.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
@magic/css
|
|
51
|
+
commands:
|
|
52
|
+
stringify - convert css in js to css
|
|
53
|
+
parse - convert css in js to an array of key value pairs
|
|
54
|
+
full - get a full result object.
|
|
55
|
+
|
|
56
|
+
flags:
|
|
57
|
+
--minified - output minified css - alias: ["--m", "-m"]
|
|
58
|
+
--help - alias: ["-h"]
|
|
59
|
+
--out - directory to write output files to. omit to print to stdout - alias: ["--o", "-o"]
|
|
60
|
+
--in - directory with source files, needs index.js to exist - alias: ["--i", "-i"]
|
|
61
|
+
|
|
62
|
+
examples:
|
|
63
|
+
mcss parse --in ./styles --out ./css
|
|
64
|
+
mcss stringify --in ./styles --out ./css
|
|
65
|
+
mcss full --in ./styles --out ./css
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### library:
|
|
69
|
+
|
|
34
70
|
##### init
|
|
35
71
|
```javascript
|
|
36
72
|
import css from '@magic/css'
|
|
@@ -487,6 +523,22 @@ overflowX is output as overflowx in earlier versions, the regex expected lowerca
|
|
|
487
523
|
#### 0.7.39
|
|
488
524
|
update dependencies
|
|
489
525
|
|
|
490
|
-
#### 0.7.40
|
|
526
|
+
#### 0.7.40
|
|
527
|
+
update dependencies
|
|
528
|
+
|
|
529
|
+
#### 0.7.41
|
|
530
|
+
update dependencies
|
|
531
|
+
|
|
532
|
+
#### 0.7.42
|
|
533
|
+
update dependencies
|
|
534
|
+
|
|
535
|
+
#### 0.7.43
|
|
536
|
+
* update dependencies
|
|
537
|
+
* added font v2 to allow handling of local() fonts (see https://magic.github.io/css/#styles-webfonts)
|
|
538
|
+
* woff2 files are placed before woff files
|
|
539
|
+
* use single quotes in output css
|
|
540
|
+
* add cli
|
|
541
|
+
|
|
542
|
+
#### 0.7.44 - unreleased
|
|
491
543
|
...
|
|
492
544
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic/css",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.43",
|
|
4
4
|
"author": "Wizards & Witches",
|
|
5
5
|
"description": "css in js",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"test": "t --exclude docs example config.js",
|
|
18
18
|
"calls": "calls"
|
|
19
19
|
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"mcss": "src/bin/index.js",
|
|
22
|
+
"magic-css": "src/bin/index.js"
|
|
23
|
+
},
|
|
20
24
|
"engines": {
|
|
21
25
|
"node": ">=14.15.4"
|
|
22
26
|
},
|
|
@@ -35,11 +39,11 @@
|
|
|
35
39
|
"dependencies": {
|
|
36
40
|
"@magic/cases": "0.0.5",
|
|
37
41
|
"@magic/deep": "0.1.7",
|
|
38
|
-
"@magic/fs": "0.0.
|
|
42
|
+
"@magic/fs": "0.0.18",
|
|
39
43
|
"@magic/log": "0.1.10",
|
|
40
44
|
"@magic/types": "0.1.16",
|
|
41
|
-
"autoprefixer": "10.
|
|
42
|
-
"postcss": "8.
|
|
45
|
+
"autoprefixer": "10.4.0",
|
|
46
|
+
"postcss": "8.4.5"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"@magic-modules/git-badges": "0.0.11",
|
|
@@ -47,9 +51,9 @@
|
|
|
47
51
|
"@magic-modules/no-spy": "0.0.6",
|
|
48
52
|
"@magic-modules/pre": "0.0.11",
|
|
49
53
|
"@magic-themes/docs": "0.0.14",
|
|
50
|
-
"@magic/core": "0.0.
|
|
51
|
-
"@magic/format": "0.0.
|
|
52
|
-
"@magic/test": "0.1.
|
|
54
|
+
"@magic/core": "0.0.133",
|
|
55
|
+
"@magic/format": "0.0.33",
|
|
56
|
+
"@magic/test": "0.1.77"
|
|
53
57
|
},
|
|
54
58
|
"keywords": [
|
|
55
59
|
"css-in-js",
|
package/src/bin/index.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'path'
|
|
4
|
+
|
|
5
|
+
import cli from '@magic/cli'
|
|
6
|
+
import fs from '@magic/fs'
|
|
7
|
+
import log from '@magic/log'
|
|
8
|
+
|
|
9
|
+
import css from '../index.mjs'
|
|
10
|
+
|
|
11
|
+
const cwd = process.cwd()
|
|
12
|
+
|
|
13
|
+
const { args, commands } = cli({
|
|
14
|
+
commands: ['full', 'parse', 'stringify'],
|
|
15
|
+
options: [
|
|
16
|
+
['--in', '--i', '-i'],
|
|
17
|
+
['--out', '--o', '-o'],
|
|
18
|
+
['--minified', '--m', '-m'],
|
|
19
|
+
],
|
|
20
|
+
single: ['--in', '--out', '--minified'],
|
|
21
|
+
help: {
|
|
22
|
+
name: '@magic/css',
|
|
23
|
+
header: 'css in js pipeline.',
|
|
24
|
+
commands: {
|
|
25
|
+
full: 'get a full result object.',
|
|
26
|
+
parse: 'convert css in js to an array of key value pairs',
|
|
27
|
+
stringify: 'convert css in js to css',
|
|
28
|
+
},
|
|
29
|
+
options: {
|
|
30
|
+
'--in': 'directory with index.js that has a css in js object as default export',
|
|
31
|
+
'--out': 'directory to write output files to. omit to print to stdout',
|
|
32
|
+
'--minified': 'output minified css',
|
|
33
|
+
},
|
|
34
|
+
example: `
|
|
35
|
+
mcss parse --in ./css --out ./css
|
|
36
|
+
mcss stringify --in ./styles --out ./css
|
|
37
|
+
`.trim(),
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const logResult = style => log.success('mcss output', `\n\n${style}\n`)
|
|
42
|
+
|
|
43
|
+
const maybeWrite = async ({ args, commands, style }) => {
|
|
44
|
+
const outFile = commands.stringify ? 'main.css' : 'theme.js'
|
|
45
|
+
|
|
46
|
+
if (args.out) {
|
|
47
|
+
if (!path.isAbsolute(args.out)) {
|
|
48
|
+
args.out = path.join(cwd, args.out)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!args.out.endsWith('.css') && !args.out.endsWith('.js')) {
|
|
52
|
+
args.out = path.join(args.out, outFile)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const dirname = path.dirname(args.out)
|
|
56
|
+
await fs.mkdirp(dirname)
|
|
57
|
+
|
|
58
|
+
await fs.writeFile(args.out, style)
|
|
59
|
+
} else {
|
|
60
|
+
logResult(style)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
log.success('mcss is done.')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const run = async () => {
|
|
67
|
+
if (!args.in) {
|
|
68
|
+
args.in = cwd
|
|
69
|
+
log.info('--in not specified, using process.cwd()', args.in)
|
|
70
|
+
} else if (!path.isAbsolute(args.in)) {
|
|
71
|
+
args.in = path.join(cwd, args.in)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!args.in.endsWith('index.js')) {
|
|
75
|
+
args.in = path.join(args.in, 'index.js')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { default: theme } = await import(args.in)
|
|
79
|
+
|
|
80
|
+
const result = await css(theme)
|
|
81
|
+
|
|
82
|
+
if (commands.full) {
|
|
83
|
+
const style = JSON.stringify(result, null, 2)
|
|
84
|
+
maybeWrite({ args, commands, style })
|
|
85
|
+
} else if (commands.stringify) {
|
|
86
|
+
const style = args.hasOwnProperty('minified') ? result.minified : result.css
|
|
87
|
+
maybeWrite({ args, commands, style })
|
|
88
|
+
} else if (commands.parse) {
|
|
89
|
+
const style = JSON.stringify(result.parsed, null, 2)
|
|
90
|
+
maybeWrite({ args, commands, style })
|
|
91
|
+
} else {
|
|
92
|
+
log.error('MISSING_COMMAND', 'Either parse, stringify or full are required.')
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
run()
|
package/src/parse/index.mjs
CHANGED
|
@@ -67,6 +67,11 @@ const recurseParse = (mod, opts) => {
|
|
|
67
67
|
|
|
68
68
|
const isStyle = style => style && style.length === 2 && is.string(style[0]) && is.object(style[1])
|
|
69
69
|
|
|
70
|
+
/*
|
|
71
|
+
* we can not use deep.flatten here, the flattened array has a specific structure:
|
|
72
|
+
* [[key, styles], [key, styles]],
|
|
73
|
+
* deep.flatten would return [key, styles, key, styles]
|
|
74
|
+
*/
|
|
70
75
|
const flat = a => {
|
|
71
76
|
if (isStyle(a)) {
|
|
72
77
|
const [k, v] = a
|
|
@@ -83,10 +88,14 @@ const flat = a => {
|
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
})
|
|
91
|
+
|
|
86
92
|
return flattened
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
/*
|
|
97
|
+
* parse the styles css object into an array of key-value pairs.
|
|
98
|
+
*/
|
|
90
99
|
const parse = (styles, opts = {}) => {
|
|
91
100
|
// first check if the user sent us a function that resolves to a css object
|
|
92
101
|
if (is.function(styles)) {
|
|
@@ -96,7 +105,7 @@ const parse = (styles, opts = {}) => {
|
|
|
96
105
|
// this might trigger additionally to the is.function if statement above
|
|
97
106
|
if (is.array(styles)) {
|
|
98
107
|
styles = styles.map(s => recurseParse(s, opts))
|
|
99
|
-
} else if (!is.array(styles) && is.
|
|
108
|
+
} else if (!is.array(styles) && is.objectNative(styles)) {
|
|
100
109
|
styles = Object.entries(styles).map(s => recurseParse(s, opts))
|
|
101
110
|
} else {
|
|
102
111
|
log.error('invalid styles received', styles)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import is from '@magic/types'
|
|
2
|
+
import deep from '@magic/deep'
|
|
3
|
+
import log from '@magic/log'
|
|
4
|
+
|
|
5
|
+
import { recurseStringify } from './recurseStringify.mjs'
|
|
6
|
+
|
|
7
|
+
export const fontFileTypes = {
|
|
8
|
+
eot: url => `src: url('${url}.eot'); src: url('${url}.eot#iefix') format('embedded-opentype')`,
|
|
9
|
+
woff2: url => `url('${url}.woff2') format('woff2')`,
|
|
10
|
+
woff: url => `url('${url}.woff') format('woff')`,
|
|
11
|
+
ttf: url => `url('${url}.ttf') format('truetype')`,
|
|
12
|
+
svg: (url, family) => `url('${url}.svg#${family}') format('svg')`,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const fontV1 = (name, font) => {
|
|
16
|
+
log.warn('W_DEPRECATED', 'font name', font.family, 'is declared in a deprecated way.')
|
|
17
|
+
log('See: https://magic.github.io/css/#styles-webfonts for more information.')
|
|
18
|
+
|
|
19
|
+
let { family, url, types = 'woff2', weights = 400, styles = 'normal', ...rest } = font
|
|
20
|
+
|
|
21
|
+
if (!url.endsWith('/')) {
|
|
22
|
+
url += '/'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!is.array(weights)) {
|
|
26
|
+
weights = [weights]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!is.array(types)) {
|
|
30
|
+
types = [types]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!is.array(styles)) {
|
|
34
|
+
styles = [styles]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return weights.map(fontWeight => {
|
|
38
|
+
return styles.map(fontStyle => {
|
|
39
|
+
const weightStyleUrl = `${url}${family}-${fontWeight}-${fontStyle}`
|
|
40
|
+
|
|
41
|
+
let fontString = `${name} ${recurseStringify({
|
|
42
|
+
fontFamily: `'${family}'`,
|
|
43
|
+
fontStyle,
|
|
44
|
+
fontWeight,
|
|
45
|
+
...rest,
|
|
46
|
+
})}`
|
|
47
|
+
|
|
48
|
+
let fontFileString = 'src:'
|
|
49
|
+
if (types.includes('eot')) {
|
|
50
|
+
fontFileString = ''
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const fontFileStrings = []
|
|
54
|
+
Object.entries(fontFileTypes).map(([name, fn]) => {
|
|
55
|
+
if (types.includes(name)) {
|
|
56
|
+
const str = fn(weightStyleUrl, family)
|
|
57
|
+
fontFileStrings.push(str)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
fontFileString += fontFileStrings.join(',') + ';'
|
|
62
|
+
|
|
63
|
+
fontString = fontString.replace('}\n', `${fontFileString} }\n`)
|
|
64
|
+
return fontString
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const fontV2 = (name, font) => {
|
|
70
|
+
let { family, url, types = 'woff2', styles, ...rest } = font
|
|
71
|
+
|
|
72
|
+
if (!url.endsWith('/')) {
|
|
73
|
+
url += '/'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!is.array(types)) {
|
|
77
|
+
types = [types]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const fontStrings = Object.entries(styles).map(entry => {
|
|
81
|
+
const [fontStyle, weights] = entry
|
|
82
|
+
|
|
83
|
+
return Object.entries(weights).map(([fontWeight, local]) => {
|
|
84
|
+
const weightStyleUrl = `${url}${family}-${fontWeight}-${fontStyle}`
|
|
85
|
+
|
|
86
|
+
const fontFileStrings = []
|
|
87
|
+
|
|
88
|
+
let fontFileString = ''
|
|
89
|
+
if (types.includes('eot')) {
|
|
90
|
+
fontFileString = ''
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
local.forEach(l => {
|
|
94
|
+
fontFileStrings.push(`local('${l}')`)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
Object.entries(fontFileTypes).map(([name, fn]) => {
|
|
98
|
+
if (types.includes(name)) {
|
|
99
|
+
const str = fn(weightStyleUrl, family)
|
|
100
|
+
fontFileStrings.push(str)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
fontFileString += fontFileStrings.join(',')
|
|
105
|
+
|
|
106
|
+
const props = recurseStringify({
|
|
107
|
+
fontFamily: `'${family}'`,
|
|
108
|
+
fontStyle,
|
|
109
|
+
fontWeight,
|
|
110
|
+
src: fontFileString,
|
|
111
|
+
...rest,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const fontString = `${name} ${props}`
|
|
115
|
+
|
|
116
|
+
return fontString
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return deep.flatten(fontStrings).join('\n')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const fontFaces = ({ res, name, items }) => {
|
|
124
|
+
if (is.array(items)) {
|
|
125
|
+
const fontStrings = items.map(font => {
|
|
126
|
+
if (is.objectNative(font.styles)) {
|
|
127
|
+
return fontV2(name, font)
|
|
128
|
+
} else {
|
|
129
|
+
return fontV1(name, font)
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
return deep.flatten(fontStrings).join('\n')
|
|
134
|
+
} else {
|
|
135
|
+
const { fontFamily, fontDir = '', fontRoot, ...rest } = items
|
|
136
|
+
res = `${name} ${recurseStringify({ fontFamily: `'${fontFamily}'`, ...rest })}`
|
|
137
|
+
|
|
138
|
+
const eotString = `src: url('${fontDir}${fontFamily}.eot');`
|
|
139
|
+
|
|
140
|
+
const srcString = `${eotString} src: ${[
|
|
141
|
+
`url('${fontDir}${fontFamily}.eot#iefix') format('embedded-opentype')`,
|
|
142
|
+
`url('${fontDir}${fontFamily}.ttf') format('truetype')`,
|
|
143
|
+
`url('${fontDir}${fontFamily}.woff2') format('woff2')`,
|
|
144
|
+
`url('${fontDir}${fontFamily}.woff') format('woff')`,
|
|
145
|
+
`url('${fontDir}${fontFamily}.svg#${fontFamily}') format('svg');`,
|
|
146
|
+
].join(', ')}`
|
|
147
|
+
|
|
148
|
+
return res.replace('}\n', `${srcString} }\n`)
|
|
149
|
+
}
|
|
150
|
+
}
|
package/src/stringify/index.mjs
CHANGED
|
@@ -4,11 +4,34 @@ import autoprefixer from 'autoprefixer'
|
|
|
4
4
|
import parse from '../parse/index.mjs'
|
|
5
5
|
import recurseStringify from './recurseStringify.mjs'
|
|
6
6
|
|
|
7
|
+
import { fontFaces } from './fontFaces.mjs'
|
|
8
|
+
|
|
9
|
+
const keyframes = ({ name, items, plugins }) => `${name} { ${recurseStringify(items, plugins)} }\n`
|
|
10
|
+
const mediaqueries = ({ name, items, plugins }) =>
|
|
11
|
+
`${name} { ${recurseStringify(items, plugins)} }\n`
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* stringify the styles css object into a valid css string.
|
|
15
|
+
*/
|
|
7
16
|
const stringify = async (styles, opts = {}) => {
|
|
17
|
+
const { plugins = {} } = opts
|
|
18
|
+
|
|
19
|
+
plugins.stringify = {
|
|
20
|
+
'@font-face': fontFaces,
|
|
21
|
+
'@keyframes': keyframes,
|
|
22
|
+
'@media': mediaqueries,
|
|
23
|
+
...plugins.stringify,
|
|
24
|
+
}
|
|
25
|
+
|
|
8
26
|
const parsed = parse(styles, opts)
|
|
9
27
|
|
|
10
|
-
const stringified = recurseStringify(parsed)
|
|
28
|
+
const stringified = recurseStringify(parsed, plugins.stringify)
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* test the resulting css using postcss and autoprefix vendors where needed.
|
|
32
|
+
*/
|
|
11
33
|
const result = await postcss([autoprefixer]).process(stringified, { from: undefined })
|
|
34
|
+
|
|
12
35
|
result.warnings().forEach(warn => {
|
|
13
36
|
console.warn(warn.toString())
|
|
14
37
|
})
|
|
@@ -2,102 +2,24 @@ import is from '@magic/types'
|
|
|
2
2
|
|
|
3
3
|
import stringifyProps from './props.mjs'
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
if (is.array(
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
items.forEach(font => {
|
|
10
|
-
let { family, url, types = 'woff2', weights = 400, styles = 'normal', ...rest } = font
|
|
11
|
-
|
|
12
|
-
if (!url.endsWith('/')) {
|
|
13
|
-
url += '/'
|
|
14
|
-
}
|
|
15
|
-
if (!is.array(weights)) {
|
|
16
|
-
weights = [weights]
|
|
17
|
-
}
|
|
18
|
-
if (!is.array(styles)) {
|
|
19
|
-
styles = [styles]
|
|
20
|
-
}
|
|
21
|
-
if (!is.array(types)) {
|
|
22
|
-
types = [types]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
weights.forEach(fontWeight => {
|
|
26
|
-
styles.forEach(fontStyle => {
|
|
27
|
-
const weightStyleUrl = `${url}${family}-${fontWeight}-${fontStyle}`
|
|
28
|
-
|
|
29
|
-
let fontString = `${name} ${recurseStringify({
|
|
30
|
-
fontFamily: `"${family}"`,
|
|
31
|
-
fontStyle,
|
|
32
|
-
fontWeight,
|
|
33
|
-
...rest,
|
|
34
|
-
})}`
|
|
35
|
-
|
|
36
|
-
const fontFileTypes = {
|
|
37
|
-
eot: url =>
|
|
38
|
-
`src: url('${url}.eot'); src: url('${url}.eot#iefix') format('embedded-opentype')`,
|
|
39
|
-
ttf: url => `url('${url}.ttf') format('truetype')`,
|
|
40
|
-
woff: url => `url('${url}.woff') format('woff')`,
|
|
41
|
-
woff2: url => `url('${url}.woff2') format('woff2')`,
|
|
42
|
-
svg: url => `url('${url}.svg#${family}') format('svg')`,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
let fontFileString = 'src:'
|
|
46
|
-
if (types.includes('eot')) {
|
|
47
|
-
fontFileString = ''
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const fontFileStrings = []
|
|
51
|
-
Object.entries(fontFileTypes).map(([name, fn]) => {
|
|
52
|
-
if (types.includes(name)) {
|
|
53
|
-
const str = fn(weightStyleUrl)
|
|
54
|
-
fontFileStrings.push(str)
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
fontFileString += fontFileStrings.join(',') + ';'
|
|
59
|
-
|
|
60
|
-
fontString = fontString.replace('}\n', `${fontFileString} }\n`)
|
|
61
|
-
fontStrings.push(fontString)
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
return fontStrings.join('\n')
|
|
67
|
-
} else {
|
|
68
|
-
const { fontFamily, fontDir = '', fontRoot, ...rest } = items
|
|
69
|
-
res = `${name} ${recurseStringify({ fontFamily: `"${fontFamily}"`, ...rest })}`
|
|
70
|
-
|
|
71
|
-
const eotString = `src: url('${fontDir}${fontFamily}.eot');`
|
|
72
|
-
|
|
73
|
-
const srcString = `${eotString} src: ${[
|
|
74
|
-
`url('${fontDir}${fontFamily}.eot#iefix') format('embedded-opentype')`,
|
|
75
|
-
`url('${fontDir}${fontFamily}.ttf') format('truetype')`,
|
|
76
|
-
`url('${fontDir}${fontFamily}.woff') format('woff')`,
|
|
77
|
-
`url('${fontDir}${fontFamily}.woff2') format('woff2')`,
|
|
78
|
-
`url('${fontDir}${fontFamily}.svg#${fontFamily}') format('svg');`,
|
|
79
|
-
].join(', ')}`
|
|
80
|
-
|
|
81
|
-
return res.replace('}\n', `${srcString} }\n`)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const recurseStringify = mod => {
|
|
86
|
-
let res = mod
|
|
87
|
-
|
|
88
|
-
if (is.array(mod)) {
|
|
89
|
-
const [name, items] = mod
|
|
5
|
+
export const recurseStringify = (res, plugins = []) => {
|
|
6
|
+
if (is.array(res)) {
|
|
7
|
+
const [name, items] = res
|
|
90
8
|
if (is.string(name)) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
9
|
+
let result = ''
|
|
10
|
+
Object.entries(plugins).forEach(([lookup, fn]) => {
|
|
11
|
+
if (name.startsWith(lookup)) {
|
|
12
|
+
result = fn({ name, items, plugins })
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
if (result) {
|
|
16
|
+
return result
|
|
95
17
|
}
|
|
96
18
|
}
|
|
97
19
|
|
|
98
|
-
return
|
|
99
|
-
} else if (is.object(
|
|
100
|
-
return `{ ${stringifyProps(
|
|
20
|
+
return res.map(r => recurseStringify(r, plugins)).join(' ')
|
|
21
|
+
} else if (is.object(res)) {
|
|
22
|
+
return `{ ${stringifyProps(res)} }\n`
|
|
101
23
|
}
|
|
102
24
|
|
|
103
25
|
return res
|