This repository has been archived by the owner on Jul 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
127 lines (106 loc) · 3.51 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* eslint-disable no-unused-vars */
const postcss = require('postcss')
const parser = require('postcss-selector-parser')
const objectPath = require('object-path')
const clone = require('clone')
const util = require('./util')
const save = require('./save')
const toJs = require('./toJs')
const DEFAULT_ELEMENT = '__'
const DEFAULT_MODIFIER = '--'
const beginsWith = (haystack, needle) => haystack.indexOf(needle) === 0
module.exports = postcss.plugin('postcss-bemit-to-json', (o) => {
const opts = o || {}
const optPrefixMap = opts.prefixMap
const optReplace = opts.replace || {}
const getJs = opts.getJs || save
const prefixKeys = optPrefixMap && Object.keys(optPrefixMap)
const edel = DEFAULT_ELEMENT
const mdel = DEFAULT_MODIFIER
const ejsdel = '_'
const mjsdel = '$'
return (root, result) => {
const output = {
}
const classNames = {}
const processReplace = (str) => {
let out = str
Object.keys(optReplace).forEach((key) => {
out = out.replace(key, optReplace[key])
})
return out
}
const elementKeyTransform = str => processReplace(util.toCamelCase(str))
const blockKeyTransform = str => processReplace(util.toUpperCamelCase(str))
const unescape = str => str.replace(/\\/g, '')
const sanitise = str => unescape(str).replace('-', '')
const setOutput = (inputPath, value) => {
const path = inputPath
let prefix = ''
if (optPrefixMap && path && path.length > 0) {
prefixKeys.forEach((key) => {
if (beginsWith(path[0], key)) {
path[0] = path[0].substr(key.length)
prefix = optPrefixMap[key]
}
})
}
const transformedPath = path.map((p, i) =>
sanitise(i === 0 ?
`${prefix}${blockKeyTransform(p)}` :
elementKeyTransform(p)))
objectPath.set(output, transformedPath, unescape(value))
}
const processClassNode = (classNode) => {
const className = classNode.value
if (!classNames[className]) {
classNames[className] = className
const eloc = className.indexOf(edel)
const mloc = className.indexOf(mdel)
if (eloc > 0) {
if (mloc > eloc) {
// Element with modifier
const [block, element, modifier] = [
className.substr(0, eloc),
className.substr(
eloc + edel.length,
mloc - eloc - edel.length
),
className.substr(mloc + mdel.length)
]
setOutput(
[block, element, `$${modifier}`],
`${block}${edel}${element} ${className}`
)
} else {
// Element with no modifier
const [block, element] = className.split(edel)
setOutput(
[block, element, '$'],
className
)
}
} else if (mloc > 0) {
// Block with modifier
const [block, modifier] = className.split(mdel)
setOutput(
[block, `$${modifier}`],
`${block} ${className}`
)
} else {
// Block with no modifier
const bkey = className
setOutput(
[className, '$'],
className
)
}
}
}
const processor = selectors =>
selectors.walkClasses(processClassNode)
const selectorProcessor = parser(processor)
root.walkRules(rule => selectorProcessor.process(rule))
return getJs(root.source.input.file, output, toJs(output))
}
})