aboutsummaryrefslogtreecommitdiff
path: root/src/services/theme_data/iss_deserializer.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/services/theme_data/iss_deserializer.js')
-rw-r--r--src/services/theme_data/iss_deserializer.js126
1 files changed, 113 insertions, 13 deletions
diff --git a/src/services/theme_data/iss_deserializer.js b/src/services/theme_data/iss_deserializer.js
index 431e1b94..3cd2f15f 100644
--- a/src/services/theme_data/iss_deserializer.js
+++ b/src/services/theme_data/iss_deserializer.js
@@ -1,24 +1,51 @@
+import { flattenDeep } from 'lodash'
+
+const parseShadow = string => {
+ const modes = ['_full', 'inset', 'x', 'y', 'blur', 'spread', 'color', 'alpha']
+ const regexPrep = [
+ // inset keyword (optional)
+ '^(?:(inset)\\s+)?',
+ // x
+ '(?:([0-9]+(?:\\.[0-9]+)?)\\s+)',
+ // y
+ '(?:([0-9]+(?:\\.[0-9]+)?)\\s+)',
+ // blur (optional)
+ '(?:([0-9]+(?:\\.[0-9]+)?)\\s+)?',
+ // spread (optional)
+ '(?:([0-9]+(?:\\.[0-9]+)?)\\s+)?',
+ // either hex, variable or function
+ '(#[0-9a-f]{6}|--[a-z\\-_]+|\\$[a-z\\-()_]+)',
+ // opacity (optional)
+ '(?:\\s+\\/\\s+([0-9]+(?:\\.[0-9]+)?)\\s*)?$'
+ ].join('')
+ const regex = new RegExp(regexPrep, 'gis') // global, (stable) indices, single-string
+ const result = regex.exec(string)
+ if (result == null) {
+ return string
+ } else {
+ return Object.fromEntries(modes.map((mode, i) => [mode, result[i]]))
+ }
+}
// this works nearly the same as HTML tree converter
-export const deserialize = (input) => {
- const buffer = []
+const parseIss = (input) => {
+ const buffer = [{ selector: null, content: [] }]
let textBuffer = ''
const getCurrentBuffer = () => {
- let current = buffer[buffer.length - 1][1]
+ let current = buffer[buffer.length - 1]
if (current == null) {
- current = { name: null, content: [] }
+ current = { selector: null, content: [] }
}
- buffer.push(current)
return current
}
// Processes current line buffer, adds it to output buffer and clears line buffer
- const flushText = (content) => {
+ const flushText = (kind) => {
if (textBuffer === '') return
- if (content) {
- getCurrentBuffer().content.push(textBuffer)
+ if (kind === 'content') {
+ getCurrentBuffer().content.push(textBuffer.trim())
} else {
- getCurrentBuffer().name = textBuffer
+ getCurrentBuffer().selector = textBuffer.trim()
}
textBuffer = ''
}
@@ -27,17 +54,90 @@ export const deserialize = (input) => {
const char = input[i]
if (char === ';') {
- flushText(true)
+ flushText('content')
} else if (char === '{') {
- flushText(false)
+ flushText('header')
} else if (char === '}') {
- buffer.push({ name: null, content: [] })
+ flushText('content')
+ buffer.push({ selector: null, content: [] })
textBuffer = ''
} else {
textBuffer += char
}
}
- flushText()
return buffer
}
+export const deserialize = (input) => {
+ const ast = parseIss(input)
+ const finalResult = ast.filter(i => i.selector != null).map(item => {
+ const { selector, content } = item
+ let stateCount = 0
+ const selectors = selector.split(/,/g)
+ const result = selectors.map(selector => {
+ const output = { component: '' }
+ let currentDepth = null
+
+ selector.split(/ /g).reverse().forEach((fragment, index, arr) => {
+ const fragmentObject = { component: '' }
+
+ let mode = 'component'
+ for (let i = 0; i < fragment.length; i++) {
+ const char = fragment[i]
+ switch (char) {
+ case '.': {
+ mode = 'variant'
+ fragmentObject.variant = ''
+ break
+ }
+ case ':': {
+ mode = 'state'
+ fragmentObject.state = fragmentObject.state || []
+ stateCount++
+ break
+ }
+ default: {
+ if (mode === 'state') {
+ const currentState = fragmentObject.state[stateCount - 1]
+ if (currentState == null) {
+ fragmentObject.state.push('')
+ }
+ fragmentObject.state[stateCount - 1] += char
+ } else {
+ fragmentObject[mode] += char
+ }
+ }
+ }
+ }
+ if (currentDepth !== null) {
+ currentDepth.parent = { ...fragmentObject }
+ currentDepth = currentDepth.parent
+ } else {
+ Object.keys(fragmentObject).forEach(key => {
+ output[key] = fragmentObject[key]
+ })
+ if (index !== (arr.length - 1)) {
+ output.parent = { component: '' }
+ }
+ currentDepth = output
+ }
+ })
+
+ output.directives = Object.fromEntries(content.map(d => {
+ const [property, value] = d.split(':')
+ console.log(property, value)
+ let realValue = value.trim()
+ if (property === 'shadow') {
+ realValue = parseShadow(value.split(',').map(v => v.trim()))
+ } if (!Number.isNaN(Number(value))) {
+ realValue = Number(value)
+ }
+ return [property, realValue]
+ }))
+
+ return output
+ })
+ return result
+ })
+ return flattenDeep(finalResult)
+}