diff --git a/assets/scripts/util.js b/assets/scripts/util.js index a0336ad..a9eddba 100644 --- a/assets/scripts/util.js +++ b/assets/scripts/util.js @@ -1,6 +1,6 @@ // 设置自定义颜色 function setColorWithTemplate(template) { - return function(color) { + return function (color) { let custom_theme = JSON.parse(JSON.stringify(template)); custom_theme.block.h1['border-bottom'] = `2px solid ${color}`; custom_theme.block.h2['background'] = color; @@ -14,7 +14,7 @@ function setColorWithTemplate(template) { let setColor = setColorWithTemplate(default_theme); function customCssWithTemplate(template) { - return function(jsonString) { + return function (jsonString) { let custom_theme = JSON.parse(JSON.stringify(template)); custom_theme.block.h1 = jsonString.h1; custom_theme.block.h2 = jsonString.h2; @@ -26,3 +26,83 @@ function customCssWithTemplate(template) { } let customCss = customCssWithTemplate(default_theme); + +// css转json +function css2json(css) { + + // Remove all comments from the css-file + while ((open = css.indexOf("/*")) !== -1 && + (close = css.indexOf("*/")) !== -1) { + css = css.substring(0, open) + css.substring(close + 2); + } + + // Initialize the return value _json_. + let json = {}; + + // Each rule gets parsed and then removed from _css_ until all rules have been + // parsed. + while (css.length > 0) { + // Save the index of the first left bracket and first right bracket. + const lbracket = css.indexOf('{'); + const rbracket = css.indexOf('}'); + + // ## Part 1: The declarations + // + // Transform the declarations to an object. For example, the declarations
+ // `font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;`
+ // result in the object
+ // `{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}`. + + // Helper method that transform an array to a object, by splitting each + // declaration (_font: Arial_) into key (_font_) and value(_Arial_). + function toObject(array) { + let ret = {}; + array.forEach(e => { + const index = e.indexOf(':'); + const property = e.substring(0, index).trim(); + const value = e.substring(index + 1).trim(); + ret[property] = value; + }); + return ret; + } + + // Split the declaration block of the first rule into an array and remove + // whitespace from each declaration. + let declarations = css.substring(lbracket + 1, rbracket) + .split(";") + .map(e => e.trim()) + .filter(e => e.length > 0); // Remove any empty ("") values from the array + + // _declaration_ is now an array reado to be transformed into an object. + declarations = toObject(declarations); + + // ## Part 2: The selectors + // + // Each selector in the selectors block will be associated with the + // declarations defined above. For example, `h1, p#bar {color: red}`
+ // result in the object
+ // {"h1": {color: red}, "p#bar": {color: red}} + + // Split the selectors block of the first rule into an array and remove + // whitespace, e.g. `"h1, p#bar, span.foo"` get parsed to + // `["h1", "p#bar", "span.foo"]`. + let selectors = css.substring(0, lbracket) + .split(",") + .map(selector => selector.trim()); + + // Iterate through each selector from _selectors_. + selectors.forEach(selector => { + // Initialize the json-object representing the declaration block of + // _selector_. + if (!json[selector]) json[selector] = {}; + // Save the declarations to the right selector + Object.keys(declarations).forEach(key => { + json[selector][key] = declarations[key]; + }); + }); + // Continue to next instance + css = css.slice(rbracket + 1).trim() + } + // return the json data + return json; +} diff --git a/index.html b/index.html index d485cb6..18bab43 100644 --- a/index.html +++ b/index.html @@ -131,9 +131,8 @@ - - + diff --git a/libs/scripts/FuriganaMD.js b/libs/scripts/FuriganaMD.js deleted file mode 100644 index 93abc5a..0000000 --- a/libs/scripts/FuriganaMD.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * 注音功能来自于:https://github.com/amclees/furigana-markdown - * 详见上述文档 - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.FuriganaMD = factory()); -}(this, (function () { - 'use strict'; - - // This function escapes special characters for use in a regex constructor. - function escapeForRegex(string) { - return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } - - function emptyStringFilter(block) { - return block !== ''; - } - - const kanjiRange = '\\u4e00-\\u9faf'; - const kanjiBlockRegex = new RegExp(`[${kanjiRange}]+`, 'g'); - const nonKanjiBlockRegex = new RegExp(`[^${kanjiRange}]+`, 'g'); - const kanaWithAnnotations = '\\u3041-\\u3095\\u3099-\\u309c\\u3081-\\u30fa\\u30fc'; - const furiganaSeperators = '..。・'; - const seperatorRegex = new RegExp(`[${furiganaSeperators}]`, 'g'); - - const singleKanjiRegex = new RegExp(`^[${kanjiRange}]$`); - - function isKanji(character) { - return character.match(singleKanjiRegex); - } - - const innerRegexString = '(?:[^\\u0000-\\u007F]|\\w)+'; - - let regexList = []; - let previousFuriganaForms = ''; - - function updateRegexList(furiganaForms) { - previousFuriganaForms = furiganaForms; - let formArray = furiganaForms.split('|'); - if (formArray.length === 0) { - formArray = ['[]:^:()']; - } - regexList = formArray.map(form => { - let furiganaComponents = form.split(':'); - if (furiganaComponents.length !== 3) { - furiganaComponents = ['[]', '^', '()']; - } - const mainBrackets = furiganaComponents[0]; - const seperator = furiganaComponents[1]; - const furiganaBrackets = furiganaComponents[2]; - return new RegExp( - escapeForRegex(mainBrackets[0]) + - '(' + innerRegexString + ')' + - escapeForRegex(mainBrackets[1]) + - escapeForRegex(seperator) + - escapeForRegex(furiganaBrackets[0]) + - '(' + innerRegexString + ')' + - escapeForRegex(furiganaBrackets[1]), - 'g' - ); - }); - } - - let autoRegexList = []; - let previousAutoBracketSets = ''; - - function updateAutoRegexList(autoBracketSets) { - previousAutoBracketSets = autoBracketSets; - autoRegexList = autoBracketSets.split('|').map(brackets => { - /* - Sample built regex: - /(^|[^\u4e00-\u9faf]|)([\u4e00-\u9faf]+)([\u3041-\u3095\u3099-\u309c\u3081-\u30fa\u30fc]*)【((?:[^【】\u4e00-\u9faf]|w)+)】/g - */ - return new RegExp( - `(^|[^${kanjiRange}]|)` + - `([${kanjiRange}]+)` + - `([${kanaWithAnnotations}]*)` + - escapeForRegex(brackets[0]) + - `((?:[^${escapeForRegex(brackets)}\\u0000-\\u007F]|\\w|[${furiganaSeperators}])+)` + - escapeForRegex(brackets[1]), - 'g' - ); - }); - } - - let replacementTemplate = ''; - let replacementBrackets = ''; - - function updateReplacementTemplate(furiganaFallbackBrackets) { - if (furiganaFallbackBrackets.length !== 2) { - furiganaFallbackBrackets = '【】'; - } - replacementBrackets = furiganaFallbackBrackets; - replacementTemplate = `$1${furiganaFallbackBrackets[0]}$2${furiganaFallbackBrackets[1]}`; - } - - updateReplacementTemplate('【】'); - - function addFurigana(text, options) { - if (options.furiganaForms !== previousFuriganaForms) { - updateRegexList(options.furiganaForms); - } - if (options.furiganaFallbackBrackets !== replacementBrackets) { - updateReplacementTemplate(options.furiganaFallbackBrackets); - } - regexList.forEach(regex => { - text = text.replace(regex, (match, wordText, furiganaText, offset, mainText) => { - if (match.indexOf('\\') === -1 && mainText[offset - 1] !== '\\') { - if ((!options.furiganaPatternMatching) || wordText.search(kanjiBlockRegex) === -1 || wordText[0].search(kanjiBlockRegex) === -1) { - return replacementTemplate.replace('$1', wordText).replace('$2', furiganaText); - } else { - let originalFuriganaText = (' ' + furiganaText).slice(1); - let nonKanji = wordText.split(kanjiBlockRegex).filter(emptyStringFilter); - let kanji = wordText.split(nonKanjiBlockRegex).filter(emptyStringFilter); - let replacementText = ''; - let lastUsedKanjiIndex = 0; - if (nonKanji.length === 0) { - return replacementTemplate.replace('$1', wordText).replace('$2', furiganaText); - } - - nonKanji.forEach((currentNonKanji, index) => { - if (furiganaText === undefined) { - if (index < kanji.length) { - replacementText += kanji[index]; - } - - replacementText += currentNonKanji; - return; - } - let splitFurigana = furiganaText.split(new RegExp(escapeForRegex(currentNonKanji) + '(.*)')).filter(emptyStringFilter); - - lastUsedKanjiIndex = index; - replacementText += replacementTemplate.replace('$1', kanji[index]).replace('$2', splitFurigana[0]); - replacementText += currentNonKanji; - - furiganaText = splitFurigana[1]; - }); - if (furiganaText !== undefined && lastUsedKanjiIndex + 1 < kanji.length) { - replacementText += replacementTemplate.replace('$1', kanji[lastUsedKanjiIndex + 1]).replace('$2', furiganaText); - } else if (furiganaText !== undefined) { - return replacementTemplate.replace('$1', wordText).replace('$2', originalFuriganaText); - } else if (lastUsedKanjiIndex + 1 < kanji.length) { - replacementText += kanji[lastUsedKanjiIndex + 1]; - } - return replacementText; - } - } else { - return match; - } - }); - }); - - if (!options.furiganaStrictMode) { - if (options.furiganaAutoBracketSets !== previousAutoBracketSets) { - updateAutoRegexList(options.furiganaAutoBracketSets); - } - autoRegexList.forEach(regex => { - text = text.replace(regex, (match, preWordTerminator, wordKanji, wordKanaSuffix, furiganaText, offset, mainText) => { - if (match.indexOf('\\') === -1) { - if (options.furiganaPatternMatching) { - let rubies = []; - - let furigana = furiganaText; - - let stem = (' ' + wordKanaSuffix).slice(1); - for (let i = furiganaText.length - 1; i >= 0; i--) { - if (wordKanaSuffix.length === 0) { - furigana = furiganaText.substring(0, i + 1); - break; - } - if (furiganaText[i] !== wordKanaSuffix.slice(-1)) { - furigana = furiganaText.substring(0, i + 1); - break; - } - wordKanaSuffix = wordKanaSuffix.slice(0, -1); - } - - if (furiganaSeperators.split('').reduce( - (noSeperator, seperator) => { - return noSeperator && (furigana.indexOf(seperator) === -1); - }, - true - )) { - rubies = [replacementTemplate.replace('$1', wordKanji).replace('$2', furigana)]; - } else { - let kanaParts = furigana.split(seperatorRegex); - let kanji = wordKanji.split(''); - if (kanaParts.length === 0 || kanaParts.length > kanji.length) { - rubies = [replacementTemplate.replace('$1', wordKanji).replace('$2', furigana)]; - } else { - for (let i = 0; i < kanaParts.length - 1; i++) { - if (kanji.length === 0) { - break; - } - rubies.push(replacementTemplate.replace('$1', kanji.shift()).replace('$2', kanaParts[i])); - } - let lastKanaPart = kanaParts.pop(); - rubies.push(replacementTemplate.replace('$1', kanji.join('')).replace('$2', lastKanaPart)); - } - } - - return preWordTerminator + rubies.join('') + stem; - } else { - return preWordTerminator + replacementTemplate.replace('$1', wordKanji).replace('$2', furiganaText) + wordKanaSuffix; - } - } else { - return match; - } - }); - }); - } - return text; - } - - function handleEscapedSpecialBrackets(text) { - // By default 【 and 】 cannot be escaped in markdown, this will remove backslashes from in front of them to give that effect. - return text.replace(/\\([【】])/g, '$1'); - } - - let FuriganaMD = {}; - FuriganaMD.register = function (renderer) { - renderer.text = function (text) { - let options = { - furigana: true, - furiganaForms: "()::{}", - furiganaFallbackBrackets: "{}", - furiganaStrictMode: false, - furiganaAutoBracketSets: "{}", - furiganaPatternMatching: true, - }; - // console.log('override text render',text); - // console.log('after add',addFurigana(text, options)); - return handleEscapedSpecialBrackets(addFurigana(text, options)); - }; - }; - - return FuriganaMD; - -})));