diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:01:11 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:02:09 +0200 |
commit | 363723fc84f7b8477592e0105aeb331ec9a017af (patch) | |
tree | 29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/concordance/lib/themeUtils.js | |
parent | 5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff) |
node_modules
Diffstat (limited to 'node_modules/concordance/lib/themeUtils.js')
-rw-r--r-- | node_modules/concordance/lib/themeUtils.js | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/node_modules/concordance/lib/themeUtils.js b/node_modules/concordance/lib/themeUtils.js new file mode 100644 index 000000000..a0a64b586 --- /dev/null +++ b/node_modules/concordance/lib/themeUtils.js @@ -0,0 +1,195 @@ +'use strict' + +const cloneDeep = require('lodash.clonedeep') +const merge = require('lodash.merge') + +const pluginRegistry = require('./pluginRegistry') + +function freezeTheme (theme) { + const queue = [theme] + while (queue.length > 0) { + const object = queue.shift() + Object.freeze(object) + + for (const key of Object.keys(object)) { + const value = object[key] + if (value !== null && typeof value === 'object') { + queue.push(value) + } + } + } + + return theme +} + +const defaultTheme = freezeTheme({ + boolean: { open: '', close: '' }, + circular: '[Circular]', + date: { + invalid: 'invalid', + value: { open: '', close: '' } + }, + diffGutters: { + actual: '- ', + expected: '+ ', + padding: ' ' + }, + error: { + ctor: { open: '(', close: ')' }, + name: { open: '', close: '' } + }, + function: { + name: { open: '', close: '' }, + stringTag: { open: '', close: '' } + }, + global: { open: '', close: '' }, + item: { + after: ',', + customFormat: null, + increaseValueIndent: false + }, + list: { openBracket: '[', closeBracket: ']' }, + mapEntry: { + after: ',', + separator: ' => ' + }, + maxDepth: '…', + null: { open: '', close: '' }, + number: { open: '', close: '' }, + object: { + openBracket: '{', + closeBracket: '}', + ctor: { open: '', close: '' }, + stringTag: { open: '@', close: '' }, + secondaryStringTag: { open: '@', close: '' } + }, + property: { + after: ',', + customFormat: null, + keyBracket: { open: '[', close: ']' }, + separator: ': ', + increaseValueIndent: false + }, + regexp: { + source: { open: '/', close: '/' }, + flags: { open: '', close: '' }, + separator: '---' + }, + stats: { separator: '---' }, + string: { + open: '', + close: '', + line: { open: "'", close: "'", escapeQuote: "'" }, + multiline: { start: '`', end: '`', escapeQuote: '``' }, + controlPicture: { open: '', close: '' }, + diff: { + insert: { open: '', close: '' }, + delete: { open: '', close: '' }, + equal: { open: '', close: '' }, + insertLine: { open: '', close: '' }, + deleteLine: { open: '', close: '' } + } + }, + symbol: { open: '', close: '' }, + typedArray: { + bytes: { open: '', close: '' } + }, + undefined: { open: '', close: '' } +}) + +const pluginRefs = new Map() +pluginRefs.count = 0 +const normalizedPluginThemes = new Map() +function normalizePlugins (plugins) { + if (!Array.isArray(plugins) || plugins.length === 0) return null + + const refs = [] + const themes = [] + for (const fromPlugin of pluginRegistry.getThemes(plugins)) { + if (!pluginRefs.has(fromPlugin.name)) { + pluginRefs.set(fromPlugin.name, pluginRefs.count++) + } + + refs.push(pluginRefs.get(fromPlugin.name)) + themes.push(fromPlugin.theme) + } + + const ref = refs.join('.') + if (normalizedPluginThemes.has(ref)) { + return { + ref, + theme: normalizedPluginThemes.get(ref) + } + } + + const theme = freezeTheme(themes.reduce((acc, pluginTheme) => { + return merge(acc, pluginTheme) + }, cloneDeep(defaultTheme))) + normalizedPluginThemes.set(ref, theme) + return {ref, theme} +} + +const normalizedCache = new WeakMap() +function normalize (options) { + options = Object.assign({plugins: [], theme: null}, options) + + const normalizedPlugins = normalizePlugins(options.plugins) + if (!options.theme) { + return normalizedPlugins ? normalizedPlugins.theme : defaultTheme + } + + const entry = normalizedCache.get(options.theme) || {theme: null, withPlugins: new Map()} + if (!normalizedCache.has(options.theme)) normalizedCache.set(options.theme, entry) + + if (normalizedPlugins) { + if (entry.withPlugins.has(normalizedPlugins.ref)) { + return entry.withPlugins.get(normalizedPlugins.ref) + } + + const theme = freezeTheme(merge(cloneDeep(normalizedPlugins.theme), options.theme)) + entry.withPlugins.set(normalizedPlugins.ref, theme) + return theme + } + + if (!entry.theme) { + entry.theme = freezeTheme(merge(cloneDeep(defaultTheme), options.theme)) + } + return entry.theme +} +exports.normalize = normalize + +const modifiers = new WeakMap() +function addModifier (descriptor, modifier) { + if (modifiers.has(descriptor)) { + modifiers.get(descriptor).add(modifier) + } else { + modifiers.set(descriptor, new Set([modifier])) + } +} +exports.addModifier = addModifier + +const modifierCache = new WeakMap() +const originalCache = new WeakMap() +function applyModifiers (descriptor, theme) { + if (!modifiers.has(descriptor)) return theme + + return Array.from(modifiers.get(descriptor)).reduce((prev, modifier) => { + const cache = modifierCache.get(modifier) || new WeakMap() + if (!modifierCache.has(modifier)) modifierCache.set(modifier, cache) + + if (cache.has(prev)) return cache.get(prev) + + const modifiedTheme = cloneDeep(prev) + modifier(modifiedTheme) + freezeTheme(modifiedTheme) + cache.set(prev, modifiedTheme) + originalCache.set(modifiedTheme, theme) + return modifiedTheme + }, theme) +} +exports.applyModifiers = applyModifiers + +function applyModifiersToOriginal (descriptor, theme) { + return applyModifiers(descriptor, originalCache.get(theme) || theme) +} +exports.applyModifiersToOriginal = applyModifiersToOriginal |