UNPKG

css-kits

Version:

Parse css to javascript object. Support change class and id

261 lines (260 loc) 9.62 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "./helpful"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.splitAtRuleBlock = exports.splitSelectors = exports.splitDeclarationBlock = exports.splitRuleSetBlock = exports.splitIntoBlocks = void 0; const helpful_1 = require("./helpful"); function findFirstIndexOfOpenBrace(subject) { let result = null; (0, helpful_1.styleForEach)({ subject, callbackFn: (e) => { if (e.value === '{') { result = e.index; e.breakForEach(); } }, }); return result; } function splitIntoBlocks(subject) { const result = []; let deep = 0; let lastIndex = 0; let isInsideOfAtRule = false; const resultPush = (index) => { result.push({ start: lastIndex, end: index + 1, }); lastIndex = index + 1; isInsideOfAtRule = false; }; (0, helpful_1.styleForEach)({ subject, callbackFn: ({ index: i, value: currentLetter }) => { switch (currentLetter) { case '{': { deep++; return; } case '}': { deep--; if (deep > 0) return; if (deep === 0) { resultPush(i); return; } throw new SyntaxError(subject.slice(i - 10, i + 10)); } case '@': { if (deep > 0) return; if (isInsideOfAtRule === false) { isInsideOfAtRule = true; return; } throw new SyntaxError(`Syntax is error at ${i}. "${subject.substring(i - 5, 10)}"`); } case ';': { if (deep > 0) return; resultPush(i); return; } } }, }); return result; } exports.splitIntoBlocks = splitIntoBlocks; /** * * @param subject look like ".header { display: block; background-color: blue; color: aqua; }" * @returns [selectors, block]; */ function splitRuleSetBlock(subject) { const indexOfOpenBrace = findFirstIndexOfOpenBrace(subject); if (!indexOfOpenBrace || indexOfOpenBrace === 0 || indexOfOpenBrace === subject.length - 1) { throw new SyntaxError(subject); } const selectors = subject.slice(0, indexOfOpenBrace).trim(); if (selectors.length === 0) { throw new SyntaxError(subject.slice(0, 30)); } const block = subject.slice(indexOfOpenBrace).trim(); return [selectors, block]; } exports.splitRuleSetBlock = splitRuleSetBlock; function splitDeclarationBlock(subject) { if (!subject.startsWith('{') || !subject.endsWith('}')) { throw new SyntaxError(subject); } const standardSubject = subject.slice(1, -1).trim(); const results = []; let hasColon = false; let allOkays = true; let lastIndex = 0; (0, helpful_1.styleForEach)({ subject: standardSubject, callbackFn: (e) => { switch (e.value) { case ':': { hasColon = true; return; } case ';': { if (!hasColon) { allOkays = false; e.breakForEach(); return; } results.push(standardSubject.slice(lastIndex, e.index)); lastIndex = e.index + 1; hasColon = false; return; } } }, }); if (!allOkays) { throw new SyntaxError(subject); } if (lastIndex < standardSubject.length) { if (!hasColon) { allOkays = false; throw new SyntaxError(subject); } results.push(standardSubject.slice(lastIndex, standardSubject.length)); } return results.map((item) => item.trim()); } exports.splitDeclarationBlock = splitDeclarationBlock; function splitSelectors(subject) { const ranges = []; let lastIndex = 0; let attributeDeep = 0; let functionDeep = 0; const pushRange = (index) => { ranges.push({ start: lastIndex, end: index, }); lastIndex = index + 1; }; (0, helpful_1.styleForEach)({ subject, callbackFn: ({ value: currentLetter, index: i }) => { switch (currentLetter) { case ',': { if (attributeDeep > 0 || functionDeep > 0) return; return pushRange(i); } case '(': { if (attributeDeep > 0) return; functionDeep += 1; return; } case ')': { if (attributeDeep > 0) return; functionDeep -= 1; if (functionDeep < 0) { throw new SyntaxError(`Extra characters after close-brace "${subject.substring(i - 5, 20)}"`); } return; } case '[': { attributeDeep += 1; return; } case ']': { attributeDeep -= 1; if (attributeDeep < 0) { throw new SyntaxError(`Extra characters after close-bracket "${subject.substring(i - 5, 20)}"`); } return; } } }, }); if (lastIndex < subject.length) { pushRange(subject.length); } const result = []; ranges.forEach(({ start, end }) => { if (end <= start) return; const tmp = subject.slice(start, end).trim(); if (tmp.length === 0) return; result.push(tmp); }); return result; } exports.splitSelectors = splitSelectors; /** * * @param subject It look like "@media screen and (max-width: 100px) { .test-media { display: block; background-color: blue; } }" */ function splitAtRuleBlock(subject) { if (subject.length === 0) { throw new SyntaxError('Empty string'); } if (!subject.startsWith('@')) { throw new SyntaxError(`${subject}`); } const lastCharacter = subject[subject.length - 1]; if (!(lastCharacter === ';' || lastCharacter === '}')) { throw new SyntaxError(`${subject}`); } const firstIndexOfSpace = subject.indexOf(' '); const identifier = subject.slice(1, firstIndexOfSpace).trim(); if (identifier.length === 0) { throw new SyntaxError(`${subject}`); } const rest = subject.slice(firstIndexOfSpace).trim(); if (rest.length === 0) { throw new SyntaxError(`${subject}`); } const result = { identifier, rule: '', block: null, }; switch (lastCharacter) { case ';': { result.rule = rest.slice(0, -1).trim(); result.block = null; break; } case '}': { const firstIndexOfOpenBrace = findFirstIndexOfOpenBrace(rest); if (!firstIndexOfOpenBrace || firstIndexOfOpenBrace === 0) { throw new SyntaxError(`${subject}`); } result.rule = rest.slice(0, firstIndexOfOpenBrace).trim(); result.block = rest.slice(firstIndexOfOpenBrace).trim(); break; } default: { throw new SyntaxError(`${subject}`); } } if (result.rule.length === 0) { throw new SyntaxError(`${subject}`); } return result; } exports.splitAtRuleBlock = splitAtRuleBlock; });