JSFiddle - React, Tailwind, and code Playground
by Константин Дралюк
HTML
<textarea name="" id="pug" cols="100" rows="15">+b.about
+e.container.container--new.-test.-test2.-test_1.container
+e.container.container.-test2231.-test
.col-two-third
+e.header
+b.about-header.about-header--new.-test
+e.H2.title Anti Age
+e.subtitle Новая летняя детокс-программа
+e.description Фантастическое омоложение за 3 дня!</textarea>
<textarea name="" id="sass" cols="100" rows="15"></textarea>
JavaScript
const getStartOffset = line => {
return line.length - line.trimStart().length
}
const removeOffset = text => {
const lines = text.split('\n')
const firstLine = lines.find(line => /\b/.test(line))
return lines.map(line => line.slice(getStartOffset(firstLine))).join('\n')
}
const removeLinesChunks = lines => {
return lines.filter(line => {
return /^\+b|\+e/.test(line.trim())
})
}
const textToLines = text => {
const lines = text.split('\n')
return removeLinesChunks(lines)
}
const buildBlocks = lines => {
const blocks = []
const items = []
const clearLine = line => {
let clearedLine = line.trim().replace(/\(.*\)/, '').replace(/( |!).*$/, '')
return clearedLine
}
const buildItem = line => {
let lineArray = clearLine(line).split('.')
const hasTag = lineArray[1].toUpperCase() === lineArray[1]
if (hasTag) {
lineArray = [...lineArray.slice(0, 1), ...lineArray.slice(2)]
}
const type = /^\+b/.test(line.trim()) ? 'block' : 'element'
const name = lineArray[1]
const modifiers = lineArray.filter(prop => {
const RE = new RegExp(`^-|${name}--`)
return RE.test(prop)
})
return {type, name, line, modifiers}
}
const buildItems = lines.map(line => {
const item = buildItem(line)
const parent = [...items].reverse().find(item =>
item.type === 'block' &&
getStartOffset(line) > getStartOffset(item.line)
)
item.parent = parent ? parent.name : null
const firstInstance = items.find(_item => _item.name === item.name && (parent && _item.parent === item.parent))
if (firstInstance) {
firstInstance.modifiers.push(...item.modifiers)
}
items.push(item)
return line
})
const getModifiers = (item) => {
return [...new Set(item.modifiers)].sort((current, next) => {
if (/^-/.test(current)) {
return -1
} else {
return 1
}
}).map(modifier => {
if (/^-/.test(modifier)) {
return...