diff options
Diffstat (limited to 'src/services/theme_data/iss_deserializer.js')
| -rw-r--r-- | src/services/theme_data/iss_deserializer.js | 126 |
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) +} |
