diff --git a/.github/workflows/build-grammars.yml b/.github/workflows/build-grammars.yml
new file mode 100644
index 0000000..ec56456
--- /dev/null
+++ b/.github/workflows/build-grammars.yml
@@ -0,0 +1,28 @@
+name: Update grammars
+
+on: [ workflow_dispatch ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [18.x]
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - run: npm install
+ - run: npm start
+ - name: Upload a Build Artifact
+ uses: actions/upload-artifact@v3.1.3
+ with:
+ name: grammars.dat
+ path: ./libprisma/grammars.dat
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v5
+ with:
+ commit-message: Update grammars
+ title: Update grammars
+ branch: update-grammars
diff --git a/.gitignore b/.gitignore
index 9491a2f..addd40b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,8 @@ bld/
# Visual Studio 2015/2017 cache/options directory
.vs/
+# Webstorm cache directory
+.idea/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
@@ -360,4 +362,4 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
-FodyWeavers.xsd
\ No newline at end of file
+FodyWeavers.xsd
diff --git a/README.md b/README.md
index eef8eda..f5e307f 100644
--- a/README.md
+++ b/README.md
@@ -28,12 +28,12 @@ for (auto it = tokens.begin(); it != tokens.end(); ++it)
```
### How to update
-As mentioned, grammars dictionary is generated starting from prism.js source code.
-Currently, this is done manually by visiting prism's [test drive](https://prismjs.com/test.html).
-Once on the page, it is necessary to select all the languages, open the browser console and paste in both `isEqual.js` and `generate.js`.
-After a few seconds, the file `grammars.dat` will be downloaded.
-
-TODO: would be great to automate this step, or at least to make the script auto-execute rather to require all the user input.
+Run
+```sh
+npm install
+npm start
+```
+The new version of `grammars.dat` will appear in the `libprisma/grammars.dat`.
### Supported languages
| Language | Aliases |
diff --git a/generate.js b/generate.js
index e25e1cc..e43deaa 100644
--- a/generate.js
+++ b/generate.js
@@ -1,25 +1,18 @@
+const fs = require('fs')
+const isEqual = require('lodash.isequal')
+
const SCRIPTS = {}
+const include = function (src) {
+ // Some black magic of eval. Load the script from src to global scope. Source: https://stackoverflow.com/a/23699187/17140794
+ (1, eval)(src.toString())
+}
-const loadScript = src => new Promise(resolve => {
- const script = document.createElement('script')
- script.type = 'text/javascript'
- script.src = src
- script.onload = script.onreadystatechange = function () {
- if (resolve && (!this.readyState || this.readyState == 'complete')) {
- resolve()
- resolve = null
- }
- }
- script.onerror = e => {
- console.error(src, e);
- if (resolve) {
- resolve()
- resolve = null
- }
- }
- document.body.appendChild(script)
- return script
- })
+
+async function loadScript(src) {
+ const script = await fetch(src)
+ const text = await script.text()
+ include(text)
+}
async function loadLanguages(lngs) {
if (lngs) {
@@ -30,7 +23,7 @@ async function loadLanguages(lngs) {
}
}
}
-
+let langNumber = 0
async function loadLanguage(lng) {
if (!components.languages[lng].title) {
return
@@ -43,33 +36,36 @@ async function loadLanguage(lng) {
if (!SCRIPTS[lng]) {
SCRIPTS[lng] = true
+ langNumber += 1
+ console.log(`${langNumber} | Loading ${lng}`);
// TODO: version should probably not be hardcoded
+
await loadScript(`https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-${lng}.min.js`)
}
}
function unique(a, fn) {
if (a.length === 0 || a.length === 1) {
- return a;
+ return a;
}
if (!fn) {
- return a;
+ return a;
}
-
+
for (let i = 0; i < a.length; i++) {
- for (let j = i + 1; j < a.length; j++) {
- if (fn(a[i], a[j])) {
- a.splice(i, 1);
+ for (let j = i + 1; j < a.length; j++) {
+ if (fn(a[i], a[j])) {
+ a.splice(i, 1);
+ }
}
- }
}
return a;
- }
+}
function uniqlo(a, fn) {
var size = a.length;
- do{
+ do {
size = a.length
a = unique(a, fn)
}
@@ -77,327 +73,340 @@ function uniqlo(a, fn) {
return a
}
-var tempPatterns = []
-var tempLanguages = {}
+async function generate() {
-var tempTokens = []
-var tempGrammars = []
+ var tempPatterns = []
+ var tempLanguages = {}
+ var tempTokens = []
+ var tempGrammars = []
+ var weak = new WeakMap
-var weak = new WeakMap
+ function flatten(grammar) {
+ var keys = {}
-function flatten(grammar) {
- var keys = {}
+ var cache = weak.get(grammar)
+ if (cache !== undefined) {
+ return cache
+ }
- var cache = weak.get(grammar)
- if (cache !== undefined) {
- return cache
- }
+ weak.set(grammar, keys)
- weak.set(grammar, keys)
+ var copy = grammar;
+ var rest = copy.rest;
+ if (rest) {
+ copy = {}
- var copy = grammar;
- var rest = copy.rest;
- if (rest) {
- copy = {}
+ Object.keys(grammar).forEach(name => {
+ copy[name] = grammar[name]
+ })
- Object.keys(grammar).forEach(name => {
- copy[name] = grammar[name]
- })
+ for (var token in rest) {
+ copy[token] = rest[token];
+ }
- for (var token in rest) {
- copy[token] = rest[token];
+ delete copy.rest;
}
- delete copy.rest;
- }
+ function sanitize(pattern) {
+ // Unsupported:
+ // UTF-16 ranges
+ // [^] => [\s\S] <- matches any character, including new line
+ // [] => ?? <- matches _empty_ string
- function sanitize(pattern) {
- // Unsupported:
- // UTF-16 ranges
- // [^] => [\s\S] <- matches any character, including new line
- // [] => ?? <- matches _empty_ string
+ // All the whitelisted languages have 0xFFFF as maximum range
+ // This is not the case for all the grammars supported by Prisma.
- // All the whitelisted languages have 0xFFFF as maximum range
- // This is not the case for all the grammars supported by Prisma.
+ pattern = pattern.replaceAll("\\uFFFF", "\\xFF");
+ pattern = pattern.replaceAll("[^]", "[\\s\\S]");
- pattern = pattern.replaceAll("\\uFFFF", "\\xFF");
- pattern = pattern.replaceAll("[^]", "[\\s\\S]");
+ // TODO: This just bruteforces the regex to work, but of course
+ // result may vary from the original one.
+ //static const boost::regex hex(R"(\\u([0-9a-fA-F]{4}))");
+ //pattern = boost::regex_replace(pattern, hex, R"(\\xFF)");
- // TODO: This just bruteforces the regex to work, but of course
- // result may vary from the original one.
- //static const boost::regex hex(R"(\\u([0-9a-fA-F]{4}))");
- //pattern = boost::regex_replace(pattern, hex, R"(\\xFF)");
+ // TODO: Again, none of the whitelisted languages use [], but others do.
+ // Howhever, it is unclear to me how [] is supposed to work.
+ pattern = pattern.replaceAll("|[])", ")");
+ pattern = pattern.replaceAll(":[]", ":");
- // TODO: Again, none of the whitelisted languages use [], but others do.
- // Howhever, it is unclear to me how [] is supposed to work.
- pattern = pattern.replaceAll("|[])", ")");
- pattern = pattern.replaceAll(":[]", ":");
+ return pattern
+ }
- return pattern
- }
+ for (var token in copy) {
+ if (!copy.hasOwnProperty(token) || !copy[token]) {
+ continue;
+ }
- for (var token in copy) {
- if (!copy.hasOwnProperty(token) || !copy[token]) {
- continue;
- }
+ var patterns = copy[token];
+ patterns = Array.isArray(patterns) ? patterns : [patterns];
- var patterns = copy[token];
- patterns = Array.isArray(patterns) ? patterns : [patterns];
+ var indexes = []
- var indexes = []
+ for (var j = 0; j < patterns.length; ++j) {
+ var patternObj = patterns[j];
+ var inside = patternObj.inside;
+ var lookbehind = !!patternObj.lookbehind;
+ var greedy = !!patternObj.greedy;
+ var alias = patternObj.alias;
- for (var j = 0; j < patterns.length; ++j) {
- var patternObj = patterns[j];
- var inside = patternObj.inside;
- var lookbehind = !!patternObj.lookbehind;
- var greedy = !!patternObj.greedy;
- var alias = patternObj.alias;
+ //alias = Array.isArray(alias) ? alias : [alias];
+ //alias = alias.join('/')
+ alias = Array.isArray(alias) ? alias[0] : alias;
- //alias = Array.isArray(alias) ? alias : [alias];
- //alias = alias.join('/')
- alias = Array.isArray(alias) ? alias[0] : alias;
+ var pattern = patternObj.pattern || patternObj;
+ var patternStr = sanitize(pattern.toString())
- var pattern = patternObj.pattern || patternObj;
- var patternStr = sanitize(pattern.toString())
+ if (lookbehind) {
+ patternStr += "l"
+ }
+ if (greedy) {
+ patternStr += "y"
+ }
- if (lookbehind) {
- patternStr += "l"
- }
- if (greedy) {
- patternStr += "y"
- }
+ var np
- var np
+ if (alias || inside) {
+ np = {
+ pattern: patternStr
+ }
- if (alias || inside) {
- np = {
- pattern: patternStr
- }
+ if (alias) {
+ np.alias = alias
+ }
+ if (inside) {
+ np.inside = flatten(inside)
+ }
- if (alias) {
- np.alias = alias
- }
- if (inside) {
- np.inside = flatten(inside)
+ } else if (pattern instanceof RegExp) {
+ np = patternStr
+ } else {
+ debugger
}
- } else if (pattern instanceof RegExp) {
- np = patternStr
- } else {
- debugger
+ tempPatterns.push(np)
+ indexes.push(np)
}
-
- tempPatterns.push(np)
- indexes.push(np)
- }
-
- keys[token] = indexes
- tempTokens.push(indexes)
- }
- tempGrammars.push(keys)
- return keys
-}
+ keys[token] = indexes
+ tempTokens.push(indexes)
+ }
-var unsupported = [
- "bsl",
- "coq",
- "gherkin",
- "jexl",
- "kumir",
- "pure",
- "purescript",
- "turtle",
- "sparql" // requires turtle
-]
-
-await loadScript("https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js")
-await loadScript("https://prismjs.com/components.js")
-await loadLanguages(Object.keys(components.languages))
-
-Object.keys(Prism.languages).forEach(lng => {
- if (unsupported.includes(lng) || !components.languages[lng]) {
- return
+ tempGrammars.push(keys)
+ return keys
}
- tempLanguages[lng] = flatten(Prism.languages[lng])
-})
-
-var allTokens = uniqlo(tempTokens, isEqual)
-var allGrammars = uniqlo(tempGrammars, isEqual)
-var allPatterns = uniqlo(tempPatterns, isEqual)
+ var unsupported = [
+ "bsl",
+ "coq",
+ "gherkin",
+ "jexl",
+ "kumir",
+ "pure",
+ "purescript",
+ "turtle",
+ "sparql" // requires turtle
+ ]
+
+ await loadScript("https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js")
+ await loadScript("https://prismjs.com/components.js")
+ await loadLanguages(Object.keys(components.languages))
+ console.log(`\nLoaded all ${langNumber} languages`)
+ console.log("Processing...")
+ Object.keys(Prism.languages).forEach(lng => {
+ if (unsupported.includes(lng) || !components.languages[lng]) {
+ return
+ }
-Object.keys(tempLanguages).forEach(name => {
- var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
- if (find === undefined) {
- debugger
- }
+ tempLanguages[lng] = flatten(Prism.languages[lng])
+ })
- tempLanguages[name] = find
-})
+ var allTokens = uniqlo(tempTokens, isEqual)
+ var allGrammars = uniqlo(tempGrammars, isEqual)
+ var allPatterns = uniqlo(tempPatterns, isEqual)
-for (var i = 0; i < allPatterns.length; i++) {
- if (allPatterns[i].inside) {
- var find = allGrammars.find(x => isEqual(x, allPatterns[i].inside))
+ Object.keys(tempLanguages).forEach(name => {
+ var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
if (find === undefined) {
debugger
}
- allPatterns[i].inside = find
- }
-}
+ tempLanguages[name] = find
+ })
-for (var i = 0; i < allTokens.length; i++) {
- var token = allTokens[i]
+ for (var i = 0; i < allPatterns.length; i++) {
+ if (allPatterns[i].inside) {
+ var find = allGrammars.find(x => isEqual(x, allPatterns[i].inside))
+ if (find === undefined) {
+ debugger
+ }
- for (var j = 0; j < token.length; j++) {
- var find = allPatterns.find(x => isEqual(x, token[j]))
- if (find === undefined) {
- debugger
+ allPatterns[i].inside = find
}
-
- token[j] = find
}
-}
-for (var i = 0; i < allGrammars.length; i++) {
- Object.keys(allGrammars[i]).forEach(name => {
- var find = allTokens.find(x => isEqual(x, allGrammars[i][name]))
- if (find === undefined) {
- debugger
- }
+ for (var i = 0; i < allTokens.length; i++) {
+ var token = allTokens[i]
- allGrammars[i][name] = find
- })
-}
+ for (var j = 0; j < token.length; j++) {
+ var find = allPatterns.find(x => isEqual(x, token[j]))
+ if (find === undefined) {
+ debugger
+ }
-for (var i = 0; i < allPatterns.length; i++) {
- if (allPatterns[i].inside) {
- allPatterns[i].inside = allGrammars.indexOf(allPatterns[i].inside)
+ token[j] = find
+ }
}
-}
-for (var i = 0; i < allTokens.length; i++) {
- var token = allTokens[i]
+ for (var i = 0; i < allGrammars.length; i++) {
+ Object.keys(allGrammars[i]).forEach(name => {
+ var find = allTokens.find(x => isEqual(x, allGrammars[i][name]))
+ if (find === undefined) {
+ debugger
+ }
- for (var j = 0; j < token.length; j++) {
- token[j] = allPatterns.indexOf(token[j])
+ allGrammars[i][name] = find
+ })
}
-}
-/*for (var i = 0; i < allGrammars.length; i++) {
- Object.keys(allGrammars[i]).forEach(name => {
- if (allGrammars[i][name].length == 1) {
- allGrammars[i][name] = allGrammars[i][name][0]
+ for (var i = 0; i < allPatterns.length; i++) {
+ if (allPatterns[i].inside) {
+ allPatterns[i].inside = allGrammars.indexOf(allPatterns[i].inside)
}
- })
-}*/
+ }
+
+ for (var i = 0; i < allTokens.length; i++) {
+ var token = allTokens[i]
-for (var i = 0; i < allPatterns.length; i++) {
- if (allPatterns[i].pattern) {
- var patternStr = allPatterns[i].pattern + ",";
- if (allPatterns[i].alias) {
- patternStr += allPatterns[i].alias
+ for (var j = 0; j < token.length; j++) {
+ token[j] = allPatterns.indexOf(token[j])
}
+ }
+
+ /*for (var i = 0; i < allGrammars.length; i++) {
+ Object.keys(allGrammars[i]).forEach(name => {
+ if (allGrammars[i][name].length == 1) {
+ allGrammars[i][name] = allGrammars[i][name][0]
+ }
+ })
+ }*/
+
+ for (var i = 0; i < allPatterns.length; i++) {
+ if (allPatterns[i].pattern) {
+ var patternStr = allPatterns[i].pattern + ",";
+ if (allPatterns[i].alias) {
+ patternStr += allPatterns[i].alias
+ }
patternStr += ","
- if (allPatterns[i].inside) {
- patternStr += allPatterns[i].inside
- }
+ if (allPatterns[i].inside) {
+ patternStr += allPatterns[i].inside
+ }
- allPatterns[i] = patternStr
- } else {
- allPatterns[i] += ",,"
+ allPatterns[i] = patternStr
+ } else {
+ allPatterns[i] += ",,"
+ }
}
-}
-var allLanguages = {}
-var languageNames = {}
+ var allLanguages = {}
+ var languageNames = {}
-Object.keys(tempLanguages).forEach(name => {
- var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
- if (find === undefined) {
- debugger
- }
+ Object.keys(tempLanguages).forEach(name => {
+ var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
+ if (find === undefined) {
+ debugger
+ }
- allLanguages[name] = allGrammars.indexOf(find)
- languageNames[name] = components.languages[name].title
+ allLanguages[name] = allGrammars.indexOf(find)
+ languageNames[name] = components.languages[name].title
- var alias = components.languages[name].alias
- if (alias) {
- alias = Array.isArray(alias) ? alias : [alias];
+ var alias = components.languages[name].alias
+ if (alias) {
+ alias = Array.isArray(alias) ? alias : [alias];
- for (const lng of alias) {
- allLanguages[lng] = allGrammars.indexOf(find)
-
- if (components.languages[name].aliasTitles) {
- languageNames[lng] = components.languages[name].aliasTitles[lng]
- } else {
- languageNames[lng] = components.languages[name].title
+ for (const lng of alias) {
+ allLanguages[lng] = allGrammars.indexOf(find)
+
+ if (components.languages[name].aliasTitles) {
+ languageNames[lng] = components.languages[name].aliasTitles[lng]
+ } else {
+ languageNames[lng] = components.languages[name].title
+ }
}
}
- }
-})
+ })
-var final = {
- patterns: allPatterns,
- grammars: allGrammars,
- languages: allLanguages
-}
+ var final = {
+ patterns: allPatterns,
+ grammars: allGrammars,
+ languages: allLanguages
+ }
-const chunks = [];
-
-const writeUint16 = i => chunks.push(new Uint16Array([ i ]))
-const writeUint8 = i => chunks.push(new Uint8Array([ i ]))
-const writeString = str => {
- if (str.length < 253) {
- writeUint8(str.length)
- } else {
- writeUint8(254 & 0xFF)
- writeUint8(str.length & 0xFF)
- writeUint8((str.length >> 8) & 0xFF)
- writeUint8((str.length >> 16) & 0xFF)
+ const chunks = [];
+
+ const writeUint16 = i => chunks.push(new Uint16Array([i]))
+ const writeUint8 = i => chunks.push(new Uint8Array([i]))
+ const writeString = str => {
+ if (str.length < 253) {
+ writeUint8(str.length)
+ } else {
+ writeUint8(254 & 0xFF)
+ writeUint8(str.length & 0xFF)
+ writeUint8((str.length >> 8) & 0xFF)
+ writeUint8((str.length >> 16) & 0xFF)
+ }
+ chunks.push(new Uint8Array(str.split('').map(char => char.charCodeAt(0))))
}
- chunks.push(new Uint8Array(str.split('').map(char => char.charCodeAt(0))))
-}
-// Patterns
-writeUint16(allPatterns.length)
+ // Patterns
+ writeUint16(allPatterns.length)
-allPatterns.forEach(pattern => {
- writeString(pattern)
-})
+ allPatterns.forEach(pattern => {
+ writeString(pattern)
+ })
-// Grammars
-writeUint16(allGrammars.length)
+ // Grammars
+ writeUint16(allGrammars.length)
-for (var i = 0; i < allGrammars.length; i++) {
- writeUint8(Object.keys(allGrammars[i]).length)
-
- Object.keys(allGrammars[i]).forEach(name => {
- writeString(name)
- writeUint8(allGrammars[i][name].length)
- allGrammars[i][name].forEach(id => {
- writeUint16(id)
+ for (var i = 0; i < allGrammars.length; i++) {
+ writeUint8(Object.keys(allGrammars[i]).length)
+
+ Object.keys(allGrammars[i]).forEach(name => {
+ writeString(name)
+ writeUint8(allGrammars[i][name].length)
+ allGrammars[i][name].forEach(id => {
+ writeUint16(id)
+ })
})
+ }
+
+ // Languages
+ writeUint16(Object.keys(allLanguages).length)
+
+ Object.keys(allLanguages).forEach(name => {
+ writeString(name)
+ if (languageNames[name]) {
+ writeString(languageNames[name])
+ } else {
+ writeString("")
+ }
+ writeUint16(allLanguages[name])
})
+
+ const blob = new Blob(chunks, {type: 'application/octet-binary'});
+ console.log(blob)
+ return blob;
}
-// Languages
-writeUint16(Object.keys(allLanguages).length)
+async function saveBlob(blob, filename) {
+ console.log(`Saving ${blob} to ${filename}`)
+ const buffer = Buffer.from(await blob.arrayBuffer())
+ fs.writeFileSync(filename, buffer)
+}
-Object.keys(allLanguages).forEach(name => {
- writeString(name)
- if (languageNames[name]) {
- writeString(languageNames[name])
- } else {
- writeString("")
- }
- writeUint16(allLanguages[name])
-})
+const filepath = "libprisma/grammars.dat";
-const blob = new Blob(chunks, { type: 'application/octet-binary' });
-const url = window.URL.createObjectURL(blob)
-const a = document.createElement('a')
-a.href = url
-a.download = 'grammars.dat'
-a.click()
+generate().then(blob => {
+ saveBlob(blob, filepath).then(() => {
+ console.log("Done! Saved to " + filepath)
+ })
+})
diff --git a/isEqual.js b/isEqual.js
deleted file mode 100644
index c76c74c..0000000
--- a/isEqual.js
+++ /dev/null
@@ -1,1647 +0,0 @@
-/**
- * lodash (Custom Build)
- * Build: `lodash modularize exports="npm" -o ./`
- * Copyright jQuery Foundation and other contributors
- * Released under MIT license
- * Based on Underscore.js 1.8.3
- * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- */
-
-/** Used as the size to enable large array optimizations. */
-var LARGE_ARRAY_SIZE = 200;
-
-/** Used to stand-in for `undefined` hash values. */
-var HASH_UNDEFINED = '__lodash_hash_undefined__';
-
-/** Used to compose bitmasks for comparison styles. */
-var UNORDERED_COMPARE_FLAG = 1,
- PARTIAL_COMPARE_FLAG = 2;
-
-/** Used as references for various `Number` constants. */
-var MAX_SAFE_INTEGER = 9007199254740991;
-
-/** `Object#toString` result references. */
-var argsTag = '[object Arguments]',
- arrayTag = '[object Array]',
- boolTag = '[object Boolean]',
- dateTag = '[object Date]',
- errorTag = '[object Error]',
- funcTag = '[object Function]',
- genTag = '[object GeneratorFunction]',
- mapTag = '[object Map]',
- numberTag = '[object Number]',
- objectTag = '[object Object]',
- promiseTag = '[object Promise]',
- regexpTag = '[object RegExp]',
- setTag = '[object Set]',
- stringTag = '[object String]',
- symbolTag = '[object Symbol]',
- weakMapTag = '[object WeakMap]';
-
-var arrayBufferTag = '[object ArrayBuffer]',
- dataViewTag = '[object DataView]',
- float32Tag = '[object Float32Array]',
- float64Tag = '[object Float64Array]',
- int8Tag = '[object Int8Array]',
- int16Tag = '[object Int16Array]',
- int32Tag = '[object Int32Array]',
- uint8Tag = '[object Uint8Array]',
- uint8ClampedTag = '[object Uint8ClampedArray]',
- uint16Tag = '[object Uint16Array]',
- uint32Tag = '[object Uint32Array]';
-
-/**
- * Used to match `RegExp`
- * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
- */
-var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
-
-/** Used to detect host constructors (Safari). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
-
-/** Used to detect unsigned integer values. */
-var reIsUint = /^(?:0|[1-9]\d*)$/;
-
-/** Used to identify `toStringTag` values of typed arrays. */
-var typedArrayTags = {};
-typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
-typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
-typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
-typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
-typedArrayTags[uint32Tag] = true;
-typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
-typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
-typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
-typedArrayTags[errorTag] = typedArrayTags[funcTag] =
-typedArrayTags[mapTag] = typedArrayTags[numberTag] =
-typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
-typedArrayTags[setTag] = typedArrayTags[stringTag] =
-typedArrayTags[weakMapTag] = false;
-
-/** Detect free variable `global` from Node.js. */
-var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
-
-/** Detect free variable `self`. */
-var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
-
-/** Used as a reference to the global object. */
-var root = freeGlobal || freeSelf || Function('return this')();
-
-/** Detect free variable `exports`. */
-var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
-
-/** Detect free variable `module`. */
-var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
-
-/** Detect the popular CommonJS extension `module.exports`. */
-var moduleExports = freeModule && freeModule.exports === freeExports;
-
-/** Detect free variable `process` from Node.js. */
-var freeProcess = moduleExports && freeGlobal.process;
-
-/** Used to access faster Node.js helpers. */
-var nodeUtil = (function() {
- try {
- return freeProcess && freeProcess.binding('util');
- } catch (e) {}
-}());
-
-/* Node.js helper references. */
-var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
-
-/**
- * A specialized version of `_.some` for arrays without support for iteratee
- * shorthands.
- *
- * @private
- * @param {Array} [array] The array to iterate over.
- * @param {Function} predicate The function invoked per iteration.
- * @returns {boolean} Returns `true` if any element passes the predicate check,
- * else `false`.
- */
-function arraySome(array, predicate) {
- var index = -1,
- length = array ? array.length : 0;
-
- while (++index < length) {
- if (predicate(array[index], index, array)) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * The base implementation of `_.times` without support for iteratee shorthands
- * or max array length checks.
- *
- * @private
- * @param {number} n The number of times to invoke `iteratee`.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the array of results.
- */
-function baseTimes(n, iteratee) {
- var index = -1,
- result = Array(n);
-
- while (++index < n) {
- result[index] = iteratee(index);
- }
- return result;
-}
-
-/**
- * The base implementation of `_.unary` without support for storing metadata.
- *
- * @private
- * @param {Function} func The function to cap arguments for.
- * @returns {Function} Returns the new capped function.
- */
-function baseUnary(func) {
- return function(value) {
- return func(value);
- };
-}
-
-/**
- * Gets the value at `key` of `object`.
- *
- * @private
- * @param {Object} [object] The object to query.
- * @param {string} key The key of the property to get.
- * @returns {*} Returns the property value.
- */
-function getValue(object, key) {
- return object == null ? undefined : object[key];
-}
-
-/**
- * Checks if `value` is a host object in IE < 9.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
- */
-function isHostObject(value) {
- // Many host objects are `Object` objects that can coerce to strings
- // despite having improperly defined `toString` methods.
- var result = false;
- if (value != null && typeof value.toString != 'function') {
- try {
- result = !!(value + '');
- } catch (e) {}
- }
- return result;
-}
-
-/**
- * Converts `map` to its key-value pairs.
- *
- * @private
- * @param {Object} map The map to convert.
- * @returns {Array} Returns the key-value pairs.
- */
-function mapToArray(map) {
- var index = -1,
- result = Array(map.size);
-
- map.forEach(function(value, key) {
- result[++index] = [key, value];
- });
- return result;
-}
-
-/**
- * Creates a unary function that invokes `func` with its argument transformed.
- *
- * @private
- * @param {Function} func The function to wrap.
- * @param {Function} transform The argument transform.
- * @returns {Function} Returns the new function.
- */
-function overArg(func, transform) {
- return function(arg) {
- return func(transform(arg));
- };
-}
-
-/**
- * Converts `set` to an array of its values.
- *
- * @private
- * @param {Object} set The set to convert.
- * @returns {Array} Returns the values.
- */
-function setToArray(set) {
- var index = -1,
- result = Array(set.size);
-
- set.forEach(function(value) {
- result[++index] = value;
- });
- return result;
-}
-
-/** Used for built-in method references. */
-var arrayProto = Array.prototype,
- funcProto = Function.prototype,
- objectProto = Object.prototype;
-
-/** Used to detect overreaching core-js shims. */
-var coreJsData = root['__core-js_shared__'];
-
-/** Used to detect methods masquerading as native. */
-var maskSrcKey = (function() {
- var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
- return uid ? ('Symbol(src)_1.' + uid) : '';
-}());
-
-/** Used to resolve the decompiled source of functions. */
-var funcToString = funcProto.toString;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Used to resolve the
- * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
- * of values.
- */
-var objectToString = objectProto.toString;
-
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
- funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
- .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
-
-/** Built-in value references. */
-var Symbol = root.Symbol,
- Uint8Array = root.Uint8Array,
- propertyIsEnumerable = objectProto.propertyIsEnumerable,
- splice = arrayProto.splice;
-
-/* Built-in method references for those with the same name as other `lodash` methods. */
-var nativeKeys = overArg(Object.keys, Object);
-
-/* Built-in method references that are verified to be native. */
-var DataView = getNative(root, 'DataView'),
- Map = getNative(root, 'Map'),
- Promise = getNative(root, 'Promise'),
- Set = getNative(root, 'Set'),
- WeakMap = getNative(root, 'WeakMap'),
- nativeCreate = getNative(Object, 'create');
-
-/** Used to detect maps, sets, and weakmaps. */
-var dataViewCtorString = toSource(DataView),
- mapCtorString = toSource(Map),
- promiseCtorString = toSource(Promise),
- setCtorString = toSource(Set),
- weakMapCtorString = toSource(WeakMap);
-
-/** Used to convert symbols to primitives and strings. */
-var symbolProto = Symbol ? Symbol.prototype : undefined,
- symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
-
-/**
- * Creates a hash object.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function Hash(entries) {
- var index = -1,
- length = entries ? entries.length : 0;
-
- this.clear();
- while (++index < length) {
- var entry = entries[index];
- this.set(entry[0], entry[1]);
- }
-}
-
-/**
- * Removes all key-value entries from the hash.
- *
- * @private
- * @name clear
- * @memberOf Hash
- */
-function hashClear() {
- this.__data__ = nativeCreate ? nativeCreate(null) : {};
-}
-
-/**
- * Removes `key` and its value from the hash.
- *
- * @private
- * @name delete
- * @memberOf Hash
- * @param {Object} hash The hash to modify.
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function hashDelete(key) {
- return this.has(key) && delete this.__data__[key];
-}
-
-/**
- * Gets the hash value for `key`.
- *
- * @private
- * @name get
- * @memberOf Hash
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function hashGet(key) {
- var data = this.__data__;
- if (nativeCreate) {
- var result = data[key];
- return result === HASH_UNDEFINED ? undefined : result;
- }
- return hasOwnProperty.call(data, key) ? data[key] : undefined;
-}
-
-/**
- * Checks if a hash value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf Hash
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function hashHas(key) {
- var data = this.__data__;
- return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
-}
-
-/**
- * Sets the hash `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf Hash
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the hash instance.
- */
-function hashSet(key, value) {
- var data = this.__data__;
- data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
- return this;
-}
-
-// Add methods to `Hash`.
-Hash.prototype.clear = hashClear;
-Hash.prototype['delete'] = hashDelete;
-Hash.prototype.get = hashGet;
-Hash.prototype.has = hashHas;
-Hash.prototype.set = hashSet;
-
-/**
- * Creates an list cache object.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function ListCache(entries) {
- var index = -1,
- length = entries ? entries.length : 0;
-
- this.clear();
- while (++index < length) {
- var entry = entries[index];
- this.set(entry[0], entry[1]);
- }
-}
-
-/**
- * Removes all key-value entries from the list cache.
- *
- * @private
- * @name clear
- * @memberOf ListCache
- */
-function listCacheClear() {
- this.__data__ = [];
-}
-
-/**
- * Removes `key` and its value from the list cache.
- *
- * @private
- * @name delete
- * @memberOf ListCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function listCacheDelete(key) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- if (index < 0) {
- return false;
- }
- var lastIndex = data.length - 1;
- if (index == lastIndex) {
- data.pop();
- } else {
- splice.call(data, index, 1);
- }
- return true;
-}
-
-/**
- * Gets the list cache value for `key`.
- *
- * @private
- * @name get
- * @memberOf ListCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function listCacheGet(key) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- return index < 0 ? undefined : data[index][1];
-}
-
-/**
- * Checks if a list cache value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf ListCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function listCacheHas(key) {
- return assocIndexOf(this.__data__, key) > -1;
-}
-
-/**
- * Sets the list cache `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf ListCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the list cache instance.
- */
-function listCacheSet(key, value) {
- var data = this.__data__,
- index = assocIndexOf(data, key);
-
- if (index < 0) {
- data.push([key, value]);
- } else {
- data[index][1] = value;
- }
- return this;
-}
-
-// Add methods to `ListCache`.
-ListCache.prototype.clear = listCacheClear;
-ListCache.prototype['delete'] = listCacheDelete;
-ListCache.prototype.get = listCacheGet;
-ListCache.prototype.has = listCacheHas;
-ListCache.prototype.set = listCacheSet;
-
-/**
- * Creates a map cache object to store key-value pairs.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function MapCache(entries) {
- var index = -1,
- length = entries ? entries.length : 0;
-
- this.clear();
- while (++index < length) {
- var entry = entries[index];
- this.set(entry[0], entry[1]);
- }
-}
-
-/**
- * Removes all key-value entries from the map.
- *
- * @private
- * @name clear
- * @memberOf MapCache
- */
-function mapCacheClear() {
- this.__data__ = {
- 'hash': new Hash,
- 'map': new (Map || ListCache),
- 'string': new Hash
- };
-}
-
-/**
- * Removes `key` and its value from the map.
- *
- * @private
- * @name delete
- * @memberOf MapCache
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function mapCacheDelete(key) {
- return getMapData(this, key)['delete'](key);
-}
-
-/**
- * Gets the map value for `key`.
- *
- * @private
- * @name get
- * @memberOf MapCache
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function mapCacheGet(key) {
- return getMapData(this, key).get(key);
-}
-
-/**
- * Checks if a map value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf MapCache
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function mapCacheHas(key) {
- return getMapData(this, key).has(key);
-}
-
-/**
- * Sets the map `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf MapCache
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the map cache instance.
- */
-function mapCacheSet(key, value) {
- getMapData(this, key).set(key, value);
- return this;
-}
-
-// Add methods to `MapCache`.
-MapCache.prototype.clear = mapCacheClear;
-MapCache.prototype['delete'] = mapCacheDelete;
-MapCache.prototype.get = mapCacheGet;
-MapCache.prototype.has = mapCacheHas;
-MapCache.prototype.set = mapCacheSet;
-
-/**
- *
- * Creates an array cache object to store unique values.
- *
- * @private
- * @constructor
- * @param {Array} [values] The values to cache.
- */
-function SetCache(values) {
- var index = -1,
- length = values ? values.length : 0;
-
- this.__data__ = new MapCache;
- while (++index < length) {
- this.add(values[index]);
- }
-}
-
-/**
- * Adds `value` to the array cache.
- *
- * @private
- * @name add
- * @memberOf SetCache
- * @alias push
- * @param {*} value The value to cache.
- * @returns {Object} Returns the cache instance.
- */
-function setCacheAdd(value) {
- this.__data__.set(value, HASH_UNDEFINED);
- return this;
-}
-
-/**
- * Checks if `value` is in the array cache.
- *
- * @private
- * @name has
- * @memberOf SetCache
- * @param {*} value The value to search for.
- * @returns {number} Returns `true` if `value` is found, else `false`.
- */
-function setCacheHas(value) {
- return this.__data__.has(value);
-}
-
-// Add methods to `SetCache`.
-SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
-SetCache.prototype.has = setCacheHas;
-
-/**
- * Creates a stack cache object to store key-value pairs.
- *
- * @private
- * @constructor
- * @param {Array} [entries] The key-value pairs to cache.
- */
-function Stack(entries) {
- this.__data__ = new ListCache(entries);
-}
-
-/**
- * Removes all key-value entries from the stack.
- *
- * @private
- * @name clear
- * @memberOf Stack
- */
-function stackClear() {
- this.__data__ = new ListCache;
-}
-
-/**
- * Removes `key` and its value from the stack.
- *
- * @private
- * @name delete
- * @memberOf Stack
- * @param {string} key The key of the value to remove.
- * @returns {boolean} Returns `true` if the entry was removed, else `false`.
- */
-function stackDelete(key) {
- return this.__data__['delete'](key);
-}
-
-/**
- * Gets the stack value for `key`.
- *
- * @private
- * @name get
- * @memberOf Stack
- * @param {string} key The key of the value to get.
- * @returns {*} Returns the entry value.
- */
-function stackGet(key) {
- return this.__data__.get(key);
-}
-
-/**
- * Checks if a stack value for `key` exists.
- *
- * @private
- * @name has
- * @memberOf Stack
- * @param {string} key The key of the entry to check.
- * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
- */
-function stackHas(key) {
- return this.__data__.has(key);
-}
-
-/**
- * Sets the stack `key` to `value`.
- *
- * @private
- * @name set
- * @memberOf Stack
- * @param {string} key The key of the value to set.
- * @param {*} value The value to set.
- * @returns {Object} Returns the stack cache instance.
- */
-function stackSet(key, value) {
- var cache = this.__data__;
- if (cache instanceof ListCache) {
- var pairs = cache.__data__;
- if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
- pairs.push([key, value]);
- return this;
- }
- cache = this.__data__ = new MapCache(pairs);
- }
- cache.set(key, value);
- return this;
-}
-
-// Add methods to `Stack`.
-Stack.prototype.clear = stackClear;
-Stack.prototype['delete'] = stackDelete;
-Stack.prototype.get = stackGet;
-Stack.prototype.has = stackHas;
-Stack.prototype.set = stackSet;
-
-/**
- * Creates an array of the enumerable property names of the array-like `value`.
- *
- * @private
- * @param {*} value The value to query.
- * @param {boolean} inherited Specify returning inherited property names.
- * @returns {Array} Returns the array of property names.
- */
-function arrayLikeKeys(value, inherited) {
- // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
- // Safari 9 makes `arguments.length` enumerable in strict mode.
- var result = (isArray(value) || isArguments(value))
- ? baseTimes(value.length, String)
- : [];
-
- var length = result.length,
- skipIndexes = !!length;
-
- for (var key in value) {
- if ((inherited || hasOwnProperty.call(value, key)) &&
- !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
- result.push(key);
- }
- }
- return result;
-}
-
-/**
- * Gets the index at which the `key` is found in `array` of key-value pairs.
- *
- * @private
- * @param {Array} array The array to inspect.
- * @param {*} key The key to search for.
- * @returns {number} Returns the index of the matched value, else `-1`.
- */
-function assocIndexOf(array, key) {
- var length = array.length;
- while (length--) {
- if (eq(array[length][0], key)) {
- return length;
- }
- }
- return -1;
-}
-
-/**
- * The base implementation of `getTag`.
- *
- * @private
- * @param {*} value The value to query.
- * @returns {string} Returns the `toStringTag`.
- */
-function baseGetTag(value) {
- return objectToString.call(value);
-}
-
-/**
- * The base implementation of `_.isEqual` which supports partial comparisons
- * and tracks traversed objects.
- *
- * @private
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @param {Function} [customizer] The function to customize comparisons.
- * @param {boolean} [bitmask] The bitmask of comparison flags.
- * The bitmask may be composed of the following flags:
- * 1 - Unordered comparison
- * 2 - Partial comparison
- * @param {Object} [stack] Tracks traversed `value` and `other` objects.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- */
-function baseIsEqual(value, other, customizer, bitmask, stack) {
- if (value === other) {
- return true;
- }
- if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
- return value !== value && other !== other;
- }
- return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
-}
-
-/**
- * A specialized version of `baseIsEqual` for arrays and objects which performs
- * deep comparisons and tracks traversed objects enabling objects with circular
- * references to be compared.
- *
- * @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} [customizer] The function to customize comparisons.
- * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
- * for more details.
- * @param {Object} [stack] Tracks traversed `object` and `other` objects.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
- */
-function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
- var objIsArr = isArray(object),
- othIsArr = isArray(other),
- objTag = arrayTag,
- othTag = arrayTag;
-
- if (!objIsArr) {
- objTag = getTag(object);
- objTag = objTag == argsTag ? objectTag : objTag;
- }
- if (!othIsArr) {
- othTag = getTag(other);
- othTag = othTag == argsTag ? objectTag : othTag;
- }
- var objIsObj = objTag == objectTag && !isHostObject(object),
- othIsObj = othTag == objectTag && !isHostObject(other),
- isSameTag = objTag == othTag;
-
- if (isSameTag && !objIsObj) {
- stack || (stack = new Stack);
- return (objIsArr || isTypedArray(object))
- ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
- : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
- }
- if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
- var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
- othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
-
- if (objIsWrapped || othIsWrapped) {
- var objUnwrapped = objIsWrapped ? object.value() : object,
- othUnwrapped = othIsWrapped ? other.value() : other;
-
- stack || (stack = new Stack);
- return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
- }
- }
- if (!isSameTag) {
- return false;
- }
- stack || (stack = new Stack);
- return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
-}
-
-/**
- * The base implementation of `_.isNative` without bad shim checks.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function,
- * else `false`.
- */
-function baseIsNative(value) {
- if (!isObject(value) || isMasked(value)) {
- return false;
- }
- var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
- return pattern.test(toSource(value));
-}
-
-/**
- * The base implementation of `_.isTypedArray` without Node.js optimizations.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
- */
-function baseIsTypedArray(value) {
- return isObjectLike(value) &&
- isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
-}
-
-/**
- * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
- *
- * @private
- * @param {Object} object The object to query.
- * @returns {Array} Returns the array of property names.
- */
-function baseKeys(object) {
- if (!isPrototype(object)) {
- return nativeKeys(object);
- }
- var result = [];
- for (var key in Object(object)) {
- if (hasOwnProperty.call(object, key) && key != 'constructor') {
- result.push(key);
- }
- }
- return result;
-}
-
-/**
- * A specialized version of `baseIsEqualDeep` for arrays with support for
- * partial deep comparisons.
- *
- * @private
- * @param {Array} array The array to compare.
- * @param {Array} other The other array to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} customizer The function to customize comparisons.
- * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
- * for more details.
- * @param {Object} stack Tracks traversed `array` and `other` objects.
- * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
- */
-function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
- var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
- arrLength = array.length,
- othLength = other.length;
-
- if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
- return false;
- }
- // Assume cyclic values are equal.
- var stacked = stack.get(array);
- if (stacked && stack.get(other)) {
- return stacked == other;
- }
- var index = -1,
- result = true,
- seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;
-
- stack.set(array, other);
- stack.set(other, array);
-
- // Ignore non-index properties.
- while (++index < arrLength) {
- var arrValue = array[index],
- othValue = other[index];
-
- if (customizer) {
- var compared = isPartial
- ? customizer(othValue, arrValue, index, other, array, stack)
- : customizer(arrValue, othValue, index, array, other, stack);
- }
- if (compared !== undefined) {
- if (compared) {
- continue;
- }
- result = false;
- break;
- }
- // Recursively compare arrays (susceptible to call stack limits).
- if (seen) {
- if (!arraySome(other, function(othValue, othIndex) {
- if (!seen.has(othIndex) &&
- (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
- return seen.add(othIndex);
- }
- })) {
- result = false;
- break;
- }
- } else if (!(
- arrValue === othValue ||
- equalFunc(arrValue, othValue, customizer, bitmask, stack)
- )) {
- result = false;
- break;
- }
- }
- stack['delete'](array);
- stack['delete'](other);
- return result;
-}
-
-/**
- * A specialized version of `baseIsEqualDeep` for comparing objects of
- * the same `toStringTag`.
- *
- * **Note:** This function only supports comparing values with tags of
- * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
- *
- * @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
- * @param {string} tag The `toStringTag` of the objects to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} customizer The function to customize comparisons.
- * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
- * for more details.
- * @param {Object} stack Tracks traversed `object` and `other` objects.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
- */
-function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
- switch (tag) {
- case dataViewTag:
- if ((object.byteLength != other.byteLength) ||
- (object.byteOffset != other.byteOffset)) {
- return false;
- }
- object = object.buffer;
- other = other.buffer;
-
- case arrayBufferTag:
- if ((object.byteLength != other.byteLength) ||
- !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
- return false;
- }
- return true;
-
- case boolTag:
- case dateTag:
- case numberTag:
- // Coerce booleans to `1` or `0` and dates to milliseconds.
- // Invalid dates are coerced to `NaN`.
- return eq(+object, +other);
-
- case errorTag:
- return object.name == other.name && object.message == other.message;
-
- case regexpTag:
- case stringTag:
- // Coerce regexes to strings and treat strings, primitives and objects,
- // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
- // for more details.
- return object == (other + '');
-
- case mapTag:
- var convert = mapToArray;
-
- case setTag:
- var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
- convert || (convert = setToArray);
-
- if (object.size != other.size && !isPartial) {
- return false;
- }
- // Assume cyclic values are equal.
- var stacked = stack.get(object);
- if (stacked) {
- return stacked == other;
- }
- bitmask |= UNORDERED_COMPARE_FLAG;
-
- // Recursively compare objects (susceptible to call stack limits).
- stack.set(object, other);
- var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
- stack['delete'](object);
- return result;
-
- case symbolTag:
- if (symbolValueOf) {
- return symbolValueOf.call(object) == symbolValueOf.call(other);
- }
- }
- return false;
-}
-
-/**
- * A specialized version of `baseIsEqualDeep` for objects with support for
- * partial deep comparisons.
- *
- * @private
- * @param {Object} object The object to compare.
- * @param {Object} other The other object to compare.
- * @param {Function} equalFunc The function to determine equivalents of values.
- * @param {Function} customizer The function to customize comparisons.
- * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
- * for more details.
- * @param {Object} stack Tracks traversed `object` and `other` objects.
- * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
- */
-function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
- var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
- objProps = keys(object),
- objLength = objProps.length,
- othProps = keys(other),
- othLength = othProps.length;
-
- if (objLength != othLength && !isPartial) {
- return false;
- }
- var index = objLength;
- while (index--) {
- var key = objProps[index];
- if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
- return false;
- }
- }
- // Assume cyclic values are equal.
- var stacked = stack.get(object);
- if (stacked && stack.get(other)) {
- return stacked == other;
- }
- var result = true;
- stack.set(object, other);
- stack.set(other, object);
-
- var skipCtor = isPartial;
- while (++index < objLength) {
- key = objProps[index];
- var objValue = object[key],
- othValue = other[key];
-
- if (customizer) {
- var compared = isPartial
- ? customizer(othValue, objValue, key, other, object, stack)
- : customizer(objValue, othValue, key, object, other, stack);
- }
- // Recursively compare objects (susceptible to call stack limits).
- if (!(compared === undefined
- ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
- : compared
- )) {
- result = false;
- break;
- }
- skipCtor || (skipCtor = key == 'constructor');
- }
- if (result && !skipCtor) {
- var objCtor = object.constructor,
- othCtor = other.constructor;
-
- // Non `Object` object instances with different constructors are not equal.
- if (objCtor != othCtor &&
- ('constructor' in object && 'constructor' in other) &&
- !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
- typeof othCtor == 'function' && othCtor instanceof othCtor)) {
- result = false;
- }
- }
- stack['delete'](object);
- stack['delete'](other);
- return result;
-}
-
-/**
- * Gets the data for `map`.
- *
- * @private
- * @param {Object} map The map to query.
- * @param {string} key The reference key.
- * @returns {*} Returns the map data.
- */
-function getMapData(map, key) {
- var data = map.__data__;
- return isKeyable(key)
- ? data[typeof key == 'string' ? 'string' : 'hash']
- : data.map;
-}
-
-/**
- * Gets the native function at `key` of `object`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
- */
-function getNative(object, key) {
- var value = getValue(object, key);
- return baseIsNative(value) ? value : undefined;
-}
-
-/**
- * Gets the `toStringTag` of `value`.
- *
- * @private
- * @param {*} value The value to query.
- * @returns {string} Returns the `toStringTag`.
- */
-var getTag = baseGetTag;
-
-// Fallback for data views, maps, sets, and weak maps in IE 11,
-// for data views in Edge < 14, and promises in Node.js.
-if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
- (Map && getTag(new Map) != mapTag) ||
- (Promise && getTag(Promise.resolve()) != promiseTag) ||
- (Set && getTag(new Set) != setTag) ||
- (WeakMap && getTag(new WeakMap) != weakMapTag)) {
- getTag = function(value) {
- var result = objectToString.call(value),
- Ctor = result == objectTag ? value.constructor : undefined,
- ctorString = Ctor ? toSource(Ctor) : undefined;
-
- if (ctorString) {
- switch (ctorString) {
- case dataViewCtorString: return dataViewTag;
- case mapCtorString: return mapTag;
- case promiseCtorString: return promiseTag;
- case setCtorString: return setTag;
- case weakMapCtorString: return weakMapTag;
- }
- }
- return result;
- };
-}
-
-/**
- * Checks if `value` is a valid array-like index.
- *
- * @private
- * @param {*} value The value to check.
- * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
- * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
- */
-function isIndex(value, length) {
- length = length == null ? MAX_SAFE_INTEGER : length;
- return !!length &&
- (typeof value == 'number' || reIsUint.test(value)) &&
- (value > -1 && value % 1 == 0 && value < length);
-}
-
-/**
- * Checks if `value` is suitable for use as unique object key.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
- */
-function isKeyable(value) {
- var type = typeof value;
- return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
- ? (value !== '__proto__')
- : (value === null);
-}
-
-/**
- * Checks if `func` has its source masked.
- *
- * @private
- * @param {Function} func The function to check.
- * @returns {boolean} Returns `true` if `func` is masked, else `false`.
- */
-function isMasked(func) {
- return !!maskSrcKey && (maskSrcKey in func);
-}
-
-/**
- * Checks if `value` is likely a prototype object.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
- */
-function isPrototype(value) {
- var Ctor = value && value.constructor,
- proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
-
- return value === proto;
-}
-
-/**
- * Converts `func` to its source code.
- *
- * @private
- * @param {Function} func The function to process.
- * @returns {string} Returns the source code.
- */
-function toSource(func) {
- if (func != null) {
- try {
- return funcToString.call(func);
- } catch (e) {}
- try {
- return (func + '');
- } catch (e) {}
- }
- return '';
-}
-
-/**
- * Performs a
- * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
- * comparison between two values to determine if they are equivalent.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'a': 1 };
- * var other = { 'a': 1 };
- *
- * _.eq(object, object);
- * // => true
- *
- * _.eq(object, other);
- * // => false
- *
- * _.eq('a', 'a');
- * // => true
- *
- * _.eq('a', Object('a'));
- * // => false
- *
- * _.eq(NaN, NaN);
- * // => true
- */
-function eq(value, other) {
- return value === other || (value !== value && other !== other);
-}
-
-/**
- * Checks if `value` is likely an `arguments` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an `arguments` object,
- * else `false`.
- * @example
- *
- * _.isArguments(function() { return arguments; }());
- * // => true
- *
- * _.isArguments([1, 2, 3]);
- * // => false
- */
-function isArguments(value) {
- // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
- return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
- (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
-}
-
-/**
- * Checks if `value` is classified as an `Array` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an array, else `false`.
- * @example
- *
- * _.isArray([1, 2, 3]);
- * // => true
- *
- * _.isArray(document.body.children);
- * // => false
- *
- * _.isArray('abc');
- * // => false
- *
- * _.isArray(_.noop);
- * // => false
- */
-var isArray = Array.isArray;
-
-/**
- * Checks if `value` is array-like. A value is considered array-like if it's
- * not a function and has a `value.length` that's an integer greater than or
- * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
- * @example
- *
- * _.isArrayLike([1, 2, 3]);
- * // => true
- *
- * _.isArrayLike(document.body.children);
- * // => true
- *
- * _.isArrayLike('abc');
- * // => true
- *
- * _.isArrayLike(_.noop);
- * // => false
- */
-function isArrayLike(value) {
- return value != null && isLength(value.length) && !isFunction(value);
-}
-
-/**
- * This method is like `_.isArrayLike` except that it also checks if `value`
- * is an object.
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an array-like object,
- * else `false`.
- * @example
- *
- * _.isArrayLikeObject([1, 2, 3]);
- * // => true
- *
- * _.isArrayLikeObject(document.body.children);
- * // => true
- *
- * _.isArrayLikeObject('abc');
- * // => false
- *
- * _.isArrayLikeObject(_.noop);
- * // => false
- */
-function isArrayLikeObject(value) {
- return isObjectLike(value) && isArrayLike(value);
-}
-
-/**
- * Performs a deep comparison between two values to determine if they are
- * equivalent.
- *
- * **Note:** This method supports comparing arrays, array buffers, booleans,
- * date objects, error objects, maps, numbers, `Object` objects, regexes,
- * sets, strings, symbols, and typed arrays. `Object` objects are compared
- * by their own, not inherited, enumerable properties. Functions and DOM
- * nodes are **not** supported.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'a': 1 };
- * var other = { 'a': 1 };
- *
- * _.isEqual(object, other);
- * // => true
- *
- * object === other;
- * // => false
- */
-function isEqual(value, other) {
- return baseIsEqual(value, other);
-}
-
-/**
- * Checks if `value` is classified as a `Function` object.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a function, else `false`.
- * @example
- *
- * _.isFunction(_);
- * // => true
- *
- * _.isFunction(/abc/);
- * // => false
- */
-function isFunction(value) {
- // The use of `Object#toString` avoids issues with the `typeof` operator
- // in Safari 8-9 which returns 'object' for typed array and other constructors.
- var tag = isObject(value) ? objectToString.call(value) : '';
- return tag == funcTag || tag == genTag;
-}
-
-/**
- * Checks if `value` is a valid array-like length.
- *
- * **Note:** This method is loosely based on
- * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
- * @example
- *
- * _.isLength(3);
- * // => true
- *
- * _.isLength(Number.MIN_VALUE);
- * // => false
- *
- * _.isLength(Infinity);
- * // => false
- *
- * _.isLength('3');
- * // => false
- */
-function isLength(value) {
- return typeof value == 'number' &&
- value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
-}
-
-/**
- * Checks if `value` is the
- * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
- * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(_.noop);
- * // => true
- *
- * _.isObject(null);
- * // => false
- */
-function isObject(value) {
- var type = typeof value;
- return !!value && (type == 'object' || type == 'function');
-}
-
-/**
- * Checks if `value` is object-like. A value is object-like if it's not `null`
- * and has a `typeof` result of "object".
- *
- * @static
- * @memberOf _
- * @since 4.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- * @example
- *
- * _.isObjectLike({});
- * // => true
- *
- * _.isObjectLike([1, 2, 3]);
- * // => true
- *
- * _.isObjectLike(_.noop);
- * // => false
- *
- * _.isObjectLike(null);
- * // => false
- */
-function isObjectLike(value) {
- return !!value && typeof value == 'object';
-}
-
-/**
- * Checks if `value` is classified as a typed array.
- *
- * @static
- * @memberOf _
- * @since 3.0.0
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
- * @example
- *
- * _.isTypedArray(new Uint8Array);
- * // => true
- *
- * _.isTypedArray([]);
- * // => false
- */
-var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
-
-/**
- * Creates an array of the own enumerable property names of `object`.
- *
- * **Note:** Non-object values are coerced to objects. See the
- * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
- * for more details.
- *
- * @static
- * @since 0.1.0
- * @memberOf _
- * @category Object
- * @param {Object} object The object to query.
- * @returns {Array} Returns the array of property names.
- * @example
- *
- * function Foo() {
- * this.a = 1;
- * this.b = 2;
- * }
- *
- * Foo.prototype.c = 3;
- *
- * _.keys(new Foo);
- * // => ['a', 'b'] (iteration order is not guaranteed)
- *
- * _.keys('hi');
- * // => ['0', '1']
- */
-function keys(object) {
- return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
-}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..1f9a3ba
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,21 @@
+{
+ "name": "libprisma",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "libprisma",
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.isequal": "^4.5.0"
+ }
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..828a9ac
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "libprisma",
+ "version": "1.0.0",
+ "description": "This is a C++ porting of [prism.js](https://github.com/PrismJS/prism) library.\r The code depends on Boost.Regex, as it's a faster and more comprehensive than STD's.",
+ "main": "generate.js",
+ "scripts": {
+ "start": "node generate.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/TelegramMessenger/libprisma.git"
+ },
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/TelegramMessenger/libprisma/issues"
+ },
+ "homepage": "https://github.com/TelegramMessenger/libprisma#readme",
+ "dependencies": {
+ "lodash.isequal": "^4.5.0"
+ }
+}