diff --git a/src/command/render/pandoc-html.ts b/src/command/render/pandoc-html.ts index 20cac21e86b..0721beffc3b 100644 --- a/src/command/render/pandoc-html.ts +++ b/src/command/render/pandoc-html.ts @@ -286,6 +286,29 @@ async function resolveQuartoSyntaxHighlighting( if (themeDescriptor) { // Other variables that need to be injected (if any) const extraVariables = extras.html?.[kQuartoCssVariables] || []; + for (let i = 0; i < extraVariables.length; ++i) { + // For the same reason as outlined in https://github.com/rstudio/bslib/issues/1104, + // we need to patch the text to include a semicolon inside the declaration + // if it doesn't have one. + // This happens because scss-parser is brittle, and will fail to parse a declaration + // if it doesn't end with a semicolon. + // + // In addition, we know that some our variables come from the output + // of sassCompile which + // - misses the last semicolon + // - emits a :root declaration + // - triggers the scss-parser bug + // So we'll attempt to target the last declaration in the :root + // block specifically and add a semicolon if it doesn't have one. + let variable = extraVariables[i].trim(); + if ( + variable.endsWith("}") && variable.startsWith(":root") && + !variable.match(/.*;\s}$/) + ) { + variable = variable.slice(0, -1) + ";}"; + extraVariables[i] = variable; + } + } // The text highlighting CSS variables const highlightCss = generateThemeCssVars(themeDescriptor.json); @@ -308,7 +331,7 @@ async function resolveQuartoSyntaxHighlighting( // Add this string literal to the rule set, which prevents pandoc // from inlining this style sheet // See https://github.com/jgm/pandoc/commit/7c0a80c323f81e6262848bfcfc922301e3f406e0 - rules.push(".prevent-inlining { content: ' bundle.key).join("|") + "-" + - // (minified ? "min" : "nomin"); - - return await compileWithCache( + const result = await compileWithCache( scssInput, loadPaths, temp, minified, - cacheKey, + md5HashBytes(new TextEncoder().encode(scssInput)), + ); + if (!Deno.env.get("QUARTO_SAVE_SCSS")) { + return result; + } + const partialOutput = Deno.readTextFileSync(result); + // now we attempt to find the SCSS variables in the output + // and inject them back in the SCSS file so that our debug tooling can use them. + const scssToWrite = [scssInput]; + const internalVars = Array.from( + partialOutput.matchAll(/(--quarto-scss-export-[^;}]+;?)/g), + ).map((m) => m[0]); + const annotation = { + "css-vars": internalVars, + }; + scssToWrite.push( + `// quarto-scss-analysis-annotation ${JSON.stringify(annotation)}`, + ); + scssInput = scssToWrite.join("\n"); + const prefix = Deno.env.get("QUARTO_SAVE_SCSS"); + const counterValue = counter++; + Deno.writeTextFileSync( + `${prefix}-${counterValue}.scss`, + scssInput, ); + + return result; } /*-- scss:uses --*/ diff --git a/src/core/sass/add-css-vars.ts b/src/core/sass/add-css-vars.ts new file mode 100644 index 00000000000..cac7db9fe98 --- /dev/null +++ b/src/core/sass/add-css-vars.ts @@ -0,0 +1,31 @@ +/* + * add-css-vars.ts + * + * Analyzes SCSS files for CSS variables and adds them as additional CSS variables + * for our tooling to use. + * + * Copyright (C) 2024 Posit Software, PBC + */ + +import { parse } from "scss-parser"; + +import { makeParserModule } from "./analyzer/parse.ts"; +import { cleanSassAst } from "./analyzer/clean-ast.ts"; +import { propagateDeclarationTypes } from "./analyzer/declaration-types.ts"; +import { getVariableDependencies } from "./analyzer/get-dependencies.ts"; + +const { getSassAst } = makeParserModule(parse); +export const cssVarsBlock = (scssSource: string) => { + const ast = propagateDeclarationTypes(cleanSassAst(getSassAst(scssSource))); + const deps = getVariableDependencies(ast); + + const output: string[] = [":root {"]; + for (const [dep, _] of deps) { + const decl = ast.get(dep); + if (decl.valueType === "color") { + output.push(`--quarto-scss-export-${dep}: #{$${dep}};`); + } + } + output.push("}"); + return output.join("\n"); +}; diff --git a/src/core/sass/analyzer/.gitignore b/src/core/sass/analyzer/.gitignore new file mode 100644 index 00000000000..4c43fe68f64 --- /dev/null +++ b/src/core/sass/analyzer/.gitignore @@ -0,0 +1 @@ +*.js \ No newline at end of file diff --git a/src/core/sass/analyzer/ast-utils.ts b/src/core/sass/analyzer/ast-utils.ts new file mode 100644 index 00000000000..b74bda68437 --- /dev/null +++ b/src/core/sass/analyzer/ast-utils.ts @@ -0,0 +1,69 @@ +export const walk = (node: any, cb: (node: any) => unknown) => { + if (!node || typeof node !== "object") return; + if (!cb(node)) { + return; + }; + for (const key of Object.keys(node)) { + walk(node[key], cb); + } +} + +export const withType = (node: any, func: (ast: any) => any) => { + if (!node?.type) { + return node; + } + return func(node); +} + +export const withTypeAndArray = (node: any, func: (ast: any) => any) => { + if (!node?.type) { + return node; + } + if (!node?.children || !Array.isArray(node.children)) { + return node; + } + return func(node); +} + +export const filterDeep = (outer: any, cb: (v: any) => boolean): any => + withType(outer, (ast: any) => { + return Object.fromEntries(Object.entries(ast).map(([k, v]) => { + if (Array.isArray(v)) { + return [k, v.filter(cb).map((v: any) => filterDeep(v, cb))]; + } else if (v && typeof v === "object") { + return [k, filterDeep(v, cb)]; + } else { + return [k, v]; + } + })); + }); + + export const mapDeep = (outer: any, cb: (mapped: any) => any): any => + withType(outer, (ast: any) => { + if (Array.isArray(ast.children)) { + ast.children = ast.children.map((v: any) => mapDeep(v, cb)); + } + if (Array.isArray(ast.value)) { + ast.value = ast.value.map((v: any) => mapDeep(v, cb)); + } + return cb(ast); + }); + +export const collect = (outer: any, cb: (v: any) => boolean): any[] => { + const results: any = []; + walk(outer, (node: any) => { + if (cb(node)) { + results.push(node); + } + return true; + }); + return results; +} + +export const annotateNode = (node: any, annotation: Record) => { + if (!node.annotation) { + node.annotation = {}; + } + Object.assign(node.annotation, annotation); + return node; +} \ No newline at end of file diff --git a/src/core/sass/analyzer/clean-ast.ts b/src/core/sass/analyzer/clean-ast.ts new file mode 100644 index 00000000000..34784bb3f9e --- /dev/null +++ b/src/core/sass/analyzer/clean-ast.ts @@ -0,0 +1,56 @@ +import { withTypeAndArray, filterDeep, mapDeep } from "./ast-utils.ts"; +import { isRealContent, isNotPunctuation } from "./remove-nonsemantic-entries.ts"; +import { simplifyLineInfo } from "./line-info.ts"; +import { explicitlyTagDefaultValues } from "./default-declarations.ts"; +import { fixImmediateTypes, tagNamedColors, tagColorConstructors, findDimensionValues } from "./value-types.ts"; +import { groupArguments } from "./group-arguments.ts"; +import { forwardAnnotations } from "./forward-annotations.ts"; + +const valueArrayToObjectKeys = (outer: any) => + withTypeAndArray(outer, (node: any) => { + const keys = node.children.map((v: any) => v.type); + if (keys.length !== new Set(keys).size) { + return node; + } + return { + ...node, + ...Object.fromEntries(node.children + .map((v: any) => { + const key = v.type; + let children = v.children; + return [key, {...v, children}]; + })), + }; + }); + +export const cleanSassAst = (ast: any) => { + // we now attempt to turn this glorified lexer into a real AST + + // before everything else, we associate declarations with the + // annotations that tell us which part of the theming system + // they belong to + ast = forwardAnnotations(ast); + + // before clearing out the punctuation, group arguments + ast = filterDeep(ast, isRealContent); + ast = mapDeep(ast, groupArguments); + + // clear out all the gunk from the AST + ast = filterDeep(ast, isNotPunctuation); + + ast = mapDeep(ast, simplifyLineInfo); + ast = mapDeep(ast, explicitlyTagDefaultValues); + ast = mapDeep(ast, findDimensionValues); + ast = mapDeep(ast, fixImmediateTypes); + ast = mapDeep(ast, tagColorConstructors); + ast = mapDeep(ast, tagNamedColors); + + // if the value array looks like an array of keys and values, + // insert those values into the parent object + // additionally, in these properties, if the value is an array + // with a single element, remove the array and just use the + // element. + ast = mapDeep(ast, valueArrayToObjectKeys); + + return ast; +} diff --git a/src/core/sass/analyzer/css-information.ts b/src/core/sass/analyzer/css-information.ts new file mode 100644 index 00000000000..9cf2bac0728 --- /dev/null +++ b/src/core/sass/analyzer/css-information.ts @@ -0,0 +1,186 @@ +export const units: Set = new Set([ + // found in 2024-07-29 + // length https://developer.mozilla.org/en-US/docs/Web/CSS/length, + "cap", "ic", "lh", "rcap", "rch", "rex", "ric", "rlh", "vb", "vi", "cqw", + "cqh", "cqi", "cqmin", "cqmax", + "Q", + "rem", "em", "px", "pt", "pc", "cm", "mm", "in", "ex", "ch", "vw", "vh", "vmin", "vmax", + // angle https://developer.mozilla.org/en-US/docs/Web/CSS/angle + "deg", "grad", "rad", "turn", + // time https://developer.mozilla.org/en-US/docs/Web/CSS/time + "s", "ms", + // resolution https://developer.mozilla.org/en-US/docs/Web/CSS/resolution + "dpi", "dpcm", "dppx", "x", + // frequency https://developer.mozilla.org/en-US/docs/Web/CSS/frequency + "Hz", "kHz" +]); + +export const namedColors = new Set([ + "black", + "silver", + "gray", + "white", + "maroon", + "red", + "purple", + "fuchsia", + "green", + "lime", + "olive", + "yellow", + "navy", + "blue", + "teal", + "aqua", + "aliceblue", + "antiquewhite", + "aqua", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanchedalmond", + "blue", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflowerblue", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkgrey", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategray", + "darkslategrey", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dimgrey", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "fuchsia", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "gray", + "green", + "greenyellow", + "grey", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrodyellow", + "lightgray", + "lightgreen", + "lightgrey", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategray", + "lightslategrey", + "lightsteelblue", + "lightyellow", + "lime", + "limegreen", + "linen", + "magenta", + "maroon", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "navy", + "oldlace", + "olive", + "olivedrab", + "orange", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "purple", + "rebeccapurple", + "red", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "silver", + "skyblue", + "slateblue", + "slategray", + "slategrey", + "snow", + "springgreen", + "steelblue", + "tan", + "teal", + "thistle", + "tomato", + "transparent", + "turquoise", + "violet", + "wheat", + "white", + "whitesmoke", + "yellow", + "yellowgreen", + + "currentcolor" // this is a bit of a hack, but it's used in color contexts +]); diff --git a/src/core/sass/analyzer/declaration-types.ts b/src/core/sass/analyzer/declaration-types.ts new file mode 100644 index 00000000000..f4fea5fdad1 --- /dev/null +++ b/src/core/sass/analyzer/declaration-types.ts @@ -0,0 +1,204 @@ +export const propagateDeclarationTypes = (ast: any) => { + + const declarationsToTrack = new Map(); + + const typesToSkip = new Set([ + "identifier", "boolean", + "number", "dimension", "percentage", + "string", "string_double", "string_single"]); + + const namesToIgnore: Set = new Set([ + "title-banner-image", // with this hack, we can assume all other instances of 'null' are color + "theme", + "theme-name", + "enable-grid-classes", + "enable-cssgrid", + "nav-tabs-link-active-border-color", + "navbar-light-bg", + "navbar-dark-bg", + "navbar-light-color", + "navbar-light-hover-color", + "navbar-light-active-color", + "navbar-light-disabled-color", + "navbar-light-toggler-icon-bg", + "navbar-light-toggler-border-color", + "navbar-light-brand-color", + "navbar-light-brand-hover-color", + "navbar-dark-color", + "navbar-dark-hover-color", + "navbar-dark-active-color", + "navbar-dark-disabled-color", + "navbar-dark-toggler-icon-bg", + "navbar-dark-toggler-border-color", + "navbar-dark-brand-color", + "navbar-dark-brand-hover-color", + ]); + + const speciallyKnownTypes: Record = { + "link-color": "color", + "input-border-color": "color", + "title-banner-color": "color", + "theme": "string", + }; + + for (const node of ast.children) { + if (node?.type !== "declaration") { + continue; + } + + // ignore declarations that have documented + // non-standard !default rules because of the + // way we set if() conditions in our SCSS + const varName = node?.property?.variable?.value; + if (namesToIgnore.has(varName)) { + continue; + } + const varValue = node?.value?.value; + if (declarationsToTrack.has(varName)) { + const prevDeclaration = declarationsToTrack.get(varName); + if (prevDeclaration?.value?.isDefault && + node?.value?.isDefault) { + // pass + } else if (!prevDeclaration?.value?.isDefault && + !node?.value?.isDefault) { + declarationsToTrack.set(varName, node); + } else { + // are these special cases? + if (speciallyKnownTypes[varName]) { + node.valueType = speciallyKnownTypes[varName]; + declarationsToTrack.set(varName, node); + } else { + console.log("Warning: variable redeclaration with conflicting default settings"); + console.log("variable: ", varName); + console.log("lines ", prevDeclaration?.line, node?.line); + } + } + } else { + declarationsToTrack.set(varName, node); + } + } + + const valueTypeMap: Record = { + "number": "number", + "boolean": "boolean", + "string": "string", + "dimension": "dimension", + "percentage": "percentage", + "identifier": "identifier", + "color_hex": "color", + "named_color": "color", + "string_double": "string", + "string_single": "string", + "null": "color", // This is specific to our themes, and requires excluding 'title-banner-image' above + }; + + const functionTypeResolver: Record string | undefined> = { + "theme-contrast": (_: any) => "color", + "quote": (_: any) => "string", + "url": (_: any) => "string", + "tint-color": (_: any) => "color", + "shade-color": (_: any) => "color", + "lighten": (_: any) => "color", + "darken": (_: any) => "color", + "mix": (_: any) => "color", + "shift-color": (_: any) => "color", + "linear-gradient": (_: any) => "image", + "color-contrast": (_: any) => "color", + "translate3d": (_: any) => "transform-function", + "rotate": (_: any) => "transform-function", + "translate": (_: any) => "transform-function", + "scale": (_: any) => "transform-function", + "calc": (_: any) => "calc-value", // this can be a number, percentage, or dimension, but we don't presently care + "add": (_: any) => "__unimplemented__", + "subtract": (_: any) => "__unimplemented__", + "brightness": (_: any) => "filter", + "minmax": (_: any) => "grid-template", + "var": (valueNode: any) => "__unimplemented__", + + // This is used in bslib as an instance of the hack described here: + // https://css-tricks.com/when-sass-and-new-css-features-collide/ + // it's truly atrocious and we'll never be able to track this kind of thing properly, + // but we can at least make sure it doesn't break the rest of the analysis + "Min": (_: any) => "__unimplemented__", + + "theme-override-value": (valueNode: any) => { + const defaultValue = valueNode?.arguments?.children[2]; + if (defaultValue && typeForValue(defaultValue)) { + return typeForValue(defaultValue); + } else { + return undefined; + } + }, + "if": (valueNode: any) => { + const _condition = valueNode?.arguments?.children[0]; + const trueValue = valueNode?.arguments?.children[1]; + const falseValue = valueNode?.arguments?.children[2]; + // we will assume type consistency for now + if (trueValue) { + const trueType = typeForValue(trueValue); + if (trueType) { + return trueType; + } + } + if (falseValue) { + const falseType = typeForValue(falseValue); + if (falseType) { + return falseType; + } + } + return undefined; + } + } + + const typeForValue = (valueNode: any): string | undefined => { + const nodeValueType = valueNode?.type; + if (valueTypeMap[nodeValueType]) { + return valueTypeMap[nodeValueType]; + } + if (nodeValueType === "variable") { + const nodeVariableName = valueNode?.value; + if (!declarationsToTrack.has(nodeVariableName) && !namesToIgnore.has(nodeVariableName)) { + console.log("Warning: variable used before declaration"); + console.log("variable: ", nodeVariableName, valueNode.line); + return undefined; + } else { + const valueType = declarationsToTrack.get(nodeVariableName)?.valueType; + if (valueType) { + return valueType; + } + } + } + if (nodeValueType === "function") { + const functionName = valueNode?.identifier?.value; + if (functionTypeResolver[functionName]) { + return functionTypeResolver[functionName](valueNode); + } + } + } + + // tag all declarations with values of known types + for (const [name, node] of declarationsToTrack) { + if (node?.value?.type === "value") { + const valueType = node.value.value[0].valueType || typeForValue(node.value.value[0]); + if (valueType) { + node.valueType = valueType; + } + } + } + return declarationsToTrack; + + // // now warn about variables with unknown types + // for (const [name, node] of declarationsToTrack) { + // if (node.valueType === "color") { + // console.log(name, node.line) + // } + // if (!node.valueType && node.value.value.length === 1) { + // // ignore unknown types for multi-value declarations, assume they're arrays which we don't care about. + // if (node.value.value[0]?.type === "parentheses") { + // continue; + // } + // console.log("Warning: variable with unknown type"); + // console.log("variable: ", name, node); + // } + // } +} diff --git a/src/core/sass/analyzer/default-declarations.ts b/src/core/sass/analyzer/default-declarations.ts new file mode 100644 index 00000000000..1fcb3601cc2 --- /dev/null +++ b/src/core/sass/analyzer/default-declarations.ts @@ -0,0 +1,24 @@ +import { withType } from './ast-utils.ts'; + +// FIXME in SCSS, _declarations_ have a `!default` flag, not _values_ +// but the parser we have puts the `!default` flag on the values +// we need to lift it up to the declaration level + +export const explicitlyTagDefaultValues = (outer: any) => + withType(outer, (node: any) => { + const l = node.value?.length; + if (node?.type !== "value" || l < 2) { + return node; + } + if (node.value[l - 1]?.type !== "identifier" || + node.value[l - 1]?.value !== "default" || + node.value[l - 2]?.type !== "operator" || + node.value[l - 2]?.value !== "!") { + return node; + } + return { + ...node, + value: node.value.slice(0, -2), + isDefault: true, + }; + }); \ No newline at end of file diff --git a/src/core/sass/analyzer/forward-annotations.ts b/src/core/sass/analyzer/forward-annotations.ts new file mode 100644 index 00000000000..ae6ad584480 --- /dev/null +++ b/src/core/sass/analyzer/forward-annotations.ts @@ -0,0 +1,33 @@ +import { annotateNode } from './ast-utils.ts'; + +export const forwardAnnotations = (ast: any) => { + const pragmaAnnotation = "quarto-scss-analysis-annotation"; + const currentAnnotation: Record = {}; + let hasAnnotations: boolean = false + for (const node of ast.children) { + if (node.type === "comment_singleline") { + const value = node?.value?.trim(); + if (value.startsWith(pragmaAnnotation)) { + let payload: Record = {}; + try { + payload = JSON.parse(value.slice(pragmaAnnotation.length).trim()); + } catch (e) { + console.error("Could not parse annotation payload", e); + continue; + } + for (const [key, value] of Object.entries(payload)) { + if (value === null) { + delete currentAnnotation[key]; + } else { + currentAnnotation[key] = value; + } + } + hasAnnotations = Object.keys(currentAnnotation).length > 0; + } + } + if (node.type === "declaration" && hasAnnotations) { + annotateNode(node, currentAnnotation); + } + } + return ast; +} diff --git a/src/core/sass/analyzer/get-dependencies.ts b/src/core/sass/analyzer/get-dependencies.ts new file mode 100644 index 00000000000..7247937a5d5 --- /dev/null +++ b/src/core/sass/analyzer/get-dependencies.ts @@ -0,0 +1,36 @@ +import { walk } from "./ast-utils.ts"; +// import { assert } from "jsr:@std/assert"; + +const assert = (condition: any) => { + if (!condition) { + throw new Error("Assertion failed"); + } +} + +export const getVariableDependencies = (declarations: Map) => { + const dependencies = new Map + }>(); + for (const [name, node] of declarations) { + assert(node?.type === "declaration"); + const varName = node?.property?.variable?.value; + assert(varName === name); + if (!dependencies.has(varName)) { + dependencies.set(varName, {node: node, dependencies: new Set()}); + } + const varValue = node?.value; + walk(varValue, (inner: any) => { + if (inner?.type === "variable") { + const innerName = inner?.value; + if (!innerName) { + console.log(inner); + throw new Error("stop") + } + dependencies.get(varName)!.dependencies.add(innerName); + } + return true; + }); + } + return dependencies; +} \ No newline at end of file diff --git a/src/core/sass/analyzer/group-arguments.ts b/src/core/sass/analyzer/group-arguments.ts new file mode 100644 index 00000000000..108c0136f0c --- /dev/null +++ b/src/core/sass/analyzer/group-arguments.ts @@ -0,0 +1,45 @@ +import { withType } from './ast-utils.ts'; + +// FIXME in SCSS, _declarations_ have a `!default` flag, not _values_ +// but the parser we have puts the `!default` flag on the values +// we need to lift it up to the declaration level + +export const groupArguments = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "function") { + return node; + } + const newArguments: any[] = []; + const newGroup = (): any => { + return { + type: "node_group", + start: node.start, // just so that simplifyLineInfo can handle it later + next: node.next, + children: [], + }; + } + let thisArgument = newGroup(); + const flushGroup = () => { + if (thisArgument.children.length > 1) { + newArguments.push(thisArgument); + } else { + newArguments.push(thisArgument.children[0]); + } + thisArgument = newGroup(); + } + if (node.children.length < 2) { + throw new Error("function node has no arguments"); + } + for (const arg of node.children[1].children) { + if (arg.type === "punctuation" && arg.value === ",") { + flushGroup(); + } else { + thisArgument.children.push(arg); + } + } + if (thisArgument.children.length > 0) { + flushGroup(); + } + node.children[1].children = newArguments; + return node; + }); diff --git a/src/core/sass/analyzer/line-info.ts b/src/core/sass/analyzer/line-info.ts new file mode 100644 index 00000000000..1af8936af98 --- /dev/null +++ b/src/core/sass/analyzer/line-info.ts @@ -0,0 +1,16 @@ +import { withType } from './ast-utils.ts'; + +export const simplifyLineInfo = (outer: any) => + withType(outer, (node: any) => { + const start = node?.start; + const next = node?.next; + + return { + ...node, + start: undefined, + next: undefined, + line: start?.line, + lineEnd: next?.line, + } + }); + diff --git a/src/core/sass/analyzer/parse.ts b/src/core/sass/analyzer/parse.ts new file mode 100644 index 00000000000..c52aed39b97 --- /dev/null +++ b/src/core/sass/analyzer/parse.ts @@ -0,0 +1,60 @@ +// our attempt at factoring out a clean parser +// that works in Deno and on the web + +import { walk } from "./ast-utils.ts"; + +export const makeParserModule = ( + parse: any, +) => { + return { + getSassAst: (contents: string) => { + // scss-parser doesn't support the `...` operator and it breaks their parser oO, so we remove it. + // our analysis doesn't need to know about it. + contents = contents.replaceAll("...", "_dot_dot_dot"); + // it also doesn't like some valid ways to do '@import url' + contents = contents.replaceAll("@import url", "//@import url"); + + // it also really doesn't like statemnts that don't end in a semicolon + // so, in case you are reading this code to understand why the parser is failing, + // ensure that your SCSS has semicolons at the end of every statement. + // + // This is relatively painful, because unfortunately the error message of scss-parser + // is not helpful. + + // Create an AST from a string of SCSS + // and convert it to a plain JSON object + const ast = JSON.parse(JSON.stringify(parse(contents))); + + if (!(ast.type === "stylesheet")) { + throw new Error("Expected AST to have type 'stylesheet'"); + } + if (!Array.isArray(ast.value)) { + throw new Error("Expected AST to have an array value"); + } + + // rename 'value' to 'children' + // because they also use 'value' for the value of a property + + // this is the only place we'll use 'walk' instead of the + // more explicit 'mapDeep' and 'filterValuesDeep' functions + // below, which will then assume 'children' + + walk(ast, (node: any) => { + if (Array.isArray(node)) { + return true; + } + if (["value", "identifier", "operator"].includes(node?.type)) { + return true; + } + if (!node?.value || !Array.isArray(node.value)) { + return true; + } + node.children = node.value; + delete node.value; + return true; + }); + + return ast; + }, + }; +}; diff --git a/src/core/sass/analyzer/remove-nonsemantic-entries.ts b/src/core/sass/analyzer/remove-nonsemantic-entries.ts new file mode 100644 index 00000000000..c11e63ee448 --- /dev/null +++ b/src/core/sass/analyzer/remove-nonsemantic-entries.ts @@ -0,0 +1,19 @@ +export const isRealContent = (v: any) => { + if (!v?.type) { + return true; + } + if (["space", "comment_singleline", "comment_multiline"].includes(v.type)) { + return false; + } + return true; +} + +export const isNotPunctuation = (v: any) => { + if (!v?.type) { + return true; + } + if (v.type === "punctuation") { + return false; + } + return true +} diff --git a/src/core/sass/analyzer/value-types.ts b/src/core/sass/analyzer/value-types.ts new file mode 100644 index 00000000000..662574d6905 --- /dev/null +++ b/src/core/sass/analyzer/value-types.ts @@ -0,0 +1,134 @@ +import { withType } from "./ast-utils.ts"; +import { namedColors, units } from "./css-information.ts"; + +const typedImmediateValues: Record = { + false: { type: "boolean", value: false }, + true: { type: "boolean", value: true }, + null: { type: "null", value: null }, +} + +export const fixImmediateTypes = (outer: any) => + withType(outer, (node: any) => { + if (node.type === "identifier" && typedImmediateValues[node.value]) { + return {...node, ...typedImmediateValues[node.value]}; + } + return node; + }); + +export const tagNamedColors = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "identifier" || !namedColors.has(node?.value)) { + return node; + } + return { + ...node, + type: "named_color", + }; + }); + +export const tagColorConstructors = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "function") { + return node; + } + const name = node.children[0].value; + if (node.children[0].type !== "identifier" || !name) { + return node; + } + const colorConstructors = new Set([ + "rgb", "rgba", "hsl", "hsla", + ]); + if (colorConstructors.has(name)) { + return { + ...node, + valueType: "color", + }; + } + return node; + }); + + // this also finds percentages +export const findDimensionValues = (outer: any) => + withType(outer, (node: any) => { + const replace = (value: any[]) => { + const newValues = []; + for (let i = 0; i < value.length; ++i) { + const thisValue = value[i]; + const nextValue = value[i + 1]; + if (thisValue?.type === "number" && + nextValue?.type === "identifier" && + units.has(nextValue?.value)) { + newValues.push({ + ...thisValue, + type: "dimension", + unit: nextValue.value, + }); + ++i; + } else if (thisValue?.type === "number" && + nextValue?.type === "operator" && + nextValue?.value === "%") { + // this might be chancy if there's stuff like (3 % 2) floating around + // I couldn't find any in our .scss files, but :grimace: + newValues.push({ + ...thisValue, + type: "percentage", + }); + ++i; + } else { + newValues.push(thisValue); + } + } + return newValues; + } + if (node.type === "value" && Array.isArray(node.value)) { + return { + ...node, + value: replace(node.value), + }; + } + if (node.type === "node_group") { + return { + ...node, + children: replace(node.children), + } + } + return node; + // if (node?.type !== "value") { + // return node; + // } + // const value = node?.value; + // if (!Array.isArray(value)) { + // return node; + // } + // const newValues = []; + // for (let i = 0; i < value.length; ++i) { + // const thisValue = value[i]; + // const nextValue = value[i + 1]; + // if (thisValue?.type === "number" && + // nextValue?.type === "identifier" && + // units.has(nextValue?.value)) { + // newValues.push({ + // ...thisValue, + // type: "dimension", + // unit: nextValue.value, + // }); + // ++i; + // } else if (thisValue?.type === "number" && + // nextValue?.type === "operator" && + // nextValue?.value === "%") { + // // this might be chancy if there's stuff like (3 % 2) floating around + // // I couldn't find any in our .scss files, but :grimace: + // newValues.push({ + // ...thisValue, + // type: "percentage", + // }); + // ++i; + // } else { + // newValues.push(thisValue); + // } + // } + // return { + // ...node, + // value: newValues, + // }; + }); diff --git a/src/core/sass/brand.ts b/src/core/sass/brand.ts index c5a67ae3bde..6fddc8b20cb 100644 --- a/src/core/sass/brand.ts +++ b/src/core/sass/brand.ts @@ -14,8 +14,16 @@ import { SassBundleLayers, } from "../../config/types.ts"; import { ProjectContext } from "../../project/types.ts"; +import { + BrandFont, + BrandFontBunny, + BrandFontGoogle, + BrandFontWeight, + BrandTypographyOptions, +} from "../../resources/types/schema-types.ts"; const defaultColorNameMap: Record = { + "pre-color": "foreground", "body-bg": "background", "body-color": "foreground", "body-secondary-color": "secondary", @@ -24,6 +32,34 @@ const defaultColorNameMap: Record = { "body-tertiary": "secondary", }; +const brandFontWeightValue: (weight: BrandFontWeight) => number = (weight) => { + if (typeof weight === "number") { + return weight; + } + // from https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#common_weight_name_mapping + // excluding 950 + const stringMap: Record = { + thin: 100, + "extra-light": 200, + "ultra-light": 200, + light: 300, + normal: 400, + regular: 400, + medium: 500, + "semi-bold": 600, + "demi-bold": 600, + bold: 700, + "extra-bold": 800, + "ultra-bold": 800, + black: 900, + }; + const result = stringMap[weight]; + if (result === undefined) { + throw new Error(`Unknown font weight ${weight}`); + } + return result; +}; + export async function brandBootstrapSassBundles( fileName: string | undefined, project: ProjectContext, @@ -43,6 +79,86 @@ export async function brandBootstrapSassBundles( }, ); } + +const bunnyFontImportString = (description: BrandFontBunny["bunny"]) => { + const bunnyName = (name: string) => name.replace(/ /g, "-"); + if (typeof description === "string") { + return `@import url('https://fonts.bunny.net/css?family=${ + bunnyName(description) + }:400,700');`; + } else { + const bunnyFamily = description.family; + if (!bunnyFamily) { + throw new Error("Bunny font family not specified"); + } + const styles = !description.style + ? ["normal", "italic"] + : typeof description.style === "string" + ? [description.style] + : description.style; + const weightArray = !description.weight + ? [400, 700] + : typeof description.weight === "number" || + typeof description.weight === "string" + ? [brandFontWeightValue(description.weight)] + : description.weight.map((w) => brandFontWeightValue(w)); + const display = description.display ?? "swap"; + const weights = styles.includes("italic") + ? weightArray.map((w) => `${w}i`).join(",") + + "," + + weightArray.join(",") + : weightArray.join(","); + // @import url(https://fonts.bunny.net/css?family=albert-sans:200i,400,700); + return `@import url('https://fonts.bunny.net/css?family=${ + bunnyName(bunnyFamily) + }:${weights}');`; + } +}; + +const googleFontImportString = (description: BrandFontGoogle["google"]) => { + if (typeof description === "string") { + return `@import url('https://fonts.googleapis.com/css2?family=${ + description.replace( + / /g, + "+", + ) + }:ital,wght@400;700&display=swap');`; + } else { + const googleFamily = typeof description === "string" + ? description + : description.family; + const styles = !description.style + ? ["normal", "italic"] + : typeof description.style === "string" + ? [description.style] + : description.style; + const weightArray = !description.weight + ? [400, 700] + : typeof description.weight === "number" || + typeof description.weight === "string" + ? [brandFontWeightValue(description.weight)] + : description.weight.map((w) => brandFontWeightValue(w)); + const display = description.display ?? "swap"; + let styleString = ""; + let weights = ""; + + if (styles.includes("italic")) { + styleString = "ital,"; + weights = weightArray.map((w) => `0,${w}`).join(";") + + ";" + + weightArray.map((w) => `1,${w}`).join(";"); + } else { + weights = !description.weight ? "400;700" : weightArray.join(";"); + } + return `@import url('https://fonts.googleapis.com/css2?family=${ + googleFamily!.replace( + / /g, + "+", + ) + }:${styleString}wght@${weights}&display=${display}');`; + } +}; + export async function brandBootstrapSassBundleLayers( fileName: string | undefined, project: ProjectContext, @@ -91,6 +207,142 @@ export async function brandBootstrapSassBundleLayers( sassBundles.push(colorBundle); } + if (brand?.data.typography) { + const typographyVariables: string[] = [ + "/* typography variables from _brand.yml */", + ]; + const typographyImports: string[] = []; + const tWith = brand.data.typography.with; + + const getFontFamily = (family: string | undefined) => { + if (!tWith || !family || !tWith[family]) { + throw new Error( + `Typography family ${family} description not found in _brand.yml`, + ); + } + return tWith[family]; + }; + + const resolveGoogleFontFamily = ( + font: BrandFont, + ): string | undefined => { + const description = (font as BrandFontGoogle).google; + if (!description) { + return undefined; + } + const googleFamily = typeof description === "string" + ? description + : description.family; + if (!googleFamily) { + return undefined; + } + typographyVariables.push(googleFontImportString(description)); + return googleFamily; + }; + + const resolveBunnyFontFamily = ( + font: BrandFont, + ): string | undefined => { + const description = (font as BrandFontBunny).bunny; + if (!description) { + return undefined; + } + const bunnyFamily = typeof description === "string" + ? description + : description.family; + if (!bunnyFamily) { + return undefined; + } + typographyVariables.push(bunnyFontImportString(description)); + return bunnyFamily; + }; + + type HTMLFontInformation = { [key: string]: unknown }; + + const resolveHTMLFontInformation = ( + kind: "base" | "headings" | "monospace", + ): HTMLFontInformation | undefined => { + const resolvedFontOptions = brand.data.typography?.[kind]; + if (!resolvedFontOptions) { + return undefined; + } + const family = resolvedFontOptions.family; + const font = getFontFamily(family); + const result: HTMLFontInformation = {}; + + result.family = resolveGoogleFontFamily(font) ?? + resolveBunnyFontFamily(font); + result.lineHeight = resolvedFontOptions["line-height"]; + if ((resolvedFontOptions as any).size) { + result[kind + "-size"] = (resolvedFontOptions as any).size; + } + return result; + }; + + // see + // https://github.com/posit-dev/brand-yml/issues/15: line-height in code + // https://github.com/posit-dev/brand-yml/issues/16: where should color be? + + const variableTranslations: Record = { + "base": [ + ["family", "font-family-base"], // bootstrap + ["family", "mainFont"], // revealjs + ["base-size", "font-size-base"], // bootstrap + ["base-size", "presentation-font-size-root"], // revealjs + ["lineHeight", "line-height-base"], + ["lineHeight", "presentation-line-height"], + ], + "headings": [ + ["family", "headings-font-family"], // bootstrap + ["family", "presentation-heading-font"], // revealjs + ["lineHeight", "headings-line-height"], // bootstrap + ["lineHeight", "presentation-heading-line-height"], // revealjs + ], + "monospace": [ + ["family", "font-family-monospace"], // bootstrap + revealjs + ["monospace-size", "code-font-size"], // bootstrap + ["monospace-size", "code-block-font-size"], // revealjs + ["lineHeight", "pre-line-height"], // bootstrap + ["lineHeight", "code-block-line-height"], // revealjs + ], + }; + + for (const kind of ["base", "headings", "monospace"]) { + const fontInformation = resolveHTMLFontInformation( + kind as "base" | "headings" | "monospace", + ); + if (!fontInformation) { + continue; + } + const variables = variableTranslations[kind]; + if (!variables) { + throw new Error(`Unknown typography kind ${kind}`); + } + for (const variable of variables) { + const source = variable[0]; + const target = variable[1]; + if (fontInformation[source]) { + typographyVariables.push( + `$${target}: ${fontInformation[source]} !default;`, + ); + } + } + } + + const typographyBundle: SassBundleLayers = { + key, + // dependency: "bootstrap", + quarto: { + defaults: typographyVariables.join("\n"), + uses: typographyImports.join("\n"), + functions: "", + mixins: "", + rules: "", + }, + }; + sassBundles.push(typographyBundle); + } + return sassBundles; } diff --git a/src/core/schema/types-from-schema.ts b/src/core/schema/types-from-schema.ts index 30833840cc1..17467832a8b 100644 --- a/src/core/schema/types-from-schema.ts +++ b/src/core/schema/types-from-schema.ts @@ -221,9 +221,9 @@ export function schemaToType(schema: any): string { ); } if (schema.object) { - const mainType = (schema.object.properties === undefined) - ? "JsonObject" - : ("{" + + let mainType: string = ""; + if (schema.object.properties) { + mainType = "{" + Object.entries(schema.object.properties).map(([key, value]) => { const optionalFlag = schema.object.required === "all" ? false @@ -234,7 +234,13 @@ export function schemaToType(schema: any): string { schemaToType(value) }`; }).sort(([k1, _v1], [k2, _v2]) => k1.localeCompare(k2)).join("; ") + - "}"); + "}"; + } else if (schema.object.additionalProperties) { + mainType = "{ [key: string]: " + + schemaToType(schema.object.additionalProperties) + " }"; + } else { + mainType = "JsonObject"; + } if (schema.object?.super?.resolveRef) { return document( "(" + mainType + " & " + diff --git a/src/dev_import_map.json b/src/dev_import_map.json index ab018ac19d4..56e0a676ad4 100644 --- a/src/dev_import_map.json +++ b/src/dev_import_map.json @@ -48,6 +48,7 @@ "js-yaml": "./vendor/cdn.skypack.dev/js-yaml@4.1.0.js", "slimdom": "./vendor/cdn.skypack.dev/slimdom@4.2.0.js", "fontoxpath": "./vendor/cdn.skypack.dev/fontoxpath@3.29.1.js", + "scss-parser": "./vendor/cdn.skypack.dev/scss-parser@1.0.6.js", "https://deno.land/std@0.161.0/": "./vendor/deno.land/std@0.217.0/", "https://deno.land/std@0.101.0/": "./vendor/deno.land/std@0.217.0/", "https://deno.land/std@0.105.0/": "./vendor/deno.land/std@0.217.0/", @@ -74,7 +75,6 @@ "cliffy/command/command.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/command/command.ts", "fmt/colors.ts": "./vendor/deno.land/std@0.217.0/fmt/colors.ts", "cliffy/prompt/select.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/prompt/select.ts", - "cliffy/prompt/confirm.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts", "fs/expand_glob.ts": "./vendor/deno.land/std@0.217.0/fs/expand_glob.ts", "fs/exists.ts": "./vendor/deno.land/std@0.217.0/fs/exists.ts", "encoding/base64.ts": "./vendor/deno.land/std@0.217.0/encoding/base64.ts", @@ -132,12 +132,14 @@ "xml/mod.ts": "./vendor/deno.land/x/xml@2.1.1/mod.ts", "path/dirname.ts": "./vendor/deno.land/std@0.217.0/path/dirname.ts", "xmlp/mod.ts": "./vendor/deno.land/x/xmlp@v0.2.8/mod.ts", + "cliffy/prompt/confirm.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts", "io/copy.ts": "./vendor/deno.land/std@0.217.0/io/copy.ts", "archive/tar.ts": "./vendor/deno.land/std@0.217.0/archive/tar.ts", "cliffy/prompt/input.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/prompt/input.ts", "encoding/hex.ts": "./vendor/deno.land/std@0.217.0/encoding/hex.ts", "cliffy/prompt/secret.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/prompt/secret.ts", "another_cookiejar/mod.ts": "./vendor/deno.land/x/another_cookiejar@v5.0.3/mod.ts", + "cliffy/command/_errors.ts": "./vendor/deno.land/x/cliffy@v1.0.0-rc.3/command/_errors.ts", "https://deno.land/std@0.105.0/path/mod.ts": "./vendor/deno.land/std@0.217.0/path/mod.ts", "https://cdn.skypack.dev/": "./vendor/cdn.skypack.dev/", "https://deno.land/": "./vendor/deno.land/" @@ -309,6 +311,7 @@ "/-/mensch@v0.3.4-bYdFVPGjq4ZCCd5bQOiD/dist=es2019,mode=imports/optimized/mensch.js": "./vendor/cdn.skypack.dev/-/mensch@v0.3.4-bYdFVPGjq4ZCCd5bQOiD/dist=es2019,mode=imports/optimized/mensch.js", "/-/slick@v1.12.2-aV7vJdJVxGxCoP6YSykY/dist=es2019,mode=imports/unoptimized/parser.js": "./vendor/cdn.skypack.dev/-/slick@v1.12.2-aV7vJdJVxGxCoP6YSykY/dist=es2019,mode=imports/unoptimized/parser.js", "/-/entities@v4.3.0-V4vIlnoYfSBRg1gj9BOL/dist=es2019,mode=imports/optimized/entities/lib/escape.js": "./vendor/cdn.skypack.dev/-/entities@v4.3.0-V4vIlnoYfSBRg1gj9BOL/dist=es2019,mode=imports/optimized/entities/lib/escape.js", + "/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js": "./vendor/cdn.skypack.dev/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js", "/-/whynot@v5.0.0-TIWeI93neceQKiPCfmA6/dist=es2019,mode=imports/optimized/whynot.js": "./vendor/cdn.skypack.dev/-/whynot@v5.0.0-TIWeI93neceQKiPCfmA6/dist=es2019,mode=imports/optimized/whynot.js", "/-/@observablehq/parser@v4.5.0-rWZiNfab8flhVomtfVvr/dist=es2019,mode=imports/optimized/@observablehq/parser.js": "./vendor/cdn.skypack.dev/-/@observablehq/parser@v4.5.0-rWZiNfab8flhVomtfVvr/dist=es2019,mode=imports/optimized/@observablehq/parser.js", "/-/acorn-class-fields@v1.0.0-VEggkLxq9gMrdwRuKkzZ/dist=es2019,mode=imports/optimized/acorn-class-fields.js": "./vendor/cdn.skypack.dev/-/acorn-class-fields@v1.0.0-VEggkLxq9gMrdwRuKkzZ/dist=es2019,mode=imports/optimized/acorn-class-fields.js", @@ -336,6 +339,7 @@ "/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniq.js": "./vendor/cdn.skypack.dev/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniq.js", "/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniqBy.js": "./vendor/cdn.skypack.dev/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniqBy.js", "/-/moment-guess@v1.2.4-bDXl7KQy0hLGNuGhyGb4/dist=es2019,mode=imports/optimized/moment-guess.js": "./vendor/cdn.skypack.dev/-/moment-guess@v1.2.4-bDXl7KQy0hLGNuGhyGb4/dist=es2019,mode=imports/optimized/moment-guess.js", + "/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js": "./vendor/cdn.skypack.dev/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js", "/-/slimdom@v4.2.0-QzuHPU3P67qdOzczKt6u/dist=es2019,mode=imports/optimized/slimdom.js": "./vendor/cdn.skypack.dev/-/slimdom@v4.2.0-QzuHPU3P67qdOzczKt6u/dist=es2019,mode=imports/optimized/slimdom.js" } } diff --git a/src/import_map.json b/src/import_map.json index f49fbca0a80..f629d7ffeba 100644 --- a/src/import_map.json +++ b/src/import_map.json @@ -49,6 +49,7 @@ "slimdom": "https://cdn.skypack.dev/slimdom@4.2.0", "fontoxpath": "https://cdn.skypack.dev/fontoxpath@3.29.1", + "scss-parser": "https://cdn.skypack.dev/scss-parser@1.0.6", "https://deno.land/std@0.161.0/": "https://deno.land/std@0.217.0/", "https://deno.land/std@0.101.0/": "https://deno.land/std@0.217.0/", diff --git a/src/resources/conf/deno-ts-compile.jsonc b/src/resources/conf/deno-ts-compile.jsonc index efbc5a7b4fe..f7b1ca76da0 100644 --- a/src/resources/conf/deno-ts-compile.jsonc +++ b/src/resources/conf/deno-ts-compile.jsonc @@ -1,7 +1,7 @@ { "compilerOptions": { "allowJs": true, - "lib": ["DOM", "ES2020"], + "lib": ["DOM", "ES2021"], "strict": true, /* these are strictly for deno check; we never use deno to emit */ diff --git a/src/resources/editor/tools/vs-code.mjs b/src/resources/editor/tools/vs-code.mjs index 3c9c9f8af21..0f7856f197a 100644 --- a/src/resources/editor/tools/vs-code.mjs +++ b/src/resources/editor/tools/vs-code.mjs @@ -12223,7 +12223,9 @@ var require_yaml_intelligence_resources = __commonJS({ id: "brand-font-with", description: "Font files and definitions for the brand.", object: { - closed: false + additionalProperties: { + ref: "brand-font" + } } }, { @@ -12233,6 +12235,9 @@ var require_yaml_intelligence_resources = __commonJS({ { ref: "brand-font-google" }, + { + ref: "brand-font-bunny" + }, { ref: "brand-font-file" }, @@ -12253,7 +12258,20 @@ var require_yaml_intelligence_resources = __commonJS({ 600, 700, 800, - 900 + 900, + "thin", + "extra-light", + "ultra-light", + "light", + "normal", + "regular", + "medium", + "semi-bold", + "demi-bold", + "bold", + "extra-bold", + "ultra-bold", + "black" ], default: 400 }, @@ -12266,58 +12284,64 @@ var require_yaml_intelligence_resources = __commonJS({ ], default: "normal" }, + { + id: "brand-font-common", + schema: { + anyOf: [ + "string", + { + object: { + closed: true, + properties: { + family: { + description: "The font family name, which must match the name of the font on the foundry website.", + schema: "string" + }, + weight: { + description: "The font weights to include.", + maybeArrayOf: { + ref: "brand-font-weight" + }, + default: [ + 400, + 700 + ] + }, + style: { + description: "The font styles to include.", + maybeArrayOf: { + ref: "brand-font-style" + }, + default: [ + "normal", + "italic" + ] + }, + display: { + description: "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", + enum: [ + "auto", + "block", + "swap", + "fallback", + "optional" + ], + default: "swap" + } + } + } + } + ] + } + }, { id: "brand-font-google", - description: "A Google Font definition.", + description: "A font definition from Google Fonts.", object: { closed: true, properties: { google: { - anyOf: [ - "string", - { - object: { - closed: true, - properties: { - family: { - description: "The font family name, which must match the name of the font on Google Fonts.", - schema: "string" - }, - weight: { - description: "The font weights to include.", - maybeArrayOf: { - ref: "brand-font-weight" - }, - default: [ - 400, - 700 - ] - }, - style: { - description: "The font styles to include.", - maybeArrayOf: { - ref: "brand-font-style" - }, - default: [ - "normal", - "italic" - ] - }, - display: { - description: "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", - enum: [ - "auto", - "block", - "swap", - "fallback", - "optional" - ], - default: "swap" - } - } - } - } - ] + ref: "brand-font-common" } }, required: [ @@ -12325,6 +12349,21 @@ var require_yaml_intelligence_resources = __commonJS({ ] } }, + { + id: "brand-font-bunny", + description: "A font definition from fonts.bunny.net.", + object: { + closed: true, + properties: { + bunny: { + ref: "brand-font-common" + } + }, + required: [ + "bunny" + ] + } + }, { id: "brand-font-file", description: "A method for providing font files directly, either locally or from an online location.", @@ -21400,7 +21439,7 @@ var require_yaml_intelligence_resources = __commonJS({ "Short/abbreviated form of container-title;", "A minor contributor to the item; typically cited using \u201Cwith\u201D before\nthe name when listed in a bibliography.", "Curator of an exhibit or collection (e.g. in a museum).", - "Physical (e.g. size) or temporal (e.g.\uFFFD\uFFFDrunning time) dimensions of\nthe item.", + "Physical (e.g. size) or temporal (e.g. running time) dimensions of\nthe item.", "Director (e.g. of a film).", "Minor subdivision of a court with a jurisdiction for a\nlegal item", "(Container) edition holding the item (e.g. \u201C3\u201D when citing a chapter\nin the third edition of a book).", @@ -21583,6 +21622,11 @@ var require_yaml_intelligence_resources = __commonJS({ "A link or path to the brand\u2019s medium-sized logo, or a link or path to\nboth the light and dark versions.", "A link or path to the brand\u2019s large- or full-sized logo, or a link or\npath to both the light and dark versions.", "Names of customizeable logos", + "Source path or source path with layout options for logo", + "X-Y positioning of logo", + "Padding of logo", + "Width of logo", + "Source path of logo", "The brand\u2019s custom color palette and theme.", "The brand\u2019s custom color palette. Any number of colors can be\ndefined, each color having a custom name.", "The foreground color, used for text.", @@ -21615,11 +21659,12 @@ var require_yaml_intelligence_resources = __commonJS({ "Font files and definitions for the brand.", "A font weight.", "A font style.", - "A Google Font definition.", - "The font family name, which must match the name of the font on Google\nFonts.", + "The font family name, which must match the name of the font on the\nfoundry website.", "The font weights to include.", "The font styles to include.", "The font display method, determines how a font face is font face is\nshown depending on its download status and readiness for use.", + "A font definition from Google Fonts.", + "A font definition from fonts.bunny.net.", "A method for providing font files directly, either locally or from an\nonline location.", "The font family name.", "The font files to include. These can be local or online. Local file\npaths should be relative to the brand.yml file. Online\npaths should be complete URLs.", @@ -23908,12 +23953,12 @@ var require_yaml_intelligence_resources = __commonJS({ mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 187585, + _internalId: 187636, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 187577, + _internalId: 187628, type: "enum", enum: [ "png", @@ -23929,7 +23974,7 @@ var require_yaml_intelligence_resources = __commonJS({ exhaustiveCompletions: true }, theme: { - _internalId: 187584, + _internalId: 187635, type: "anyOf", anyOf: [ { diff --git a/src/resources/editor/tools/yaml/web-worker.js b/src/resources/editor/tools/yaml/web-worker.js index 6983ad64ff8..e68bac73b54 100644 --- a/src/resources/editor/tools/yaml/web-worker.js +++ b/src/resources/editor/tools/yaml/web-worker.js @@ -12224,7 +12224,9 @@ try { id: "brand-font-with", description: "Font files and definitions for the brand.", object: { - closed: false + additionalProperties: { + ref: "brand-font" + } } }, { @@ -12234,6 +12236,9 @@ try { { ref: "brand-font-google" }, + { + ref: "brand-font-bunny" + }, { ref: "brand-font-file" }, @@ -12254,7 +12259,20 @@ try { 600, 700, 800, - 900 + 900, + "thin", + "extra-light", + "ultra-light", + "light", + "normal", + "regular", + "medium", + "semi-bold", + "demi-bold", + "bold", + "extra-bold", + "ultra-bold", + "black" ], default: 400 }, @@ -12267,58 +12285,64 @@ try { ], default: "normal" }, + { + id: "brand-font-common", + schema: { + anyOf: [ + "string", + { + object: { + closed: true, + properties: { + family: { + description: "The font family name, which must match the name of the font on the foundry website.", + schema: "string" + }, + weight: { + description: "The font weights to include.", + maybeArrayOf: { + ref: "brand-font-weight" + }, + default: [ + 400, + 700 + ] + }, + style: { + description: "The font styles to include.", + maybeArrayOf: { + ref: "brand-font-style" + }, + default: [ + "normal", + "italic" + ] + }, + display: { + description: "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", + enum: [ + "auto", + "block", + "swap", + "fallback", + "optional" + ], + default: "swap" + } + } + } + } + ] + } + }, { id: "brand-font-google", - description: "A Google Font definition.", + description: "A font definition from Google Fonts.", object: { closed: true, properties: { google: { - anyOf: [ - "string", - { - object: { - closed: true, - properties: { - family: { - description: "The font family name, which must match the name of the font on Google Fonts.", - schema: "string" - }, - weight: { - description: "The font weights to include.", - maybeArrayOf: { - ref: "brand-font-weight" - }, - default: [ - 400, - 700 - ] - }, - style: { - description: "The font styles to include.", - maybeArrayOf: { - ref: "brand-font-style" - }, - default: [ - "normal", - "italic" - ] - }, - display: { - description: "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", - enum: [ - "auto", - "block", - "swap", - "fallback", - "optional" - ], - default: "swap" - } - } - } - } - ] + ref: "brand-font-common" } }, required: [ @@ -12326,6 +12350,21 @@ try { ] } }, + { + id: "brand-font-bunny", + description: "A font definition from fonts.bunny.net.", + object: { + closed: true, + properties: { + bunny: { + ref: "brand-font-common" + } + }, + required: [ + "bunny" + ] + } + }, { id: "brand-font-file", description: "A method for providing font files directly, either locally or from an online location.", @@ -21401,7 +21440,7 @@ try { "Short/abbreviated form of container-title;", "A minor contributor to the item; typically cited using \u201Cwith\u201D before\nthe name when listed in a bibliography.", "Curator of an exhibit or collection (e.g. in a museum).", - "Physical (e.g. size) or temporal (e.g.\uFFFD\uFFFDrunning time) dimensions of\nthe item.", + "Physical (e.g. size) or temporal (e.g. running time) dimensions of\nthe item.", "Director (e.g. of a film).", "Minor subdivision of a court with a jurisdiction for a\nlegal item", "(Container) edition holding the item (e.g. \u201C3\u201D when citing a chapter\nin the third edition of a book).", @@ -21584,6 +21623,11 @@ try { "A link or path to the brand\u2019s medium-sized logo, or a link or path to\nboth the light and dark versions.", "A link or path to the brand\u2019s large- or full-sized logo, or a link or\npath to both the light and dark versions.", "Names of customizeable logos", + "Source path or source path with layout options for logo", + "X-Y positioning of logo", + "Padding of logo", + "Width of logo", + "Source path of logo", "The brand\u2019s custom color palette and theme.", "The brand\u2019s custom color palette. Any number of colors can be\ndefined, each color having a custom name.", "The foreground color, used for text.", @@ -21616,11 +21660,12 @@ try { "Font files and definitions for the brand.", "A font weight.", "A font style.", - "A Google Font definition.", - "The font family name, which must match the name of the font on Google\nFonts.", + "The font family name, which must match the name of the font on the\nfoundry website.", "The font weights to include.", "The font styles to include.", "The font display method, determines how a font face is font face is\nshown depending on its download status and readiness for use.", + "A font definition from Google Fonts.", + "A font definition from fonts.bunny.net.", "A method for providing font files directly, either locally or from an\nonline location.", "The font family name.", "The font files to include. These can be local or online. Local file\npaths should be relative to the brand.yml file. Online\npaths should be complete URLs.", @@ -23909,12 +23954,12 @@ try { mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 187585, + _internalId: 187636, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 187577, + _internalId: 187628, type: "enum", enum: [ "png", @@ -23930,7 +23975,7 @@ try { exhaustiveCompletions: true }, theme: { - _internalId: 187584, + _internalId: 187635, type: "anyOf", anyOf: [ { diff --git a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json index 2e2e9dc6c9f..949b774e239 100644 --- a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json +++ b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json @@ -5195,7 +5195,9 @@ "id": "brand-font-with", "description": "Font files and definitions for the brand.", "object": { - "closed": false + "additionalProperties": { + "ref": "brand-font" + } } }, { @@ -5205,6 +5207,9 @@ { "ref": "brand-font-google" }, + { + "ref": "brand-font-bunny" + }, { "ref": "brand-font-file" }, @@ -5225,7 +5230,20 @@ 600, 700, 800, - 900 + 900, + "thin", + "extra-light", + "ultra-light", + "light", + "normal", + "regular", + "medium", + "semi-bold", + "demi-bold", + "bold", + "extra-bold", + "ultra-bold", + "black" ], "default": 400 }, @@ -5238,58 +5256,64 @@ ], "default": "normal" }, + { + "id": "brand-font-common", + "schema": { + "anyOf": [ + "string", + { + "object": { + "closed": true, + "properties": { + "family": { + "description": "The font family name, which must match the name of the font on the foundry website.", + "schema": "string" + }, + "weight": { + "description": "The font weights to include.", + "maybeArrayOf": { + "ref": "brand-font-weight" + }, + "default": [ + 400, + 700 + ] + }, + "style": { + "description": "The font styles to include.", + "maybeArrayOf": { + "ref": "brand-font-style" + }, + "default": [ + "normal", + "italic" + ] + }, + "display": { + "description": "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", + "enum": [ + "auto", + "block", + "swap", + "fallback", + "optional" + ], + "default": "swap" + } + } + } + } + ] + } + }, { "id": "brand-font-google", - "description": "A Google Font definition.", + "description": "A font definition from Google Fonts.", "object": { "closed": true, "properties": { "google": { - "anyOf": [ - "string", - { - "object": { - "closed": true, - "properties": { - "family": { - "description": "The font family name, which must match the name of the font on Google Fonts.", - "schema": "string" - }, - "weight": { - "description": "The font weights to include.", - "maybeArrayOf": { - "ref": "brand-font-weight" - }, - "default": [ - 400, - 700 - ] - }, - "style": { - "description": "The font styles to include.", - "maybeArrayOf": { - "ref": "brand-font-style" - }, - "default": [ - "normal", - "italic" - ] - }, - "display": { - "description": "The font display method, determines how a font face is font face is shown depending on its download status and readiness for use.\n", - "enum": [ - "auto", - "block", - "swap", - "fallback", - "optional" - ], - "default": "swap" - } - } - } - } - ] + "ref": "brand-font-common" } }, "required": [ @@ -5297,6 +5321,21 @@ ] } }, + { + "id": "brand-font-bunny", + "description": "A font definition from fonts.bunny.net.", + "object": { + "closed": true, + "properties": { + "bunny": { + "ref": "brand-font-common" + } + }, + "required": [ + "bunny" + ] + } + }, { "id": "brand-font-file", "description": "A method for providing font files directly, either locally or from an online location.", @@ -14372,7 +14411,7 @@ "Short/abbreviated form of container-title;", "A minor contributor to the item; typically cited using “with” before\nthe name when listed in a bibliography.", "Curator of an exhibit or collection (e.g. in a museum).", - "Physical (e.g. size) or temporal (e.g.��running time) dimensions of\nthe item.", + "Physical (e.g. size) or temporal (e.g. running time) dimensions of\nthe item.", "Director (e.g. of a film).", "Minor subdivision of a court with a jurisdiction for a\nlegal item", "(Container) edition holding the item (e.g. “3” when citing a chapter\nin the third edition of a book).", @@ -14555,6 +14594,11 @@ "A link or path to the brand’s medium-sized logo, or a link or path to\nboth the light and dark versions.", "A link or path to the brand’s large- or full-sized logo, or a link or\npath to both the light and dark versions.", "Names of customizeable logos", + "Source path or source path with layout options for logo", + "X-Y positioning of logo", + "Padding of logo", + "Width of logo", + "Source path of logo", "The brand’s custom color palette and theme.", "The brand’s custom color palette. Any number of colors can be\ndefined, each color having a custom name.", "The foreground color, used for text.", @@ -14587,11 +14631,12 @@ "Font files and definitions for the brand.", "A font weight.", "A font style.", - "A Google Font definition.", - "The font family name, which must match the name of the font on Google\nFonts.", + "The font family name, which must match the name of the font on the\nfoundry website.", "The font weights to include.", "The font styles to include.", "The font display method, determines how a font face is font face is\nshown depending on its download status and readiness for use.", + "A font definition from Google Fonts.", + "A font definition from fonts.bunny.net.", "A method for providing font files directly, either locally or from an\nonline location.", "The font family name.", "The font files to include. These can be local or online. Local file\npaths should be relative to the brand.yml file. Online\npaths should be complete URLs.", @@ -16880,12 +16925,12 @@ "mermaid": "%%" }, "handlers/mermaid/schema.yml": { - "_internalId": 187585, + "_internalId": 187636, "type": "object", "description": "be an object", "properties": { "mermaid-format": { - "_internalId": 187577, + "_internalId": 187628, "type": "enum", "enum": [ "png", @@ -16901,7 +16946,7 @@ "exhaustiveCompletions": true }, "theme": { - "_internalId": 187584, + "_internalId": 187635, "type": "anyOf", "anyOf": [ { diff --git a/src/resources/formats/html/bootstrap/_bootstrap-variables.scss b/src/resources/formats/html/bootstrap/_bootstrap-variables.scss index 036ee20b233..3d8f07d395c 100644 --- a/src/resources/formats/html/bootstrap/_bootstrap-variables.scss +++ b/src/resources/formats/html/bootstrap/_bootstrap-variables.scss @@ -8,8 +8,10 @@ $white: #ffffff !default; $gray-200: #e9ecef !default; $gray-100: #f8f9fa !default; $gray-900: #212529 !default; +// Pending SCSS change until Charles clears it with us +// $link-color: theme-override-value($theme-name, "link-color", $primary) !default; +// $link-color: $primary !default; - $link-color: if( $link-color == $blue, theme-override-value($theme-name, "link-color", $link-color), diff --git a/src/resources/formats/html/bootstrap/dist/scss/_reboot.scss b/src/resources/formats/html/bootstrap/dist/scss/_reboot.scss index 017316b01ea..93a7d8cc3ea 100644 --- a/src/resources/formats/html/bootstrap/dist/scss/_reboot.scss +++ b/src/resources/formats/html/bootstrap/dist/scss/_reboot.scss @@ -305,6 +305,7 @@ pre { @include font-size($code-font-size); color: $pre-color; background-color: $pre-bg; + line-height: $pre-line-height; padding: $spacer / 2; border: $border-width solid var(--#{$prefix}border-color, $border-color); @include border-radius($border-radius); diff --git a/src/resources/formats/html/bootstrap/dist/scss/_variables.scss b/src/resources/formats/html/bootstrap/dist/scss/_variables.scss index 634526d6dc6..ffda0d61d65 100644 --- a/src/resources/formats/html/bootstrap/dist/scss/_variables.scss +++ b/src/resources/formats/html/bootstrap/dist/scss/_variables.scss @@ -1773,3 +1773,4 @@ $nested-kbd-font-weight: null !default; // Deprecated in v5.2.0, remo $pre-bg: $code-bg !default; $pre-color: $body-emphasis-color !default; +$pre-line-height: $line-height-base !default; \ No newline at end of file diff --git a/src/resources/formats/html/bootstrap/themes/cerulean.scss b/src/resources/formats/html/bootstrap/themes/cerulean.scss index 170861d3cd5..50113ef30d1 100644 --- a/src/resources/formats/html/bootstrap/themes/cerulean.scss +++ b/src/resources/formats/html/bootstrap/themes/cerulean.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "cerulean (builtin theme)" } $theme: "cerulean" !default; @@ -146,3 +147,4 @@ $text-shadow: 0 1px 0 rgba(0, 0, 0, .05) !default; } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/cosmo.scss b/src/resources/formats/html/bootstrap/themes/cosmo.scss index 7ef7b1080fc..d4dd6c9ad04 100644 --- a/src/resources/formats/html/bootstrap/themes/cosmo.scss +++ b/src/resources/formats/html/bootstrap/themes/cosmo.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "cosmo (builtin theme)" } $theme: "cosmo" !default; @@ -105,3 +106,4 @@ body { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/cyborg.scss b/src/resources/formats/html/bootstrap/themes/cyborg.scss index 6a1506c438d..4431e4e1e26 100644 --- a/src/resources/formats/html/bootstrap/themes/cyborg.scss +++ b/src/resources/formats/html/bootstrap/themes/cyborg.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "cyborg (builtin theme)" } $theme: "cyborg" !default; @@ -339,3 +340,4 @@ legend { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/darkly.scss b/src/resources/formats/html/bootstrap/themes/darkly.scss index f14d9602955..acfd9dbebec 100644 --- a/src/resources/formats/html/bootstrap/themes/darkly.scss +++ b/src/resources/formats/html/bootstrap/themes/darkly.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "darkly (builtin theme)" } $theme: "darkly" !default; @@ -272,3 +273,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0 } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/flatly.scss b/src/resources/formats/html/bootstrap/themes/flatly.scss index 13587d3b526..24a3b08e369 100644 --- a/src/resources/formats/html/bootstrap/themes/flatly.scss +++ b/src/resources/formats/html/bootstrap/themes/flatly.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "flatly (builtin theme)" } $theme: "flatly" !default; @@ -209,3 +210,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0 } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/journal.scss b/src/resources/formats/html/bootstrap/themes/journal.scss index aa5fdfd68c9..e65567ed979 100644 --- a/src/resources/formats/html/bootstrap/themes/journal.scss +++ b/src/resources/formats/html/bootstrap/themes/journal.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "journal (builtin theme)" } $theme: "journal" !default; @@ -106,3 +107,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=News+Cycle:wght@400;70 } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/litera.scss b/src/resources/formats/html/bootstrap/themes/litera.scss index 72414556cc5..0cb7977e2c9 100644 --- a/src/resources/formats/html/bootstrap/themes/litera.scss +++ b/src/resources/formats/html/bootstrap/themes/litera.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "litera (builtin theme)" } $theme: "litera" !default; @@ -195,3 +196,4 @@ table, } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/lumen.scss b/src/resources/formats/html/bootstrap/themes/lumen.scss index b8bab78a171..0a199a60a18 100644 --- a/src/resources/formats/html/bootstrap/themes/lumen.scss +++ b/src/resources/formats/html/bootstrap/themes/lumen.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "lumen (builtin theme)" } $theme: "lumen" !default; @@ -430,3 +431,4 @@ a.list-group-item { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/lux.scss b/src/resources/formats/html/bootstrap/themes/lux.scss index 00625f9cde0..63984591fda 100644 --- a/src/resources/formats/html/bootstrap/themes/lux.scss +++ b/src/resources/formats/html/bootstrap/themes/lux.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "lux (builtin theme)" } $theme: "lux" !default; @@ -277,3 +278,4 @@ th { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/materia.scss b/src/resources/formats/html/bootstrap/themes/materia.scss index 1b8a3da56d5..e06b8e22c2a 100644 --- a/src/resources/formats/html/bootstrap/themes/materia.scss +++ b/src/resources/formats/html/bootstrap/themes/materia.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "materia (builtin theme)" } $theme: "materia" !default; @@ -775,3 +776,4 @@ select.form-control { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/minty.scss b/src/resources/formats/html/bootstrap/themes/minty.scss index 84789a83501..7ef63dac2cf 100644 --- a/src/resources/formats/html/bootstrap/themes/minty.scss +++ b/src/resources/formats/html/bootstrap/themes/minty.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "minty (builtin theme)" } $theme: "minty" !default; @@ -186,3 +187,4 @@ legend { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/morph.scss b/src/resources/formats/html/bootstrap/themes/morph.scss index ed2efcdbc4e..f912cf74d20 100644 --- a/src/resources/formats/html/bootstrap/themes/morph.scss +++ b/src/resources/formats/html/bootstrap/themes/morph.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "morph (builtin theme)" } $theme: "morph" !default; @@ -717,3 +718,4 @@ $btn-box-shadow-inset: inset 2px 3px 6px rgba($black, .2), inset -3px -2px 6px r } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/pulse.scss b/src/resources/formats/html/bootstrap/themes/pulse.scss index ec435be9c2e..bcdaab5f994 100644 --- a/src/resources/formats/html/bootstrap/themes/pulse.scss +++ b/src/resources/formats/html/bootstrap/themes/pulse.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "pulse (builtin theme)" } $theme: "pulse" !default; @@ -237,3 +238,4 @@ $list-group-disabled-color: lighten($list-group-bg, 30%) !default; } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/quartz.scss b/src/resources/formats/html/bootstrap/themes/quartz.scss index 8b6190fc779..38246bb2309 100644 --- a/src/resources/formats/html/bootstrap/themes/quartz.scss +++ b/src/resources/formats/html/bootstrap/themes/quartz.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "quartz (builtin theme)" } $theme: "quartz" !default; @@ -537,3 +538,4 @@ body { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/sandstone.scss b/src/resources/formats/html/bootstrap/themes/sandstone.scss index c97694ed581..b2820c8297a 100644 --- a/src/resources/formats/html/bootstrap/themes/sandstone.scss +++ b/src/resources/formats/html/bootstrap/themes/sandstone.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "sandstone (builtin theme)" } $theme: "sandstone" !default; @@ -368,3 +369,4 @@ input, } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/simplex.scss b/src/resources/formats/html/bootstrap/themes/simplex.scss index a4bc7272fed..f5041499827 100644 --- a/src/resources/formats/html/bootstrap/themes/simplex.scss +++ b/src/resources/formats/html/bootstrap/themes/simplex.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "simplex (builtin theme)" } $theme: "simplex" !default; @@ -243,3 +244,4 @@ label { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/sketchy.scss b/src/resources/formats/html/bootstrap/themes/sketchy.scss index 0d01a32a675..c62f8be196c 100644 --- a/src/resources/formats/html/bootstrap/themes/sketchy.scss +++ b/src/resources/formats/html/bootstrap/themes/sketchy.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "sketchy (builtin theme)" } $theme: "sketchy" !default; @@ -658,3 +659,4 @@ pre { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/slate.scss b/src/resources/formats/html/bootstrap/themes/slate.scss index a9f1518ad1d..f3e29b90c5a 100644 --- a/src/resources/formats/html/bootstrap/themes/slate.scss +++ b/src/resources/formats/html/bootstrap/themes/slate.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "slate (builtin theme)" } $theme: "slate" !default; @@ -530,3 +531,4 @@ legend { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/solar.scss b/src/resources/formats/html/bootstrap/themes/solar.scss index f1ae9712703..399968f744b 100644 --- a/src/resources/formats/html/bootstrap/themes/solar.scss +++ b/src/resources/formats/html/bootstrap/themes/solar.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "solar (builtin theme)" } $theme: "solar" !default; @@ -257,3 +258,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@4 } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/spacelab.scss b/src/resources/formats/html/bootstrap/themes/spacelab.scss index eb22749cb63..1ca53390605 100644 --- a/src/resources/formats/html/bootstrap/themes/spacelab.scss +++ b/src/resources/formats/html/bootstrap/themes/spacelab.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "spacelab (builtin theme)" } $theme: "spacelab" !default; @@ -157,3 +158,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0, } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/superhero.scss b/src/resources/formats/html/bootstrap/themes/superhero.scss index 17070657623..02642a551eb 100644 --- a/src/resources/formats/html/bootstrap/themes/superhero.scss +++ b/src/resources/formats/html/bootstrap/themes/superhero.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "superhero (builtin theme)" } $theme: "superhero" !default; @@ -350,3 +351,4 @@ label, } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/united.scss b/src/resources/formats/html/bootstrap/themes/united.scss index 8de77534eda..aa3a21212cf 100644 --- a/src/resources/formats/html/bootstrap/themes/united.scss +++ b/src/resources/formats/html/bootstrap/themes/united.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "united (builtin theme)" } $theme: "united" !default; @@ -75,3 +76,4 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&di } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/vapor.scss b/src/resources/formats/html/bootstrap/themes/vapor.scss index 8f98e4944b0..02611773b25 100644 --- a/src/resources/formats/html/bootstrap/themes/vapor.scss +++ b/src/resources/formats/html/bootstrap/themes/vapor.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "vapor (builtin theme)" } $theme: "vapor" !default; @@ -502,3 +503,4 @@ legend { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/yeti.scss b/src/resources/formats/html/bootstrap/themes/yeti.scss index 672927852bb..11f8947ea1d 100644 --- a/src/resources/formats/html/bootstrap/themes/yeti.scss +++ b/src/resources/formats/html/bootstrap/themes/yeti.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "yeti (builtin theme)" } $theme: "yeti" !default; @@ -450,3 +451,4 @@ label, } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bootstrap/themes/zephyr.scss b/src/resources/formats/html/bootstrap/themes/zephyr.scss index 5b4644332db..39e3905b046 100644 --- a/src/resources/formats/html/bootstrap/themes/zephyr.scss +++ b/src/resources/formats/html/bootstrap/themes/zephyr.scss @@ -1,4 +1,5 @@ /*-- scss:defaults --*/ +// quarto-scss-analysis-annotation { "origin": "zephyr (builtin theme)" } $theme: "zephyr" !default; @@ -367,3 +368,4 @@ thead th { } +// quarto-scss-analysis-annotation { "origin": null } diff --git a/src/resources/formats/html/bslib/components/scss/sidebar.scss b/src/resources/formats/html/bslib/components/scss/sidebar.scss index 001d04647f4..69ef62789e7 100644 --- a/src/resources/formats/html/bslib/components/scss/sidebar.scss +++ b/src/resources/formats/html/bslib/components/scss/sidebar.scss @@ -279,7 +279,7 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--bslib-sidebar-icon-size)), &, &.sidebar-right { // Remove sidebar borders in mobile view (except always-open, added below) - > .sidebar { border: none } + > .sidebar { border: none; } // Main area takes up entire layout area to avoid layout shift when // sidebar is expanded as an overlay. @@ -332,7 +332,7 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--bslib-sidebar-icon-size)), // Make main contents transparent while sidebar is expanded > .main { opacity: 0; - transition: opacity var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration) + transition: opacity var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration); } &.sidebar-collapsed > .main { opacity: 1; diff --git a/src/resources/formats/html/bslib/components/scss/value_box.scss b/src/resources/formats/html/bslib/components/scss/value_box.scss index 787fd7bdccc..05e580f1a15 100644 --- a/src/resources/formats/html/bslib/components/scss/value_box.scss +++ b/src/resources/formats/html/bslib/components/scss/value_box.scss @@ -109,7 +109,7 @@ $bslib-value-box-horizontal-break-point: 300px; @include bootstrap-heading-font-and-spacing($h6-font-size); // add a non-breaking space to ensure it's not 0 height &:empty::after { - content: '\00a0 ' + content: '\00a0 '; } } @@ -117,7 +117,7 @@ $bslib-value-box-horizontal-break-point: 300px; @include bootstrap-heading-font-and-spacing($h2-font-size); // add a non-breaking space to ensure it's not 0 height &:empty::after { - content: '\00a0 ' + content: '\00a0 '; } } diff --git a/src/resources/formats/revealjs/quarto.scss b/src/resources/formats/revealjs/quarto.scss index b5ea1419cc9..fc26aba3c87 100644 --- a/src/resources/formats/revealjs/quarto.scss +++ b/src/resources/formats/revealjs/quarto.scss @@ -291,6 +291,7 @@ div.reveal div.slides section.quarto-title-block { border: none; margin: 0; font-size: $code-block-font-size; + line-height: $code-block-line-height; } // Inside code-file-name div, we want to use the same background color as decorated codeblock header diff --git a/src/resources/schema/definitions.yml b/src/resources/schema/definitions.yml index 83badc74640..8c87accb48a 100644 --- a/src/resources/schema/definitions.yml +++ b/src/resources/schema/definitions.yml @@ -2781,18 +2781,44 @@ - id: brand-font-with description: Font files and definitions for the brand. object: - closed: false + additionalProperties: + ref: brand-font - id: brand-font description: Font files and definitions for the brand. anyOf: - ref: brand-font-google + - ref: brand-font-bunny - ref: brand-font-file - ref: brand-font-family - id: brand-font-weight description: A font weight. - enum: [100, 200, 300, 400, 500, 600, 700, 800, 900] + enum: + [ + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + thin, + extra-light, + ultra-light, + light, + normal, + regular, + medium, + semi-bold, + demi-bold, + bold, + extra-bold, + ultra-bold, + black, + ] default: 400 - id: brand-font-style @@ -2800,38 +2826,51 @@ enum: [normal, italic] default: normal +- id: brand-font-common + schema: + anyOf: + - string + - object: + closed: true + properties: + family: + description: The font family name, which must match the name of the font on the foundry website. + schema: string + weight: + description: The font weights to include. + maybeArrayOf: + ref: brand-font-weight + default: [400, 700] + style: + description: The font styles to include. + maybeArrayOf: + ref: brand-font-style + default: [normal, italic] + display: + description: > + The font display method, determines how a font face is font face is shown + depending on its download status and readiness for use. + enum: [auto, block, swap, fallback, optional] + default: swap + - id: brand-font-google - description: A Google Font definition. + description: A font definition from Google Fonts. object: closed: true properties: google: - anyOf: - - string - - object: - closed: true - properties: - family: - description: The font family name, which must match the name of the font on Google Fonts. - schema: string - weight: - description: The font weights to include. - maybeArrayOf: - ref: brand-font-weight - default: [400, 700] - style: - description: The font styles to include. - maybeArrayOf: - ref: brand-font-style - default: [normal, italic] - display: - description: > - The font display method, determines how a font face is font face is shown - depending on its download status and readiness for use. - enum: [auto, block, swap, fallback, optional] - default: swap + ref: brand-font-common required: [google] +- id: brand-font-bunny + description: A font definition from fonts.bunny.net. + object: + closed: true + properties: + bunny: + ref: brand-font-common + required: [bunny] + - id: brand-font-file description: A method for providing font files directly, either locally or from an online location. object: diff --git a/src/resources/schema/json-schemas.json b/src/resources/schema/json-schemas.json new file mode 100644 index 00000000000..47364a5732d --- /dev/null +++ b/src/resources/schema/json-schemas.json @@ -0,0 +1,3818 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$defs": { + "Date": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "value": { + "type": "string" + }, + "format": { + "type": "string" + } + } + } + } + ] + }, + "MathMethods": { + "enum": { + "values": [ + "plain", + "webtex", + "gladtex", + "mathml", + "mathjax", + "katex" + ] + } + }, + "PandocFormatRequestHeaders": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "PandocFormatOutputFile": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": { + "values": [ + null + ], + "hidden": true + } + } + ] + }, + "PandocFormatFilters": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "path": { + "type": "string" + } + } + } + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "path": { + "type": "string" + }, + "at": { + "enum": [ + "pre-ast", + "post-ast", + "pre-quarto", + "post-quarto", + "pre-render", + "post-render" + ] + } + } + } + }, + { + "object": { + "properties": { + "type": { + "enum": [ + "citeproc" + ] + } + }, + "required": [ + "type" + ], + "additionalProperties": false + } + } + ] + } + }, + "PandocShortcodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "PageColumn": { + "enum": [ + "body", + "body-outset", + "body-outset-left", + "body-outset-right", + "page", + "page-left", + "page-right", + "page-inset-left", + "page-inset-right", + "screen", + "screen-left", + "screen-right", + "screen-inset", + "screen-inset-shaded", + "screen-inset-left", + "screen-inset-right", + "margin" + ] + }, + "ContentsAuto": { + "object": { + "properties": { + "auto": { + "anyOf": [ + { + "type": "boolean" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + ] + } + } + } + }, + "NavigationItem": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/NavigationItemObject" + } + ] + }, + "NavigationItemObject": { + "object": { + "properties": { + "aria-label": { + "type": "string" + }, + "file": { + "type": "string" + }, + "href": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "id": { + "type": "string" + }, + "menu": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + }, + "text": { + "type": "string" + }, + "url": { + "type": "string" + }, + "rel": { + "type": "string" + }, + "target": { + "type": "string" + } + } + } + }, + "GiscusThemes": { + "enum": { + "values": [ + "light", + "light_high_contrast", + "light_protanopia", + "light_tritanopia", + "dark", + "dark_high_contrast", + "dark_protanopia", + "dark_tritanopia", + "dark_dimmed", + "transparent_dark", + "cobalt", + "purple_dark", + "noborder_light", + "noborder_dark", + "noborder_gray", + "preferred_color_scheme" + ] + } + }, + "Comments": { + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "object": { + "properties": { + "utterances": { + "object": { + "properties": { + "repo": { + "type": "string" + }, + "label": { + "type": "string" + }, + "theme": { + "type": "string" + }, + "issue-term": { + "type": "string" + } + } + } + }, + "giscus": { + "object": { + "properties": { + "repo": { + "type": "string" + }, + "repo-id": { + "type": "string" + }, + "category": { + "type": "string" + }, + "category-id": { + "type": "string" + }, + "mapping": { + "anyOf": [ + { + "enum": [ + "pathname", + "url", + "title", + "og:title" + ] + }, + { + "type": "string" + } + ] + }, + "reactions-enabled": { + "type": "boolean" + }, + "loading": { + "enum": [ + "lazy" + ] + }, + "input-position": { + "enum": [ + "top", + "bottom" + ] + }, + "theme": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GiscusThemes" + }, + { + "object": { + "properties": { + "light": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GiscusThemes" + } + ] + }, + "dark": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/GiscusThemes" + } + ] + } + } + } + } + ] + }, + "language": { + "type": "string" + } + } + } + }, + "hypothesis": { + "anyOf": [ + { + "type": "boolean" + }, + { + "object": { + "properties": { + "client-url": { + "type": "string" + }, + "openSidebar": { + "type": "boolean" + }, + "showHighlights": { + "anyOf": [ + { + "type": "boolean" + }, + { + "enum": [ + "always", + "whenSidebarOpen", + "never" + ] + } + ] + }, + "theme": { + "enum": [ + "classic", + "clean" + ] + }, + "enableExperimentalNewNoteButton": { + "type": "boolean" + }, + "usernameUrl": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "object": { + "properties": { + "apiUrl": { + "type": "string" + }, + "authority": { + "type": "string" + }, + "grantToken": { + "type": "string" + }, + "allowLeavingGroups": { + "type": "boolean" + }, + "enableShareLinks": { + "type": "boolean" + }, + "groups": { + "anyOf": [ + { + "enum": [ + "$rpc:requestGroups" + ] + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "icon": { + "type": "string" + } + } + } + } + }, + "branding": { + "object": { + "properties": { + "accentColor": { + "type": "string" + }, + "appBackgroundColor": { + "type": "string" + }, + "ctaBackgroundColor": { + "type": "string" + }, + "selectionFontFamily": { + "type": "string" + }, + "annotationFontFamily": { + "type": "string" + } + } + } + }, + "externalContainerSelector": { + "type": "string" + }, + "focus": { + "object": { + "properties": { + "user": { + "object": { + "properties": { + "username": { + "type": "string" + }, + "userid": { + "type": "string" + }, + "displayName": { + "type": "string" + } + } + } + } + } + } + }, + "requestConfigFromFrame": { + "object": { + "properties": { + "origin": { + "type": "string" + }, + "ancestorLevel": { + "type": "number" + } + } + } + }, + "assetRoot": { + "type": "string" + }, + "sidebarAppUrl": { + "type": "string" + } + } + } + } + ] + } + } + } + } + ] + }, + "SocialMetadata": { + "object": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "image": { + "type": "string" + }, + "image-alt": { + "type": "string" + }, + "image-width": { + "type": "number" + }, + "image-height": { + "type": "number" + } + } + } + }, + "PageFooterRegion": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + } + ] + }, + "SidebarContents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/ContentsAuto" + }, + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/NavigationItem" + }, + { + "type": "string" + }, + { + "object": { + "properties": { + "section": { + "anyOf": [ + { + "type": "string" + }, + { + "enum": [ + null + ] + } + ] + }, + "contents": { + "$ref": "#/$defs/SidebarContents" + } + } + } + }, + { + "$ref": "#/$defs/ContentsAuto" + } + ] + } + } + ] + }, + "ProjectPreview": { + "object": { + "properties": { + "port": { + "type": "number" + }, + "host": { + "type": "string" + }, + "serve": { + "$ref": "#/$defs/ProjectServe" + }, + "browser": { + "type": "boolean" + }, + "watch-inputs": { + "type": "boolean" + }, + "navigate": { + "type": "boolean" + }, + "timeout": { + "type": "number" + } + } + } + }, + "ProjectServe": { + "object": { + "properties": { + "cmd": { + "type": "string" + }, + "args": { + "type": "string" + }, + "env": { + "object": { + "properties": {} + } + }, + "ready": { + "type": "string" + } + } + } + }, + "Publish": { + "object": { + "properties": { + "netlify": { + "type": "array", + "items": { + "$ref": "#/$defs/PublishRecord" + } + } + } + } + }, + "PublishRecord": { + "object": { + "properties": { + "id": { + "type": "string" + }, + "url": { + "type": "string" + } + } + } + }, + "TwitterCardConfig": { + "object": { + "properties": { + "card-style": { + "enum": [ + "summary", + "summary_large_image" + ] + }, + "creator": { + "type": "string" + }, + "site": { + "type": "string" + } + } + } + }, + "OpenGraphConfig": { + "object": { + "properties": { + "locale": { + "type": "string" + }, + "site-name": { + "type": "string" + } + } + } + }, + "PageFooter": { + "object": { + "properties": { + "left": { + "$ref": "#/$defs/PageFooterRegion" + }, + "right": { + "$ref": "#/$defs/PageFooterRegion" + }, + "center": { + "$ref": "#/$defs/PageFooterRegion" + }, + "border": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "background": { + "type": "string" + }, + "foreground": { + "type": "string" + } + } + } + }, + "BaseWebsite": { + "object": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "favicon": { + "type": "string" + }, + "site-url": { + "type": "string" + }, + "site-path": { + "type": "string" + }, + "repo-url": { + "type": "string" + }, + "repo-link-target": { + "type": "string" + }, + "repo-link-rel": { + "type": "string" + }, + "repo-subdir": { + "type": "string" + }, + "repo-branch": { + "type": "string" + }, + "issue-url": { + "type": "string" + }, + "repo-actions": { + "anyOf": [ + { + "type": "array", + "items": { + "enum": [ + "none", + "edit", + "source", + "issue" + ] + } + }, + { + "enum": [ + "none", + "edit", + "source", + "issue" + ] + } + ] + }, + "reader-mode": { + "type": "boolean" + }, + "google-analytics": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "tracking-id": { + "type": "string" + }, + "storage": { + "enum": [ + "cookies", + "none" + ] + }, + "anonymize-ip": { + "type": "boolean" + }, + "version": { + "enum": [ + 3, + 4 + ] + } + } + } + } + ] + }, + "announcement": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "content": { + "type": "string" + }, + "dismissable": { + "type": "boolean" + }, + "icon": { + "type": "string" + }, + "position": { + "enum": [ + "above-navbar", + "below-navbar" + ] + }, + "type": { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + } + } + } + } + ] + }, + "cookie-consent": { + "anyOf": [ + { + "enum": [ + "express", + "implied" + ] + }, + { + "type": "boolean" + }, + { + "object": { + "properties": { + "type": { + "enum": [ + "implied", + "express" + ] + }, + "style": { + "enum": [ + "simple", + "headline", + "interstitial", + "standalone" + ] + }, + "palette": { + "enum": [ + "light", + "dark" + ] + }, + "policy-url": { + "type": "string" + }, + "language": { + "type": "string" + }, + "prefs-text": { + "type": "string" + } + } + } + } + ] + }, + "search": { + "anyOf": [ + { + "type": "boolean" + }, + { + "object": { + "properties": { + "location": { + "enum": [ + "navbar", + "sidebar" + ] + }, + "type": { + "enum": [ + "overlay", + "textbox" + ] + }, + "limit": { + "type": "number" + }, + "collapse-after": { + "type": "number" + }, + "copy-button": { + "type": "boolean" + }, + "keyboard-shortcut": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "show-item-context": { + "anyOf": [ + { + "enum": [ + "tree", + "parent", + "root" + ] + }, + { + "type": "boolean" + } + ] + }, + "algolia": { + "object": { + "properties": { + "index-name": { + "type": "string" + }, + "application-id": { + "type": "string" + }, + "search-only-api-key": { + "type": "string" + }, + "analytics-events": { + "type": "boolean" + }, + "show-logo": { + "type": "boolean" + }, + "index-fields": { + "object": { + "properties": { + "href": { + "type": "string" + }, + "title": { + "type": "string" + }, + "text": { + "type": "string" + }, + "section": { + "type": "string" + } + } + } + }, + "params": { + "object": { + "properties": {} + } + } + } + } + } + } + } + } + ] + }, + "navbar": { + "anyOf": [ + { + "type": "boolean" + }, + { + "object": { + "properties": { + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "logo": { + "type": "string" + }, + "logo-alt": { + "type": "string" + }, + "logo-href": { + "type": "string" + }, + "background": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "foreground": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "search": { + "type": "boolean" + }, + "pinned": { + "type": "boolean" + }, + "collapse": { + "type": "boolean" + }, + "collapse-below": { + "enum": [ + "sm", + "md", + "lg", + "xl", + "xxl" + ] + }, + "left": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + }, + "right": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + }, + "toggle-position": { + "enum": [ + "left", + "right" + ] + }, + "tools-collapse": { + "type": "boolean" + } + } + } + } + ] + }, + "sidebar": { + "anyOf": [ + { + "type": "boolean" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "object": { + "properties": { + "id": { + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "logo": { + "type": "string" + }, + "logo-alt": { + "type": "string" + }, + "logo-href": { + "type": "string" + }, + "search": { + "type": "boolean" + }, + "tools": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItemObject" + } + }, + "contents": { + "$ref": "#/$defs/SidebarContents" + }, + "style": { + "enum": [ + "docked", + "floating" + ] + }, + "background": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "foreground": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "border": { + "type": "boolean" + }, + "alignment": { + "enum": [ + "left", + "right", + "center" + ] + }, + "collapse-level": { + "type": "number" + }, + "pinned": { + "type": "boolean" + }, + "header": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "footer": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + } + } + } + }, + { + "object": { + "properties": { + "id": { + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "logo": { + "type": "string" + }, + "logo-alt": { + "type": "string" + }, + "logo-href": { + "type": "string" + }, + "search": { + "type": "boolean" + }, + "tools": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItemObject" + } + }, + "contents": { + "$ref": "#/$defs/SidebarContents" + }, + "style": { + "enum": [ + "docked", + "floating" + ] + }, + "background": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "foreground": { + "anyOf": [ + { + "enum": [ + "primary", + "secondary", + "success", + "danger", + "warning", + "info", + "light", + "dark" + ] + }, + { + "type": "string" + } + ] + }, + "border": { + "type": "boolean" + }, + "alignment": { + "enum": [ + "left", + "right", + "center" + ] + }, + "collapse-level": { + "type": "number" + }, + "pinned": { + "type": "boolean" + }, + "header": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "footer": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + } + } + } + ] + } + ] + }, + "body-header": { + "type": "string" + }, + "body-footer": { + "type": "string" + }, + "margin-header": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "margin-footer": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "page-navigation": { + "type": "boolean" + }, + "back-to-top-navigation": { + "type": "boolean" + }, + "bread-crumbs": { + "type": "boolean" + }, + "page-footer": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/PageFooter" + } + ] + }, + "image": { + "type": "string" + }, + "image-alt": { + "type": "string" + }, + "comments": { + "$ref": "#/$defs/Comments" + }, + "open-graph": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/OpenGraphConfig" + } + ] + }, + "twitter-card": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/TwitterCardConfig" + } + ] + }, + "other-links": { + "$ref": "#/$defs/OtherLinks" + }, + "code-links": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/$defs/CodeLinksSchema" + } + ] + }, + "drafts": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "draft-mode": { + "enum": [ + "visible", + "unlinked", + "gone" + ] + } + } + } + }, + "BookSchema": { + "object": { + "properties": { + "title": { + "type": "string" + }, + "subtitle": { + "type": "string" + }, + "author": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + ] + }, + "date": { + "type": "string" + }, + "date-format": { + "type": "string" + }, + "abstract": { + "type": "string" + }, + "description": { + "type": "string" + }, + "chapters": { + "$ref": "#/$defs/ChapterList" + }, + "appendices": { + "$ref": "#/$defs/ChapterList" + }, + "references": { + "type": "string" + }, + "output-file": { + "type": "string" + }, + "cover-image": { + "type": "string" + }, + "cover-image-alt": { + "type": "string" + }, + "sharing": { + "anyOf": [ + { + "type": "array", + "items": { + "enum": [ + "twitter", + "facebook", + "linkedin" + ] + } + }, + { + "enum": [ + "twitter", + "facebook", + "linkedin" + ] + } + ] + }, + "downloads": { + "anyOf": [ + { + "type": "array", + "items": { + "enum": [ + "pdf", + "epub", + "docx" + ] + } + }, + { + "enum": [ + "pdf", + "epub", + "docx" + ] + } + ] + }, + "tools": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + }, + "doi": { + "type": "string" + } + } + } + }, + "ChapterItem": { + "anyOf": [ + { + "$ref": "#/$defs/NavigationItem" + }, + { + "object": { + "properties": { + "part": { + "type": "string" + }, + "chapters": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + } + } + } + } + ] + }, + "ChapterList": { + "type": "array", + "items": { + "$ref": "#/$defs/ChapterItem" + } + }, + "OtherLinks": { + "type": "array", + "items": { + "object": { + "properties": { + "text": { + "type": "string" + }, + "href": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "rel": { + "type": "string" + }, + "target": { + "type": "string" + } + } + } + } + }, + "CrossrefLabelsSchema": { + "type": "string" + }, + "EpubContributor": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "object": { + "properties": { + "role": { + "type": "string" + }, + "file-as": { + "type": "string" + }, + "text": { + "type": "string" + } + } + } + } + }, + { + "object": { + "properties": { + "role": { + "type": "string" + }, + "file-as": { + "type": "string" + }, + "text": { + "type": "string" + } + } + } + } + ] + } + ] + }, + "FormatLanguage": { + "object": { + "properties": { + "toc-title-document": { + "type": "string" + }, + "toc-title-website": { + "type": "string" + }, + "related-formats-title": { + "type": "string" + }, + "related-notebooks-title": { + "type": "string" + }, + "callout-tip-title": { + "type": "string" + }, + "callout-note-title": { + "type": "string" + }, + "callout-warning-title": { + "type": "string" + }, + "callout-important-title": { + "type": "string" + }, + "callout-caution-title": { + "type": "string" + }, + "section-title-abstract": { + "type": "string" + }, + "section-title-footnotes": { + "type": "string" + }, + "section-title-appendices": { + "type": "string" + }, + "code-summary": { + "type": "string" + }, + "code-tools-menu-caption": { + "type": "string" + }, + "code-tools-show-all-code": { + "type": "string" + }, + "code-tools-hide-all-code": { + "type": "string" + }, + "code-tools-view-source": { + "type": "string" + }, + "code-tools-source-code": { + "type": "string" + }, + "search-no-results-text": { + "type": "string" + }, + "copy-button-tooltip": { + "type": "string" + }, + "copy-button-tooltip-success": { + "type": "string" + }, + "repo-action-links-edit": { + "type": "string" + }, + "repo-action-links-source": { + "type": "string" + }, + "repo-action-links-issue": { + "type": "string" + }, + "search-matching-documents-text": { + "type": "string" + }, + "search-copy-link-title": { + "type": "string" + }, + "search-hide-matches-text": { + "type": "string" + }, + "search-more-match-text": { + "type": "string" + }, + "search-more-matches-text": { + "type": "string" + }, + "search-clear-button-title": { + "type": "string" + }, + "search-text-placeholder": { + "type": "string" + }, + "search-detached-cancel-button-title": { + "type": "string" + }, + "search-submit-button-title": { + "type": "string" + }, + "crossref-fig-title": { + "type": "string" + }, + "crossref-tbl-title": { + "type": "string" + }, + "crossref-lst-title": { + "type": "string" + }, + "crossref-thm-title": { + "type": "string" + }, + "crossref-lem-title": { + "type": "string" + }, + "crossref-cor-title": { + "type": "string" + }, + "crossref-prp-title": { + "type": "string" + }, + "crossref-cnj-title": { + "type": "string" + }, + "crossref-def-title": { + "type": "string" + }, + "crossref-exm-title": { + "type": "string" + }, + "crossref-exr-title": { + "type": "string" + }, + "crossref-fig-prefix": { + "type": "string" + }, + "crossref-tbl-prefix": { + "type": "string" + }, + "crossref-lst-prefix": { + "type": "string" + }, + "crossref-ch-prefix": { + "type": "string" + }, + "crossref-apx-prefix": { + "type": "string" + }, + "crossref-sec-prefix": { + "type": "string" + }, + "crossref-eq-prefix": { + "type": "string" + }, + "crossref-thm-prefix": { + "type": "string" + }, + "crossref-lem-prefix": { + "type": "string" + }, + "crossref-cor-prefix": { + "type": "string" + }, + "crossref-prp-prefix": { + "type": "string" + }, + "crossref-cnj-prefix": { + "type": "string" + }, + "crossref-def-prefix": { + "type": "string" + }, + "crossref-exm-prefix": { + "type": "string" + }, + "crossref-exr-prefix": { + "type": "string" + }, + "crossref-lof-title": { + "type": "string" + }, + "crossref-lot-title": { + "type": "string" + }, + "crossref-lol-title": { + "type": "string" + } + } + } + }, + "WebsiteAbout": { + "object": { + "properties": { + "id": { + "type": "string" + }, + "template": { + "anyOf": [ + { + "enum": [ + "jolla", + "trestles", + "solana", + "marquee", + "broadside" + ] + }, + { + "type": "string" + } + ] + }, + "image": { + "type": "string" + }, + "image-alt": { + "type": "string" + }, + "image-title": { + "type": "string" + }, + "image-width": { + "type": "string" + }, + "image-shape": { + "enum": [ + "rectangle", + "round", + "rounded" + ] + }, + "links": { + "type": "array", + "items": { + "$ref": "#/$defs/NavigationItem" + } + } + } + } + }, + "WebsiteListing": { + "object": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "enum": [ + "default", + "table", + "grid", + "custom" + ] + }, + "contents": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/WebsiteListingContentsObject" + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/WebsiteListingContentsObject" + } + ] + } + ] + }, + "sort": { + "anyOf": [ + { + "type": "boolean" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + ] + }, + "max-items": { + "type": "number" + }, + "page-size": { + "type": "number" + }, + "sort-ui": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "filter-ui": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "categories": { + "anyOf": [ + { + "type": "boolean" + }, + { + "enum": [ + "numbered", + "unnumbered", + "cloud" + ] + } + ] + }, + "feed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "object": { + "properties": { + "items": { + "type": "number" + }, + "type": { + "enum": [ + "full", + "partial", + "metadata" + ] + }, + "title": { + "type": "string" + }, + "image": { + "type": "string" + }, + "description": { + "type": "string" + }, + "language": { + "type": "string" + }, + "categories": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "xml-stylesheet": { + "type": "string" + } + } + } + } + ] + }, + "date-format": { + "type": "string" + }, + "max-description-length": { + "type": "number" + }, + "image-placeholder": { + "type": "string" + }, + "image-lazy-loading": { + "type": "boolean" + }, + "image-align": { + "enum": [ + "left", + "right" + ] + }, + "image-height": { + "type": "string" + }, + "grid-columns": { + "type": "number" + }, + "grid-item-border": { + "type": "boolean" + }, + "grid-item-align": { + "enum": [ + "left", + "right", + "center" + ] + }, + "table-striped": { + "type": "boolean" + }, + "table-hover": { + "type": "boolean" + }, + "template": { + "type": "string" + }, + "template-params": { + "type": "object" + }, + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "field-display-names": { + "object": { + "properties": {} + } + }, + "field-types": { + "object": { + "properties": {} + } + }, + "field-links": { + "type": "array", + "items": { + "type": "string" + } + }, + "field-required": { + "type": "array", + "items": { + "type": "string" + } + }, + "include": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "object" + } + ] + }, + "exclude": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "object" + } + ] + } + } + } + }, + "WebsiteListingContentsObject": { + "object": { + "properties": { + "author": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "date": { + "type": "string" + }, + "title": { + "type": "string" + }, + "subtitle": { + "type": "string" + } + } + } + }, + "CslDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "number" + } + }, + { + "type": "number" + } + ] + }, + { + "object": { + "properties": { + "year": { + "type": "number" + }, + "month": { + "type": "number" + }, + "day": { + "type": "number" + } + } + } + } + ] + }, + "CslPerson": { + "anyOf": [ + { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "object": { + "properties": { + "family-name": { + "type": "string" + }, + "given-name": { + "type": "string" + } + } + } + } + }, + { + "object": { + "properties": { + "family-name": { + "type": "string" + }, + "given-name": { + "type": "string" + } + } + } + } + ] + } + ] + }, + "CslNumber": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "CslItemShared": { + "object": { + "properties": { + "abstract-url": { + "type": "string" + }, + "accessed": { + "$ref": "#/$defs/CslDate" + }, + "annote": { + "type": "string" + }, + "archive": { + "type": "string" + }, + "archive-collection": { + "type": "string" + }, + "archive_collection": { + "type": "string" + }, + "archive-location": { + "type": "string" + }, + "archive_location": { + "type": "string" + }, + "archive-place": { + "type": "string" + }, + "authority": { + "type": "string" + }, + "available-date": { + "$ref": "#/$defs/CslDate" + }, + "call-number": { + "type": "string" + }, + "chair": { + "$ref": "#/$defs/CslPerson" + }, + "chapter-number": { + "$ref": "#/$defs/CslNumber" + }, + "citation-key": { + "type": "string" + }, + "citation-label": { + "type": "string" + }, + "citation-number": { + "$ref": "#/$defs/CslNumber" + }, + "collection-editor": { + "$ref": "#/$defs/CslPerson" + }, + "collection-number": { + "$ref": "#/$defs/CslNumber" + }, + "collection-title": { + "type": "string" + }, + "compiler": { + "$ref": "#/$defs/CslPerson" + }, + "composer": { + "$ref": "#/$defs/CslPerson" + }, + "container-author": { + "$ref": "#/$defs/CslPerson" + }, + "container-title": { + "type": "string" + }, + "container-title-short": { + "type": "string" + }, + "contributor": { + "$ref": "#/$defs/CslPerson" + }, + "curator": { + "$ref": "#/$defs/CslPerson" + }, + "dimensions": { + "type": "string" + }, + "director": { + "$ref": "#/$defs/CslPerson" + }, + "division": { + "type": "string" + }, + "DOI": { + "type": "string" + }, + "edition": { + "$ref": "#/$defs/CslNumber" + }, + "editor": { + "$ref": "#/$defs/CslPerson" + }, + "editorial-director": { + "$ref": "#/$defs/CslPerson" + }, + "editor-translator": { + "$ref": "#/$defs/CslPerson" + }, + "event": { + "type": "string" + }, + "event-date": { + "$ref": "#/$defs/CslDate" + }, + "event-title": { + "type": "string" + }, + "event-place": { + "type": "string" + }, + "executive-producer": { + "$ref": "#/$defs/CslPerson" + }, + "first-reference-note-number": { + "$ref": "#/$defs/CslNumber" + }, + "fulltext-url": { + "type": "string" + }, + "genre": { + "type": "string" + }, + "guest": { + "$ref": "#/$defs/CslPerson" + }, + "host": { + "$ref": "#/$defs/CslPerson" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, + "illustrator": { + "$ref": "#/$defs/CslPerson" + }, + "interviewer": { + "$ref": "#/$defs/CslPerson" + }, + "isbn": { + "type": "string" + }, + "ISBN": { + "type": "string" + }, + "issn": { + "type": "string" + }, + "ISSN": { + "type": "string" + }, + "issue": { + "$ref": "#/$defs/CslNumber" + }, + "issued": { + "$ref": "#/$defs/CslDate" + }, + "jurisdiction": { + "type": "string" + }, + "keyword": { + "type": "string" + }, + "language": { + "type": "string" + }, + "license": { + "type": "string" + }, + "locator": { + "$ref": "#/$defs/CslNumber" + }, + "medium": { + "type": "string" + }, + "narrator": { + "$ref": "#/$defs/CslPerson" + }, + "note": { + "type": "string" + }, + "number": { + "$ref": "#/$defs/CslNumber" + }, + "number-of-pages": { + "$ref": "#/$defs/CslNumber" + }, + "number-of-volumes": { + "$ref": "#/$defs/CslNumber" + }, + "organizer": { + "$ref": "#/$defs/CslPerson" + }, + "original-author": { + "$ref": "#/$defs/CslPerson" + }, + "original-date": { + "$ref": "#/$defs/CslDate" + }, + "original-publisher": { + "type": "string" + }, + "original-publisher-place": { + "type": "string" + }, + "original-title": { + "type": "string" + }, + "page": { + "$ref": "#/$defs/CslNumber" + }, + "page-first": { + "$ref": "#/$defs/CslNumber" + }, + "page-last": { + "$ref": "#/$defs/CslNumber" + }, + "part-number": { + "$ref": "#/$defs/CslNumber" + }, + "part-title": { + "type": "string" + }, + "pdf-url": { + "type": "string" + }, + "performer": { + "$ref": "#/$defs/CslPerson" + }, + "pmcid": { + "type": "string" + }, + "PMCID": { + "type": "string" + }, + "pmid": { + "type": "string" + }, + "PMID": { + "type": "string" + }, + "printing-number": { + "$ref": "#/$defs/CslNumber" + }, + "producer": { + "$ref": "#/$defs/CslPerson" + }, + "public-url": { + "type": "string" + }, + "publisher": { + "type": "string" + }, + "publisher-place": { + "type": "string" + }, + "recipient": { + "$ref": "#/$defs/CslPerson" + }, + "reviewed-author": { + "$ref": "#/$defs/CslPerson" + }, + "reviewed-genre": { + "type": "string" + }, + "reviewed-title": { + "type": "string" + }, + "scale": { + "type": "string" + }, + "script-writer": { + "$ref": "#/$defs/CslPerson" + }, + "section": { + "$ref": "#/$defs/CslNumber" + }, + "series-creator": { + "$ref": "#/$defs/CslPerson" + }, + "source": { + "type": "string" + }, + "status": { + "type": "string" + }, + "submitted": { + "$ref": "#/$defs/CslDate" + }, + "supplement-number": { + "$ref": "#/$defs/CslNumber" + }, + "title-short": { + "type": "string" + }, + "translator": { + "$ref": "#/$defs/CslPerson" + }, + "type": { + "enum": [ + "article", + "article-journal", + "article-magazine", + "article-newspaper", + "bill", + "book", + "broadcast", + "chapter", + "classic", + "collection", + "dataset", + "document", + "entry", + "entry-dictionary", + "entry-encyclopedia", + "event", + "figure", + "graphic", + "hearing", + "interview", + "legal_case", + "legislation", + "manuscript", + "map", + "motion_picture", + "musical_score", + "pamphlet", + "paper-conference", + "patent", + "performance", + "periodical", + "personal_communication", + "post", + "post-weblog", + "regulation", + "report", + "review", + "review-book", + "software", + "song", + "speech", + "standard", + "thesis", + "treaty", + "webpage" + ] + }, + "url": { + "type": "string" + }, + "URL": { + "type": "string" + }, + "version": { + "$ref": "#/$defs/CslNumber" + }, + "volume": { + "$ref": "#/$defs/CslNumber" + }, + "volume-title": { + "type": "string" + }, + "year-suffix": { + "type": "string" + } + } + } + }, + "CslItem": { + "object": { + "properties": { + "abstract": { + "type": "string" + }, + "author": { + "$ref": "#/$defs/CslPerson" + }, + "doi": { + "type": "string" + }, + "references": { + "type": "string" + }, + "title": { + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + } + } + }, + "CitationItem": { + "object": { + "properties": { + "article-id": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + ] + } + ] + }, + "elocation-id": { + "type": "string" + }, + "eissn": { + "type": "string" + }, + "pissn": { + "type": "string" + }, + "art-access-id": { + "type": "string" + }, + "publisher-location": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "categories": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "container-id": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + ] + } + ] + }, + "jats-type": { + "type": "string" + } + } + } + }, + "SmartInclude": { + "anyOf": [ + { + "object": { + "properties": { + "text": { + "type": "string" + } + }, + "required": [ + "text" + ], + "additionalProperties": false + } + }, + { + "object": { + "properties": { + "file": { + "type": "string" + } + }, + "required": [ + "file" + ], + "additionalProperties": false + } + } + ] + }, + "Semver": { + "type": "string" + }, + "QuartoDate": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "format": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + ] + }, + "ProjectProfile": { + "object": { + "properties": { + "default": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "group": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + } + } + }, + "BadParseSchema": { + "object": { + "properties": {} + } + }, + "QuartoDevSchema": { + "object": { + "properties": { + "_quarto": { + "object": { + "properties": { + "trace-filters": { + "type": "string" + }, + "tests": { + "type": "object" + } + } + } + } + } + } + }, + "NotebookViewSchema": { + "object": { + "properties": { + "notebook": { + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "url": { + "type": "string" + }, + "download-url": { + "type": "string" + } + } + } + }, + "CodeLinksSchema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "object": { + "properties": { + "icon": { + "type": "string" + }, + "text": { + "type": "string" + }, + "href": { + "type": "string" + }, + "rel": { + "type": "string" + }, + "target": { + "type": "string" + } + } + } + }, + { + "enum": [ + "repo", + "binder", + "devcontainer" + ] + } + ] + } + }, + { + "anyOf": [ + { + "object": { + "properties": { + "icon": { + "type": "string" + }, + "text": { + "type": "string" + }, + "href": { + "type": "string" + }, + "rel": { + "type": "string" + }, + "target": { + "type": "string" + } + } + } + }, + { + "enum": [ + "repo", + "binder", + "devcontainer" + ] + } + ] + } + ] + } + ] + }, + "ManuscriptSchema": { + "object": { + "properties": { + "article": { + "type": "string" + }, + "code-links": { + "$ref": "#/$defs/CodeLinksSchema" + }, + "manuscript-url": { + "type": "string" + }, + "meca-bundle": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "notebooks": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/NotebookViewSchema" + } + ] + } + }, + "resources": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "environment": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + } + } + }, + "BrandMeta": { + "object": { + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "full": { + "type": "string" + }, + "short": { + "type": "string" + } + } + } + } + ] + }, + "link": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "home": { + "type": "string" + }, + "mastodon": { + "type": "string" + }, + "github": { + "type": "string" + }, + "linkedin": { + "type": "string" + }, + "twitter": { + "type": "string" + }, + "facebook": { + "type": "string" + } + } + } + } + ] + } + } + } + }, + "BrandStringLightDark": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "light": { + "type": "string" + }, + "dark": { + "type": "string" + } + } + } + } + ] + }, + "BrandLogo": { + "object": { + "properties": { + "with": { + "object": { + "properties": {} + } + }, + "small": { + "$ref": "#/$defs/BrandStringLightDark" + }, + "medium": { + "$ref": "#/$defs/BrandStringLightDark" + }, + "large": { + "$ref": "#/$defs/BrandStringLightDark" + } + } + } + }, + "BrandNamedLogo": { + "enum": [ + "small", + "medium", + "large" + ] + }, + "BrandColorValue": { + "type": "string" + }, + "LogoStringLayout": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "location": { + "type": "string" + }, + "padding": { + "type": "string" + }, + "width": { + "type": "string" + }, + "src": { + "type": "string" + } + } + } + } + ] + }, + "BrandColor": { + "object": { + "properties": { + "with": { + "object": { + "properties": {} + } + }, + "foreground": { + "$ref": "#/$defs/BrandColorValue" + }, + "background": { + "$ref": "#/$defs/BrandColorValue" + }, + "primary": { + "$ref": "#/$defs/BrandColorValue" + }, + "secondary": { + "$ref": "#/$defs/BrandColorValue" + }, + "tertiary": { + "$ref": "#/$defs/BrandColorValue" + }, + "success": { + "$ref": "#/$defs/BrandColorValue" + }, + "info": { + "$ref": "#/$defs/BrandColorValue" + }, + "warning": { + "$ref": "#/$defs/BrandColorValue" + }, + "danger": { + "$ref": "#/$defs/BrandColorValue" + }, + "light": { + "$ref": "#/$defs/BrandColorValue" + }, + "dark": { + "$ref": "#/$defs/BrandColorValue" + }, + "emphasis": { + "$ref": "#/$defs/BrandColorValue" + }, + "link": { + "$ref": "#/$defs/BrandColorValue" + } + } + } + }, + "BrandMaybeNamedColor": { + "anyOf": [ + { + "$ref": "#/$defs/BrandNamedThemeColor" + }, + { + "type": "string" + } + ] + }, + "BrandNamedThemeColor": { + "enum": [ + "foreground", + "background", + "primary", + "secondary", + "tertiary", + "success", + "info", + "warning", + "danger", + "light", + "dark", + "emphasis", + "link" + ] + }, + "BrandTypography": { + "object": { + "properties": { + "with": { + "$ref": "#/$defs/BrandFontWith" + }, + "base": { + "$ref": "#/$defs/BrandTypographyOptions" + }, + "headings": { + "$ref": "#/$defs/BrandTypographyOptionsNoSize" + }, + "monospace": { + "$ref": "#/$defs/BrandTypographyOptions" + }, + "emphasis": { + "object": { + "properties": { + "weight": { + "$ref": "#/$defs/BrandFontWeight" + }, + "color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + }, + "background-color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + } + } + } + }, + "link": { + "object": { + "properties": { + "weight": { + "$ref": "#/$defs/BrandFontWeight" + }, + "decoration": { + "type": "string" + }, + "color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + }, + "background-color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + } + } + } + } + } + } + }, + "BrandTypographyOptions": { + "object": { + "properties": { + "family": { + "type": "string" + }, + "size": { + "type": "string" + }, + "line-height": { + "type": "string" + }, + "weight": { + "$ref": "#/$defs/BrandFontWeight" + }, + "style": { + "$ref": "#/$defs/BrandFontStyle" + }, + "color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + }, + "background-color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + }, + "files": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + ] + } + } + } + }, + "BrandNamedFont": { + "enum": [ + "base", + "headings", + "monospace" + ] + }, + "BrandTypographyOptionsNoSize": { + "object": { + "properties": { + "family": { + "type": "string" + }, + "line-height": { + "type": "string" + }, + "weight": { + "$ref": "#/$defs/BrandFontWeight" + }, + "style": { + "$ref": "#/$defs/BrandFontStyle" + }, + "color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + }, + "background-color": { + "$ref": "#/$defs/BrandMaybeNamedColor" + } + } + } + }, + "BrandFontWith": { + "object": { + "properties": {} + } + }, + "BrandFont": { + "anyOf": [ + { + "$ref": "#/$defs/BrandFontGoogle" + }, + { + "$ref": "#/$defs/BrandFontBunny" + }, + { + "$ref": "#/$defs/BrandFontFile" + }, + { + "$ref": "#/$defs/BrandFontFamily" + } + ] + }, + "BrandFontWeight": { + "enum": [ + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + "thin", + "extra-light", + "ultra-light", + "light", + "normal", + "regular", + "medium", + "semi-bold", + "demi-bold", + "bold", + "extra-bold", + "ultra-bold", + "black" + ] + }, + "BrandFontStyle": { + "enum": [ + "normal", + "italic" + ] + }, + "BrandFontCommon": { + "anyOf": [ + { + "type": "string" + }, + { + "object": { + "properties": { + "family": { + "type": "string" + }, + "weight": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/BrandFontWeight" + } + }, + { + "$ref": "#/$defs/BrandFontWeight" + } + ] + }, + "style": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/BrandFontStyle" + } + }, + { + "$ref": "#/$defs/BrandFontStyle" + } + ] + }, + "display": { + "enum": [ + "auto", + "block", + "swap", + "fallback", + "optional" + ] + } + } + } + } + ] + }, + "BrandFontGoogle": { + "object": { + "properties": { + "google": { + "$ref": "#/$defs/BrandFontCommon" + } + } + } + }, + "BrandFontBunny": { + "object": { + "properties": { + "bunny": { + "$ref": "#/$defs/BrandFontCommon" + } + } + } + }, + "BrandFontFile": { + "object": { + "properties": { + "family": { + "type": "string" + }, + "files": { + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + }, + { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string" + } + ] + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/BrandFontWeight" + } + }, + { + "$ref": "#/$defs/BrandFontWeight" + } + ] + }, + "style": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/BrandFontStyle" + } + }, + { + "$ref": "#/$defs/BrandFontStyle" + } + ] + }, + "display": { + "enum": [ + "auto", + "block", + "swap", + "fallback", + "optional" + ] + } + } + } + }, + "BrandFontFamily": { + "type": "string" + }, + "Brand": { + "object": { + "properties": { + "meta": { + "$ref": "#/$defs/BrandMeta" + }, + "logo": { + "$ref": "#/$defs/BrandLogo" + }, + "color": { + "$ref": "#/$defs/BrandColor" + }, + "typography": { + "$ref": "#/$defs/BrandTypography" + }, + "defaults": { + "type": "object" + } + } + } + }, + "ProjectConfig": { + "object": { + "properties": { + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "render": { + "type": "array", + "items": { + "type": "string" + } + }, + "execute-dir": { + "enum": [ + "file", + "project" + ] + }, + "output-dir": { + "type": "string" + }, + "lib-dir": { + "type": "string" + }, + "resources": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "preview": { + "$ref": "#/$defs/ProjectPreview" + }, + "pre-render": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "post-render": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "detect": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "BookProject": { + "object": { + "properties": {} + } + } + } +} \ No newline at end of file diff --git a/src/resources/types/schema-types.ts b/src/resources/types/schema-types.ts index 5bfac98b50f..0907dd07654 100644 --- a/src/resources/types/schema-types.ts +++ b/src/resources/types/schema-types.ts @@ -1287,7 +1287,7 @@ export type BrandLogo = { large?: BrandStringLightDark; medium?: BrandStringLightDark; small?: BrandStringLightDark; - with?: JsonObject; + with?: { [key: string]: BrandStringLightDark }; }; /* Provide definitions and defaults for brand's logo in various formats and sizes. */ export type BrandNamedLogo = @@ -1317,8 +1317,9 @@ export type BrandColor = { secondary?: BrandColorValue; success?: BrandColorValue; tertiary?: BrandColorValue; - with?: - JsonObject /* The brand's custom color palette. Any number of colors can be defined, each color having a custom name. */; + with?: { + [key: string]: BrandColorValue; + } /* The brand's custom color palette. Any number of colors can be defined, each color having a custom name. */; warning?: BrandColorValue; }; /* The brand's custom color palette and theme. */ @@ -1384,11 +1385,13 @@ export type BrandTypographyOptionsNoSize = { weight?: BrandFontWeight; }; /* Typographic options without a font size. */ -export type BrandFontWith = - JsonObject; /* Font files and definitions for the brand. */ +export type BrandFontWith = { + [key: string]: BrandFont; +}; /* Font files and definitions for the brand. */ export type BrandFont = | BrandFontGoogle + | BrandFontBunny | BrandFontFile | BrandFontFamily; /* Font files and definitions for the brand. */ @@ -1401,23 +1404,42 @@ export type BrandFontWeight = | 600 | 700 | 800 - | 900; /* A font weight. */ + | 900 + | "thin" + | "extra-light" + | "ultra-light" + | "light" + | "normal" + | "regular" + | "medium" + | "semi-bold" + | "demi-bold" + | "bold" + | "extra-bold" + | "ultra-bold" + | "black"; /* A font weight. */ export type BrandFontStyle = "normal" | "italic"; /* A font style. */ +export type BrandFontCommon = string | { + display?: + | "auto" + | "block" + | "swap" + | "fallback" + | "optional" /* The font display method, determines how a font face is font face is shown depending on its download status and readiness for use. */; + family?: string; + style?: MaybeArrayOf /* The font styles to include. */; + weight?: MaybeArrayOf; /* The font weights to include. */ +}; + export type BrandFontGoogle = { - google: string | { - display?: - | "auto" - | "block" - | "swap" - | "fallback" - | "optional" /* The font display method, determines how a font face is font face is shown depending on its download status and readiness for use. */; - family?: string; - style?: MaybeArrayOf /* The font styles to include. */; - weight?: MaybeArrayOf; /* The font weights to include. */ - }; -}; /* A Google Font definition. */ + google: BrandFontCommon; +}; /* A font definition from Google Fonts. */ + +export type BrandFontBunny = { + bunny: BrandFontCommon; +}; /* A font definition from fonts.bunny.net. */ export type BrandFontFile = { display?: diff --git a/src/vendor/cdn.skypack.dev/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js b/src/vendor/cdn.skypack.dev/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js new file mode 100644 index 00000000000..7369109654c --- /dev/null +++ b/src/vendor/cdn.skypack.dev/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js @@ -0,0 +1,19 @@ +var invariant = function(condition, format, a, b, c, d, e, f) { + if (!condition) { + var error; + if (format === void 0) { + error = new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings."); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error(format.replace(/%s/g, function() { + return args[argIndex++]; + })); + error.name = "Invariant Violation"; + } + error.framesToPop = 1; + throw error; + } +}; +var browser = invariant; +export default browser; diff --git a/src/vendor/cdn.skypack.dev/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js b/src/vendor/cdn.skypack.dev/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js new file mode 100644 index 00000000000..351b1872b30 --- /dev/null +++ b/src/vendor/cdn.skypack.dev/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js @@ -0,0 +1,6087 @@ +import invariant2 from "/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js"; +var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; +function createCommonjsModule(fn, basedir, module) { + return module = { + path: basedir, + exports: {}, + require: function(path, base) { + return commonjsRequire(path, base === void 0 || base === null ? module.path : base); + } + }, fn(module, module.exports), module.exports; +} +function commonjsRequire() { + throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs"); +} +var lodash = createCommonjsModule(function(module, exports) { + (function() { + var undefined$1; + var VERSION = "4.17.20"; + var LARGE_ARRAY_SIZE = 200; + var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function"; + var HASH_UNDEFINED = "__lodash_hash_undefined__"; + var MAX_MEMOIZE_SIZE = 500; + var PLACEHOLDER = "__lodash_placeholder__"; + var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4; + var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2; + var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 800, HOT_SPAN = 16; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3; + var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var wrapFlags = [ + ["ary", WRAP_ARY_FLAG], + ["bind", WRAP_BIND_FLAG], + ["bindKey", WRAP_BIND_KEY_FLAG], + ["curry", WRAP_CURRY_FLAG], + ["curryRight", WRAP_CURRY_RIGHT_FLAG], + ["flip", WRAP_FLIP_FLAG], + ["partial", WRAP_PARTIAL_FLAG], + ["partialRight", WRAP_PARTIAL_RIGHT_FLAG], + ["rearg", WRAP_REARG_FLAG] + ]; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]"; + 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]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); + var reTrim = /^\s+|\s+$/g, reTrimStart = /^\s+/, reTrimEnd = /\s+$/; + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /; + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + var reIsBinary = /^0b[01]+$/i; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsOctal = /^0o[0-7]+$/i; + var reIsUint = /^(?:0|[1-9]\d*)$/; + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + var rsApos = "['\u2019]", rsAstral = "[" + rsAstralRange + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d"; + var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq, rsSymbol = "(?:" + [rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral].join("|") + ")"; + var reApos = RegExp(rsApos, "g"); + var reComboMark = RegExp(rsCombo, "g"); + var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g"); + var reUnicodeWord = RegExp([ + rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")", + rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")", + rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower, + rsUpper + "+" + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join("|"), "g"); + var reHasUnicode = RegExp("[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]"); + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + var contextProps = [ + "Array", + "Buffer", + "DataView", + "Date", + "Error", + "Float32Array", + "Float64Array", + "Function", + "Int8Array", + "Int16Array", + "Int32Array", + "Map", + "Math", + "Object", + "Promise", + "RegExp", + "Set", + "String", + "Symbol", + "TypeError", + "Uint8Array", + "Uint8ClampedArray", + "Uint16Array", + "Uint32Array", + "WeakMap", + "_", + "clearTimeout", + "isFinite", + "parseInt", + "setTimeout" + ]; + var templateCounter = -1; + 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; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + \u00C0: "A", + \u00C1: "A", + \u00C2: "A", + \u00C3: "A", + \u00C4: "A", + \u00C5: "A", + \u00E0: "a", + \u00E1: "a", + \u00E2: "a", + \u00E3: "a", + \u00E4: "a", + \u00E5: "a", + \u00C7: "C", + \u00E7: "c", + \u00D0: "D", + \u00F0: "d", + \u00C8: "E", + \u00C9: "E", + \u00CA: "E", + \u00CB: "E", + \u00E8: "e", + \u00E9: "e", + \u00EA: "e", + \u00EB: "e", + \u00CC: "I", + \u00CD: "I", + \u00CE: "I", + \u00CF: "I", + \u00EC: "i", + \u00ED: "i", + \u00EE: "i", + \u00EF: "i", + \u00D1: "N", + \u00F1: "n", + \u00D2: "O", + \u00D3: "O", + \u00D4: "O", + \u00D5: "O", + \u00D6: "O", + \u00D8: "O", + \u00F2: "o", + \u00F3: "o", + \u00F4: "o", + \u00F5: "o", + \u00F6: "o", + \u00F8: "o", + \u00D9: "U", + \u00DA: "U", + \u00DB: "U", + \u00DC: "U", + \u00F9: "u", + \u00FA: "u", + \u00FB: "u", + \u00FC: "u", + \u00DD: "Y", + \u00FD: "y", + \u00FF: "y", + \u00C6: "Ae", + \u00E6: "ae", + \u00DE: "Th", + \u00FE: "th", + \u00DF: "ss", + \u0100: "A", + \u0102: "A", + \u0104: "A", + \u0101: "a", + \u0103: "a", + \u0105: "a", + \u0106: "C", + \u0108: "C", + \u010A: "C", + \u010C: "C", + \u0107: "c", + \u0109: "c", + \u010B: "c", + \u010D: "c", + \u010E: "D", + \u0110: "D", + \u010F: "d", + \u0111: "d", + \u0112: "E", + \u0114: "E", + \u0116: "E", + \u0118: "E", + \u011A: "E", + \u0113: "e", + \u0115: "e", + \u0117: "e", + \u0119: "e", + \u011B: "e", + \u011C: "G", + \u011E: "G", + \u0120: "G", + \u0122: "G", + \u011D: "g", + \u011F: "g", + \u0121: "g", + \u0123: "g", + \u0124: "H", + \u0126: "H", + \u0125: "h", + \u0127: "h", + \u0128: "I", + \u012A: "I", + \u012C: "I", + \u012E: "I", + \u0130: "I", + \u0129: "i", + \u012B: "i", + \u012D: "i", + \u012F: "i", + \u0131: "i", + \u0134: "J", + \u0135: "j", + \u0136: "K", + \u0137: "k", + \u0138: "k", + \u0139: "L", + \u013B: "L", + \u013D: "L", + \u013F: "L", + \u0141: "L", + \u013A: "l", + \u013C: "l", + \u013E: "l", + \u0140: "l", + \u0142: "l", + \u0143: "N", + \u0145: "N", + \u0147: "N", + \u014A: "N", + \u0144: "n", + \u0146: "n", + \u0148: "n", + \u014B: "n", + \u014C: "O", + \u014E: "O", + \u0150: "O", + \u014D: "o", + \u014F: "o", + \u0151: "o", + \u0154: "R", + \u0156: "R", + \u0158: "R", + \u0155: "r", + \u0157: "r", + \u0159: "r", + \u015A: "S", + \u015C: "S", + \u015E: "S", + \u0160: "S", + \u015B: "s", + \u015D: "s", + \u015F: "s", + \u0161: "s", + \u0162: "T", + \u0164: "T", + \u0166: "T", + \u0163: "t", + \u0165: "t", + \u0167: "t", + \u0168: "U", + \u016A: "U", + \u016C: "U", + \u016E: "U", + \u0170: "U", + \u0172: "U", + \u0169: "u", + \u016B: "u", + \u016D: "u", + \u016F: "u", + \u0171: "u", + \u0173: "u", + \u0174: "W", + \u0175: "w", + \u0176: "Y", + \u0177: "y", + \u0178: "Y", + \u0179: "Z", + \u017B: "Z", + \u017D: "Z", + \u017A: "z", + \u017C: "z", + \u017E: "z", + \u0132: "IJ", + \u0133: "ij", + \u0152: "Oe", + \u0153: "oe", + \u0149: "'n", + \u017F: "s" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeParseFloat = parseFloat, freeParseInt = parseInt; + var freeGlobal = typeof commonjsGlobal == "object" && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal; + var freeSelf = typeof self == "object" && self && self.Object === Object && self; + var root = freeGlobal || freeSelf || Function("return this")(); + var freeExports = exports && !exports.nodeType && exports; + var freeModule = freeExports && true && module && !module.nodeType && module; + var moduleExports = freeModule && freeModule.exports === freeExports; + var freeProcess = moduleExports && freeGlobal.process; + var nodeUtil = function() { + try { + var types = freeModule && freeModule.require && freeModule.require("util").types; + if (types) { + return types; + } + return freeProcess && freeProcess.binding && freeProcess.binding("util"); + } catch (e) { + } + }(); + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + function apply(func, thisArg, args) { + switch (args.length) { + case 0: + return func.call(thisArg); + case 1: + return func.call(thisArg, args[0]); + case 2: + return func.call(thisArg, args[0], args[1]); + case 3: + return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + function arrayEach(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayFilter(array, predicate) { + var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + function arrayIncludesWith(array, value, comparator) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + function arrayMap(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + var asciiSize = baseProperty("length"); + function asciiToArray(string) { + return string.split(""); + } + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection2) { + if (predicate(value, key, collection2)) { + result = key; + return false; + } + }); + return result; + } + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 1 : -1); + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex); + } + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + function baseIsNaN(value) { + return value !== value; + } + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? baseSum(array, iteratee) / length : NAN; + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined$1 : object[key]; + }; + } + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined$1 : object[key]; + }; + } + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection2) { + accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection2); + }); + return accumulator; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSum(array, iteratee) { + var result, index = -1, length = array.length; + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined$1) { + result = result === undefined$1 ? current : result + current; + } + } + return result; + } + function baseTimes(n, iteratee) { + var index = -1, result = Array(n); + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + function cacheHas(cache, key) { + return cache.has(key); + } + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, length = strSymbols.length; + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) { + } + return index; + } + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) { + } + return index; + } + function countHolders(array, placeholder) { + var length = array.length, result = 0; + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + var deburrLetter = basePropertyOf(deburredLetters); + var escapeHtmlChar = basePropertyOf(htmlEscapes); + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function getValue(object, key) { + return object == null ? undefined$1 : object[key]; + } + function hasUnicode(string) { + return reHasUnicode.test(string); + } + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + function iteratorToArray(iterator) { + var data, result = []; + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + function mapToArray(map) { + var index = -1, result = Array(map.size); + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = 0, result = []; + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + function setToArray(set) { + var index = -1, result = Array(set.size); + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + function setToPairs(set) { + var index = -1, result = Array(set.size); + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + function stringSize(string) { + return hasUnicode(string) ? unicodeSize(string) : asciiSize(string); + } + function stringToArray(string) { + return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string); + } + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + var runInContext = function runInContext2(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + var Array2 = context.Array, Date = context.Date, Error2 = context.Error, Function2 = context.Function, Math = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype; + var coreJsData = context["__core-js_shared__"]; + var funcToString = funcProto.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var maskSrcKey = function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ""); + return uid ? "Symbol(src)_1." + uid : ""; + }(); + var nativeObjectToString = objectProto.toString; + var objectCtorString = funcToString.call(Object2); + var oldDash = root._; + var reIsNative = RegExp2("^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var Buffer = moduleExports ? context.Buffer : undefined$1, Symbol = context.Symbol, Uint8Array = context.Uint8Array, allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1, getPrototype = overArg(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined$1, symIterator = Symbol ? Symbol.iterator : undefined$1, symToStringTag = Symbol ? Symbol.toStringTag : undefined$1; + var defineProperty = function() { + try { + var func = getNative(Object2, "defineProperty"); + func({}, "", {}); + return func; + } catch (e) { + } + }(); + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, ctxNow = Date && Date.now !== root.Date.now && Date.now, ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + var nativeCeil = Math.ceil, nativeFloor = Math.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax = Math.max, nativeMin = Math.min, nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReverse = arrayProto.reverse; + var DataView = getNative(context, "DataView"), Map = getNative(context, "Map"), Promise = getNative(context, "Promise"), Set = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object2, "create"); + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap); + var symbolProto = Symbol ? Symbol.prototype : undefined$1, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1, symbolToString = symbolProto ? symbolProto.toString : undefined$1; + function lodash2(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + var baseCreate = function() { + function object() { + } + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result2 = new object(); + object.prototype = undefined$1; + return result2; + }; + }(); + function baseLodash() { + } + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined$1; + } + lodash2.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash2 + } + }; + lodash2.prototype = baseLodash.prototype; + lodash2.prototype.constructor = lodash2; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + function lazyClone() { + var result2 = new LazyWrapper(this.__wrapped__); + result2.__actions__ = copyArray(this.__actions__); + result2.__dir__ = this.__dir__; + result2.__filtered__ = this.__filtered__; + result2.__iteratees__ = copyArray(this.__iteratees__); + result2.__takeCount__ = this.__takeCount__; + result2.__views__ = copyArray(this.__views__); + return result2; + } + function lazyReverse() { + if (this.__filtered__) { + var result2 = new LazyWrapper(this); + result2.__dir__ = -1; + result2.__filtered__ = true; + } else { + result2 = this.clone(); + result2.__dir__ *= -1; + } + return result2; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || !isRight && arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result2 = []; + outer: + while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee2 = data.iteratee, type2 = data.type, computed = iteratee2(value); + if (type2 == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type2 == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result2[resIndex++] = value; + } + return result2; + } + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + function Hash(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + function hashDelete(key) { + var result2 = this.has(key) && delete this.__data__[key]; + this.size -= result2 ? 1 : 0; + return result2; + } + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result2 = data[key]; + return result2 === HASH_UNDEFINED ? undefined$1 : result2; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined$1; + } + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined$1 : hasOwnProperty.call(data, key); + } + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = nativeCreate && value === undefined$1 ? HASH_UNDEFINED : value; + return this; + } + Hash.prototype.clear = hashClear; + Hash.prototype["delete"] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + function ListCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + 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); + } + --this.size; + return true; + } + function listCacheGet(key) { + var data = this.__data__, index = assocIndexOf(data, key); + return index < 0 ? undefined$1 : data[index][1]; + } + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + function listCacheSet(key, value) { + var data = this.__data__, index = assocIndexOf(data, key); + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + ListCache.prototype.clear = listCacheClear; + ListCache.prototype["delete"] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + function MapCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + function mapCacheClear() { + this.size = 0; + this.__data__ = { + hash: new Hash(), + map: new (Map || ListCache)(), + string: new Hash() + }; + } + function mapCacheDelete(key) { + var result2 = getMapData(this, key)["delete"](key); + this.size -= result2 ? 1 : 0; + return result2; + } + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + function mapCacheSet(key, value) { + var data = getMapData(this, key), size2 = data.size; + data.set(key, value); + this.size += data.size == size2 ? 0 : 1; + return this; + } + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype["delete"] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + function SetCache(values2) { + var index = -1, length = values2 == null ? 0 : values2.length; + this.__data__ = new MapCache(); + while (++index < length) { + this.add(values2[index]); + } + } + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + function setCacheHas(value) { + return this.__data__.has(value); + } + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + function stackClear() { + this.__data__ = new ListCache(); + this.size = 0; + } + function stackDelete(key) { + var data = this.__data__, result2 = data["delete"](key); + this.size = data.size; + return result2; + } + function stackGet(key) { + return this.__data__.get(key); + } + function stackHas(key) { + return this.__data__.has(key); + } + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + Stack.prototype.clear = stackClear; + Stack.prototype["delete"] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes(value.length, String) : [], length = result2.length; + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) { + result2.push(key); + } + } + return result2; + } + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined$1; + } + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + function assignMergeValue(object, key, value) { + if (value !== undefined$1 && !eq(object[key], value) || value === undefined$1 && !(key in object)) { + baseAssignValue(object, key, value); + } + } + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined$1 && !(key in object)) { + baseAssignValue(object, key, value); + } + } + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + function baseAggregator(collection, setter, iteratee2, accumulator) { + baseEach(collection, function(value, key, collection2) { + setter(accumulator, value, iteratee2(value), collection2); + }); + return accumulator; + } + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + function baseAssignValue(object, key, value) { + if (key == "__proto__" && defineProperty) { + defineProperty(object, key, { + configurable: true, + enumerable: true, + value, + writable: true + }); + } else { + object[key] = value; + } + } + function baseAt(object, paths) { + var index = -1, length = paths.length, result2 = Array2(length), skip = object == null; + while (++index < length) { + result2[index] = skip ? undefined$1 : get(object, paths[index]); + } + return result2; + } + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined$1) { + number = number <= upper ? number : upper; + } + if (lower !== undefined$1) { + number = number >= lower ? number : lower; + } + } + return number; + } + function baseClone(value, bitmask, customizer, key, object, stack) { + var result2, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG; + if (customizer) { + result2 = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result2 !== undefined$1) { + return result2; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result2 = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result2); + } + } else { + var tag = getTag(value), isFunc = tag == funcTag || tag == genTag; + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result2 = isFlat || isFunc ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat ? copySymbolsIn(value, baseAssignIn(result2, value)) : copySymbols(value, baseAssign(result2, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result2 = initCloneByTag(value, tag, isDeep); + } + } + stack || (stack = new Stack()); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result2); + if (isSet(value)) { + value.forEach(function(subValue) { + result2.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key2) { + result2.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + } + var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys; + var props = isArr ? undefined$1 : keysFunc(value); + arrayEach(props || value, function(subValue, key2) { + if (props) { + key2 = subValue; + subValue = value[key2]; + } + assignValue(result2, key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + return result2; + } + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object2(object); + while (length--) { + var key = props[length], predicate = source[key], value = object[key]; + if (value === undefined$1 && !(key in object) || !predicate(value)) { + return false; + } + } + return true; + } + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined$1, args); + }, wait); + } + function baseDifference(array, values2, iteratee2, comparator) { + var index = -1, includes2 = arrayIncludes, isCommon = true, length = array.length, result2 = [], valuesLength = values2.length; + if (!length) { + return result2; + } + if (iteratee2) { + values2 = arrayMap(values2, baseUnary(iteratee2)); + } + if (comparator) { + includes2 = arrayIncludesWith; + isCommon = false; + } else if (values2.length >= LARGE_ARRAY_SIZE) { + includes2 = cacheHas; + isCommon = false; + values2 = new SetCache(values2); + } + outer: + while (++index < length) { + var value = array[index], computed = iteratee2 == null ? value : iteratee2(value); + value = comparator || value !== 0 ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values2[valuesIndex] === computed) { + continue outer; + } + } + result2.push(value); + } else if (!includes2(values2, computed, comparator)) { + result2.push(value); + } + } + return result2; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result2 = true; + baseEach(collection, function(value, index, collection2) { + result2 = !!predicate(value, index, collection2); + return result2; + }); + return result2; + } + function baseExtremum(array, iteratee2, comparator) { + var index = -1, length = array.length; + while (++index < length) { + var value = array[index], current = iteratee2(value); + if (current != null && (computed === undefined$1 ? current === current && !isSymbol(current) : comparator(current, computed))) { + var computed = current, result2 = value; + } + } + return result2; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined$1 || end > length ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result2 = []; + baseEach(collection, function(value, index, collection2) { + if (predicate(value, index, collection2)) { + result2.push(value); + } + }); + return result2; + } + function baseFlatten(array, depth, predicate, isStrict, result2) { + var index = -1, length = array.length; + predicate || (predicate = isFlattenable); + result2 || (result2 = []); + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + baseFlatten(value, depth - 1, predicate, isStrict, result2); + } else { + arrayPush(result2, value); + } + } else if (!isStrict) { + result2[result2.length] = value; + } + } + return result2; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForOwn(object, iteratee2) { + return object && baseFor(object, iteratee2, keys); + } + function baseForOwnRight(object, iteratee2) { + return object && baseForRight(object, iteratee2, keys); + } + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + function baseGet(object, path) { + path = castPath(path, object); + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return index && index == length ? object : undefined$1; + } + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result2 = keysFunc(object); + return isArray(object) ? result2 : arrayPush(result2, symbolsFunc(object)); + } + function baseGetTag(value) { + if (value == null) { + return value === undefined$1 ? undefinedTag : nullTag; + } + return symToStringTag && symToStringTag in Object2(value) ? getRawTag(value) : objectToString(value); + } + function baseGt(value, other) { + return value > other; + } + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + function baseHasIn(object, key) { + return object != null && key in Object2(object); + } + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + function baseIntersection(arrays, iteratee2, comparator) { + var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array2(othLength), maxLength = Infinity, result2 = []; + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee2) { + array = arrayMap(array, baseUnary(iteratee2)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined$1; + } + array = arrays[0]; + var index = -1, seen = caches[0]; + outer: + while (++index < length && result2.length < maxLength) { + var value = array[index], computed = iteratee2 ? iteratee2(value) : value; + value = comparator || value !== 0 ? value : 0; + if (!(seen ? cacheHas(seen, computed) : includes2(result2, computed, comparator))) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache ? cacheHas(cache, computed) : includes2(arrays[othIndex], computed, comparator))) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result2.push(value); + } + } + return result2; + } + function baseInverter(object, setter, iteratee2, accumulator) { + baseForOwn(object, function(value, key, object2) { + setter(accumulator, iteratee2(value), key, object2); + }); + return accumulator; + } + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined$1 : apply(func, object, args); + } + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other); + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack()); + return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_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, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack()); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = Object2(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined$1 && !(key in object)) { + return false; + } + } else { + var stack = new Stack(); + if (customizer) { + var result2 = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result2 === undefined$1 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result2)) { + return false; + } + } + } + return true; + } + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + function baseIsTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + function baseIteratee(value) { + if (typeof value == "function") { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == "object") { + return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); + } + return property(value); + } + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result2 = []; + for (var key in Object2(object)) { + if (hasOwnProperty.call(object, key) && key != "constructor") { + result2.push(key); + } + } + return result2; + } + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), result2 = []; + for (var key in object) { + if (!(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result2.push(key); + } + } + return result2; + } + function baseLt(value, other) { + return value < other; + } + function baseMap(collection, iteratee2) { + var index = -1, result2 = isArrayLike(collection) ? Array2(collection.length) : []; + baseEach(collection, function(value, key, collection2) { + result2[++index] = iteratee2(value, key, collection2); + }); + return result2; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return objValue === undefined$1 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack()); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } else { + var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + "", object, source, stack) : undefined$1; + if (newValue === undefined$1) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), srcValue = safeGet(source, key), stacked = stack.get(srcValue); + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined$1; + var isCommon = newValue === undefined$1; + if (isCommon) { + var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue); + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } else { + newValue = []; + } + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } else { + isCommon = false; + } + } + if (isCommon) { + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack["delete"](srcValue); + } + assignMergeValue(object, key, newValue); + } + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined$1; + } + function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee2) { + if (isArray(iteratee2)) { + return function(value) { + return baseGet(value, iteratee2.length === 1 ? iteratee2[0] : iteratee2); + }; + } + return iteratee2; + }); + } else { + iteratees = [identity]; + } + var index = -1; + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + var result2 = baseMap(collection, function(value, key, collection2) { + var criteria = arrayMap(iteratees, function(iteratee2) { + return iteratee2(value); + }); + return {criteria, index: ++index, value}; + }); + return baseSortBy(result2, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + function basePickBy(object, paths, predicate) { + var index = -1, length = paths.length, result2 = {}; + while (++index < length) { + var path = paths[index], value = baseGet(object, path); + if (predicate(value, path)) { + baseSet(result2, castPath(path, object), value); + } + } + return result2; + } + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + function basePullAll(array, values2, iteratee2, comparator) { + var indexOf2 = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values2.length, seen = array; + if (array === values2) { + values2 = copyArray(values2); + } + if (iteratee2) { + seen = arrayMap(array, baseUnary(iteratee2)); + } + while (++index < length) { + var fromIndex = 0, value = values2[index], computed = iteratee2 ? iteratee2(value) : value; + while ((fromIndex = indexOf2(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, lastIndex = length - 1; + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + function baseRange(start, end, step, fromRight) { + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array2(length); + while (length--) { + result2[fromRight ? length : ++index] = start; + start += step; + } + return result2; + } + function baseRepeat(string, n) { + var result2 = ""; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result2; + } + do { + if (n % 2) { + result2 += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + return result2; + } + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ""); + } + function baseSample(collection) { + return arraySample(values(collection)); + } + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = toKey(path[index]), newValue = value; + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return object; + } + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined$1; + if (newValue === undefined$1) { + newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {}; + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, "toString", { + configurable: true, + enumerable: false, + value: constant(string), + writable: true + }); + }; + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + function baseSlice(array, start, end) { + var index = -1, length = array.length; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result2 = Array2(length); + while (++index < length) { + result2[index] = array[index + start]; + } + return result2; + } + function baseSome(collection, predicate) { + var result2; + baseEach(collection, function(value, index, collection2) { + result2 = predicate(value, index, collection2); + return !result2; + }); + return !!result2; + } + function baseSortedIndex(array, value, retHighest) { + var low = 0, high = array == null ? low : array.length; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + function baseSortedIndexBy(array, value, iteratee2, retHighest) { + var low = 0, high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + value = iteratee2(value); + var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined$1; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee2(array[mid]), othIsDefined = computed !== undefined$1, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed); + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function baseSortedUniq(array, iteratee2) { + var index = -1, length = array.length, resIndex = 0, result2 = []; + while (++index < length) { + var value = array[index], computed = iteratee2 ? iteratee2(value) : value; + if (!index || !eq(computed, seen)) { + var seen = computed; + result2[resIndex++] = value === 0 ? 0 : value; + } + } + return result2; + } + function baseToNumber(value) { + if (typeof value == "number") { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + function baseToString(value) { + if (typeof value == "string") { + return value; + } + if (isArray(value)) { + return arrayMap(value, baseToString) + ""; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ""; + } + var result2 = value + ""; + return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2; + } + function baseUniq(array, iteratee2, comparator) { + var index = -1, includes2 = arrayIncludes, length = array.length, isCommon = true, result2 = [], seen = result2; + if (comparator) { + isCommon = false; + includes2 = arrayIncludesWith; + } else if (length >= LARGE_ARRAY_SIZE) { + var set2 = iteratee2 ? null : createSet(array); + if (set2) { + return setToArray(set2); + } + isCommon = false; + includes2 = cacheHas; + seen = new SetCache(); + } else { + seen = iteratee2 ? [] : result2; + } + outer: + while (++index < length) { + var value = array[index], computed = iteratee2 ? iteratee2(value) : value; + value = comparator || value !== 0 ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee2) { + seen.push(computed); + } + result2.push(value); + } else if (!includes2(seen, computed, comparator)) { + if (seen !== result2) { + seen.push(computed); + } + result2.push(value); + } + } + return result2; + } + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) { + } + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result2 = value; + if (result2 instanceof LazyWrapper) { + result2 = result2.value(); + } + return arrayReduce(actions, function(result3, action) { + return action.func.apply(action.thisArg, arrayPush([result3], action.args)); + }, result2); + } + function baseXor(arrays, iteratee2, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, result2 = Array2(length); + while (++index < length) { + var array = arrays[index], othIndex = -1; + while (++othIndex < length) { + if (othIndex != index) { + result2[index] = baseDifference(result2[index] || array, arrays[othIndex], iteratee2, comparator); + } + } + } + return baseUniq(baseFlatten(result2, 1), iteratee2, comparator); + } + function baseZipObject(props, values2, assignFunc) { + var index = -1, length = props.length, valsLength = values2.length, result2 = {}; + while (++index < length) { + var value = index < valsLength ? values2[index] : undefined$1; + assignFunc(result2, props[index], value); + } + return result2; + } + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + function castFunction(value) { + return typeof value == "function" ? value : identity; + } + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + var castRest = baseRest; + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined$1 ? length : end; + return !start && end >= length ? array : baseSlice(array, start, end); + } + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, result2 = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + buffer.copy(result2); + return result2; + } + function cloneArrayBuffer(arrayBuffer) { + var result2 = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result2).set(new Uint8Array(arrayBuffer)); + return result2; + } + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + function cloneRegExp(regexp) { + var result2 = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result2.lastIndex = regexp.lastIndex; + return result2; + } + function cloneSymbol(symbol) { + return symbolValueOf ? Object2(symbolValueOf.call(symbol)) : {}; + } + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined$1, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value); + var othIsDefined = other !== undefined$1, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other); + if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) { + return 1; + } + if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) { + return -1; + } + } + return 0; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result2 = compareAscending(objCriteria[index], othCriteria[index]); + if (result2) { + if (index >= ordersLength) { + return result2; + } + var order = orders[index]; + return result2 * (order == "desc" ? -1 : 1); + } + } + return object.index - other.index; + } + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(leftLength + rangeLength), isUncurried = !isCurried; + while (++leftIndex < leftLength) { + result2[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result2[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result2[leftIndex++] = args[argsIndex++]; + } + return result2; + } + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(rangeLength + rightLength), isUncurried = !isCurried; + while (++argsIndex < rangeLength) { + result2[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result2[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result2[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result2; + } + function copyArray(source, array) { + var index = -1, length = source.length; + array || (array = Array2(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined$1; + if (newValue === undefined$1) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + function createAggregator(setter, initializer) { + return function(collection, iteratee2) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {}; + return func(collection, setter, getIteratee(iteratee2, 2), accumulator); + }; + } + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined$1, guard = length > 2 ? sources[2] : undefined$1; + customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : undefined$1; + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined$1 : customizer; + length = 1; + } + object = Object2(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee2) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee2); + } + var length = collection.length, index = fromRight ? length : -1, iterable = Object2(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee2(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee2, keysFunc) { + var index = -1, iterable = Object2(object), props = keysFunc(object), length = props.length; + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee2(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined$1; + var chr = strSymbols ? strSymbols[0] : string.charAt(0); + var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1); + return chr[methodName]() + trailing; + }; + } + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, "")), callback, ""); + }; + } + function createCtor(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + case 1: + return new Ctor(args[0]); + case 2: + return new Ctor(args[0], args[1]); + case 3: + return new Ctor(args[0], args[1], args[2]); + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result2 = Ctor.apply(thisBinding, args); + return isObject(result2) ? result2 : thisBinding; + }; + } + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + function wrapper() { + var length = arguments.length, args = Array2(length), index = length, placeholder = getHolder(wrapper); + while (index--) { + args[index] = arguments[index]; + } + var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder); + length -= holders.length; + if (length < arity) { + return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined$1, args, holders, undefined$1, undefined$1, arity - length); + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object2(collection); + if (!isArrayLike(collection)) { + var iteratee2 = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { + return iteratee2(iterable[key], key, iterable); + }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee2 ? collection[index] : index] : undefined$1; + }; + } + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == "wrapper") { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined$1; + if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index2 = 0, result2 = length ? funcs[index2].apply(this, args) : value; + while (++index2 < length) { + result2 = funcs[index2].call(this, result2); + } + return result2; + }; + }); + } + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary2, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined$1 : createCtor(func); + function wrapper() { + var length = arguments.length, args = Array2(length), index = length; + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary2, arity - length); + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary2 < length) { + args.length = ary2; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createInverter(setter, toIteratee) { + return function(object, iteratee2) { + return baseInverter(object, setter, toIteratee(iteratee2), {}); + }; + } + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result2; + if (value === undefined$1 && other === undefined$1) { + return defaultValue; + } + if (value !== undefined$1) { + result2 = value; + } + if (other !== undefined$1) { + if (result2 === undefined$1) { + return other; + } + if (typeof value == "string" || typeof other == "string") { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result2 = operator(value, other); + } + return result2; + }; + } + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee2) { + return apply(iteratee2, thisArg, args); + }); + }); + }); + } + function createPadding(length, chars) { + chars = chars === undefined$1 ? " " : baseToString(chars); + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result2 = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) ? castSlice(stringToArray(result2), 0, length).join("") : result2.slice(0, length); + } + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array2(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func; + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != "number" && isIterateeCall(start, end, step)) { + end = step = undefined$1; + } + start = toFinite(start); + if (end === undefined$1) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined$1 ? start < end ? 1 : -1 : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == "string" && typeof other == "string")) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary2, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined$1, newHoldersRight = isCurry ? undefined$1 : holders, newPartials = isCurry ? partials : undefined$1, newPartialsRight = isCurry ? undefined$1 : partials; + bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, + bitmask, + thisArg, + newPartials, + newHolders, + newPartialsRight, + newHoldersRight, + argPos, + ary2, + arity + ]; + var result2 = wrapFunc.apply(undefined$1, newData); + if (isLaziable(func)) { + setData(result2, newData); + } + result2.placeholder = placeholder; + return setWrapToString(result2, func, bitmask); + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision && nativeIsFinite(number)) { + var pair = (toString(number) + "e").split("e"), value = func(pair[0] + "e" + (+pair[1] + precision)); + pair = (toString(value) + "e").split("e"); + return +(pair[0] + "e" + (+pair[1] - precision)); + } + return func(number); + }; + } + var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function(values2) { + return new Set(values2); + }; + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary2, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined$1; + } + ary2 = ary2 === undefined$1 ? ary2 : nativeMax(toInteger(ary2), 0); + arity = arity === undefined$1 ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined$1; + } + var data = isBindKey ? undefined$1 : getData(func); + var newData = [ + func, + bitmask, + thisArg, + partials, + holders, + partialsRight, + holdersRight, + argPos, + ary2, + arity + ]; + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined$1 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0); + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result2 = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result2 = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result2 = createPartial(func, bitmask, thisArg, partials); + } else { + result2 = createHybrid.apply(undefined$1, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result2, newData), func, bitmask); + } + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined$1 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) { + return srcValue; + } + return objValue; + } + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack); + stack["delete"](srcValue); + } + return objValue; + } + function customOmitClone(value) { + return isPlainObject(value) ? undefined$1 : value; + } + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined$1; + stack.set(array, other); + stack.set(other, array); + 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$1) { + if (compared) { + continue; + } + result2 = false; + break; + } + if (seen) { + if (!arraySome(other, function(othValue2, othIndex) { + if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result2 = false; + break; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + result2 = false; + break; + } + } + stack["delete"](array); + stack["delete"](other); + return result2; + } + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, 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: + return eq(+object, +other); + case errorTag: + return object.name == other.name && object.message == other.message; + case regexpTag: + case stringTag: + return object == other + ""; + case mapTag: + var convert = mapToArray; + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + if (object.size != other.size && !isPartial) { + return false; + } + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + stack.set(object, other); + var result2 = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack["delete"](object); + return result2; + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(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; + } + } + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result2 = 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); + } + if (!(compared === undefined$1 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) { + result2 = false; + break; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (result2 && !skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + result2 = false; + } + } + stack["delete"](object); + stack["delete"](other); + return result2; + } + function flatRest(func) { + return setToString(overRest(func, undefined$1, flatten), func + ""); + } + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result2 = func.name + "", array = realNames[result2], length = hasOwnProperty.call(realNames, result2) ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result2; + } + function getHolder(func) { + var object = hasOwnProperty.call(lodash2, "placeholder") ? lodash2 : func; + return object.placeholder; + } + function getIteratee() { + var result2 = lodash2.iteratee || iteratee; + result2 = result2 === iteratee ? baseIteratee : result2; + return arguments.length ? result2(arguments[0], arguments[1]) : result2; + } + function getMapData(map2, key) { + var data = map2.__data__; + return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; + } + function getMatchData(object) { + var result2 = keys(object), length = result2.length; + while (length--) { + var key = result2[length], value = object[key]; + result2[length] = [key, value, isStrictComparable(value)]; + } + return result2; + } + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined$1; + } + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; + try { + value[symToStringTag] = undefined$1; + var unmasked = true; + } catch (e) { + } + var result2 = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result2; + } + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object2(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result2 = []; + while (object) { + arrayPush(result2, getSymbols(object)); + object = getPrototype(object); + } + return result2; + }; + var getTag = baseGetTag; + 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 result2 = baseGetTag(value), Ctor = result2 == objectTag ? value.constructor : undefined$1, ctorString = Ctor ? toSource(Ctor) : ""; + 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 result2; + }; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size2 = data.size; + switch (data.type) { + case "drop": + start += size2; + break; + case "dropRight": + end -= size2; + break; + case "take": + end = nativeMin(end, start + size2); + break; + case "takeRight": + start = nativeMax(start, end - size2); + break; + } + } + return {start, end}; + } + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + var index = -1, length = path.length, result2 = false; + while (++index < length) { + var key = toKey(path[index]); + if (!(result2 = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result2 || ++index != length) { + return result2; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)); + } + function initCloneArray(array) { + var length = array.length, result2 = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result2.index = array.index; + result2.input = array.input; + } + return result2; + } + function initCloneObject(object) { + return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {}; + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + case boolTag: + case dateTag: + return new Ctor(+object); + case dataViewTag: + return cloneDataView(object, isDeep); + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + return cloneTypedArray(object, isDeep); + case mapTag: + return new Ctor(); + case numberTag: + case stringTag: + return new Ctor(object); + case regexpTag: + return cloneRegExp(object); + case setTag: + return new Ctor(); + case symbolTag: + return cloneSymbol(object); + } + } + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? "& " : "") + details[lastIndex]; + details = details.join(length > 2 ? ", " : " "); + return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n"); + } + function isFlattenable(value) { + return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]); + } + function isIndex(value, length) { + var type2 = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && (type2 == "number" || type2 != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type2 = typeof index; + if (type2 == "number" ? isArrayLike(object) && isIndex(index, object.length) : type2 == "string" && index in object) { + return eq(object[index], value); + } + return false; + } + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type2 = typeof value; + if (type2 == "number" || type2 == "symbol" || type2 == "boolean" || value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object2(object); + } + function isKeyable(value) { + var type2 = typeof value; + return type2 == "string" || type2 == "number" || type2 == "symbol" || type2 == "boolean" ? value !== "__proto__" : value === null; + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash2[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isMasked(func) { + return !!maskSrcKey && maskSrcKey in func; + } + var isMaskable = coreJsData ? isFunction : stubFalse; + function isPrototype(value) { + var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto; + return value === proto; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && (srcValue !== undefined$1 || key in Object2(object)); + }; + } + function memoizeCapped(func) { + var result2 = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + var cache = result2.cache; + return result2; + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + value = source[7]; + if (value) { + data[7] = value; + } + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function nativeKeysIn(object) { + var result2 = []; + if (object != null) { + for (var key in Object2(object)) { + result2.push(key); + } + } + return result2; + } + function objectToString(value) { + return nativeObjectToString.call(value); + } + function overRest(func, start, transform2) { + start = nativeMax(start === undefined$1 ? func.length - 1 : start, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array2(length); + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array2(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform2(array); + return apply(func, this, otherArgs); + }; + } + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1; + } + return array; + } + function safeGet(object, key) { + if (key === "constructor" && typeof object[key] === "function") { + return; + } + if (key == "__proto__") { + return; + } + return object[key]; + } + var setData = shortOut(baseSetData); + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + var setToString = shortOut(baseSetToString); + function setWrapToString(wrapper, reference, bitmask) { + var source = reference + ""; + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + function shortOut(func) { + var count = 0, lastCalled = 0; + return function() { + var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined$1, arguments); + }; + } + function shuffleSelf(array, size2) { + var index = -1, length = array.length, lastIndex = length - 1; + size2 = size2 === undefined$1 ? length : size2; + while (++index < size2) { + var rand = baseRandom(index, lastIndex), value = array[rand]; + array[rand] = array[index]; + array[index] = value; + } + array.length = size2; + return array; + } + var stringToPath = memoizeCapped(function(string) { + var result2 = []; + if (string.charCodeAt(0) === 46) { + result2.push(""); + } + string.replace(rePropName, function(match, number, quote, subString) { + result2.push(quote ? subString.replace(reEscapeChar, "$1") : number || match); + }); + return result2; + }); + function toKey(value) { + if (typeof value == "string" || isSymbol(value)) { + return value; + } + var result2 = value + ""; + return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2; + } + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) { + } + try { + return func + ""; + } catch (e) { + } + } + return ""; + } + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = "_." + pair[0]; + if (bitmask & pair[1] && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result2 = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result2.__actions__ = copyArray(wrapper.__actions__); + result2.__index__ = wrapper.__index__; + result2.__values__ = wrapper.__values__; + return result2; + } + function chunk(array, size2, guard) { + if (guard ? isIterateeCall(array, size2, guard) : size2 === undefined$1) { + size2 = 1; + } else { + size2 = nativeMax(toInteger(size2), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size2 < 1) { + return []; + } + var index = 0, resIndex = 0, result2 = Array2(nativeCeil(length / size2)); + while (index < length) { + result2[resIndex++] = baseSlice(array, index, index += size2); + } + return result2; + } + function compact(array) { + var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result2 = []; + while (++index < length) { + var value = array[index]; + if (value) { + result2[resIndex++] = value; + } + } + return result2; + } + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array2(length - 1), array = arguments[0], index = length; + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + var difference = baseRest(function(array, values2) { + return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true)) : []; + }); + var differenceBy = baseRest(function(array, values2) { + var iteratee2 = last(values2); + if (isArrayLikeObject(iteratee2)) { + iteratee2 = undefined$1; + } + return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)) : []; + }); + var differenceWith = baseRest(function(array, values2) { + var comparator = last(values2); + if (isArrayLikeObject(comparator)) { + comparator = undefined$1; + } + return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), undefined$1, comparator) : []; + }); + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = guard || n === undefined$1 ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = guard || n === undefined$1 ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate) { + return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : []; + } + function dropWhile(array, predicate) { + return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined$1) { + index = toInteger(fromIndex); + index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined$1 ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + function fromPairs(pairs) { + var index = -1, length = pairs == null ? 0 : pairs.length, result2 = {}; + while (++index < length) { + var pair = pairs[index]; + result2[pair[0]] = pair[1]; + } + return result2; + } + function head(array) { + return array && array.length ? array[0] : undefined$1; + } + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : []; + }); + var intersectionBy = baseRest(function(arrays) { + var iteratee2 = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); + if (iteratee2 === last(mapped)) { + iteratee2 = undefined$1; + } else { + mapped.pop(); + } + return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee2, 2)) : []; + }); + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); + comparator = typeof comparator == "function" ? comparator : undefined$1; + if (comparator) { + mapped.pop(); + } + return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined$1, comparator) : []; + }); + function join(array, separator) { + return array == null ? "" : nativeJoin.call(array, separator); + } + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined$1; + } + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined$1) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true); + } + function nth(array, n) { + return array && array.length ? baseNth(array, toInteger(n)) : undefined$1; + } + var pull = baseRest(pullAll); + function pullAll(array, values2) { + return array && array.length && values2 && values2.length ? basePullAll(array, values2) : array; + } + function pullAllBy(array, values2, iteratee2) { + return array && array.length && values2 && values2.length ? basePullAll(array, values2, getIteratee(iteratee2, 2)) : array; + } + function pullAllWith(array, values2, comparator) { + return array && array.length && values2 && values2.length ? basePullAll(array, values2, undefined$1, comparator) : array; + } + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, result2 = baseAt(array, indexes); + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + return result2; + }); + function remove(array, predicate) { + var result2 = []; + if (!(array && array.length)) { + return result2; + } + var index = -1, indexes = [], length = array.length; + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result2.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result2; + } + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } else { + start = start == null ? 0 : toInteger(start); + end = end === undefined$1 ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + function sortedIndexBy(array, value, iteratee2) { + return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2)); + } + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + function sortedLastIndexBy(array, value, iteratee2) { + return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2), true); + } + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + function sortedUniq(array) { + return array && array.length ? baseSortedUniq(array) : []; + } + function sortedUniqBy(array, iteratee2) { + return array && array.length ? baseSortedUniq(array, getIteratee(iteratee2, 2)) : []; + } + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = guard || n === undefined$1 ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = guard || n === undefined$1 ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + function takeRightWhile(array, predicate) { + return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : []; + } + function takeWhile(array, predicate) { + return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : []; + } + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + var unionBy = baseRest(function(arrays) { + var iteratee2 = last(arrays); + if (isArrayLikeObject(iteratee2)) { + iteratee2 = undefined$1; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)); + }); + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == "function" ? comparator : undefined$1; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator); + }); + function uniq(array) { + return array && array.length ? baseUniq(array) : []; + } + function uniqBy(array, iteratee2) { + return array && array.length ? baseUniq(array, getIteratee(iteratee2, 2)) : []; + } + function uniqWith(array, comparator) { + comparator = typeof comparator == "function" ? comparator : undefined$1; + return array && array.length ? baseUniq(array, undefined$1, comparator) : []; + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + function unzipWith(array, iteratee2) { + if (!(array && array.length)) { + return []; + } + var result2 = unzip(array); + if (iteratee2 == null) { + return result2; + } + return arrayMap(result2, function(group) { + return apply(iteratee2, undefined$1, group); + }); + } + var without = baseRest(function(array, values2) { + return isArrayLikeObject(array) ? baseDifference(array, values2) : []; + }); + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + var xorBy = baseRest(function(arrays) { + var iteratee2 = last(arrays); + if (isArrayLikeObject(iteratee2)) { + iteratee2 = undefined$1; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee2, 2)); + }); + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == "function" ? comparator : undefined$1; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator); + }); + var zip = baseRest(unzip); + function zipObject(props, values2) { + return baseZipObject(props || [], values2 || [], assignValue); + } + function zipObjectDeep(props, values2) { + return baseZipObject(props || [], values2 || [], baseSet); + } + var zipWith = baseRest(function(arrays) { + var length = arrays.length, iteratee2 = length > 1 ? arrays[length - 1] : undefined$1; + iteratee2 = typeof iteratee2 == "function" ? (arrays.pop(), iteratee2) : undefined$1; + return unzipWith(arrays, iteratee2); + }); + function chain(value) { + var result2 = lodash2(value); + result2.__chain__ = true; + return result2; + } + function tap(value, interceptor) { + interceptor(value); + return value; + } + function thru(value, interceptor) { + return interceptor(value); + } + var wrapperAt = flatRest(function(paths) { + var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) { + return baseAt(object, paths); + }; + if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + func: thru, + args: [interceptor], + thisArg: undefined$1 + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined$1); + } + return array; + }); + }); + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + function wrapperNext() { + if (this.__values__ === undefined$1) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, value = done ? undefined$1 : this.__values__[this.__index__++]; + return {done, value}; + } + function wrapperToIterator() { + return this; + } + function wrapperPlant(value) { + var result2, parent2 = this; + while (parent2 instanceof baseLodash) { + var clone2 = wrapperClone(parent2); + clone2.__index__ = 0; + clone2.__values__ = undefined$1; + if (result2) { + previous.__wrapped__ = clone2; + } else { + result2 = clone2; + } + var previous = clone2; + parent2 = parent2.__wrapped__; + } + previous.__wrapped__ = value; + return result2; + } + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [reverse], + thisArg: undefined$1 + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var countBy = createAggregator(function(result2, value, key) { + if (hasOwnProperty.call(result2, key)) { + ++result2[key]; + } else { + baseAssignValue(result2, key, 1); + } + }); + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined$1; + } + return func(collection, getIteratee(predicate, 3)); + } + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + var find = createFind(findIndex); + var findLast = createFind(findLastIndex); + function flatMap(collection, iteratee2) { + return baseFlatten(map(collection, iteratee2), 1); + } + function flatMapDeep(collection, iteratee2) { + return baseFlatten(map(collection, iteratee2), INFINITY); + } + function flatMapDepth(collection, iteratee2, depth) { + depth = depth === undefined$1 ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee2), depth); + } + function forEach(collection, iteratee2) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee2, 3)); + } + function forEachRight(collection, iteratee2) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee2, 3)); + } + var groupBy = createAggregator(function(result2, value, key) { + if (hasOwnProperty.call(result2, key)) { + result2[key].push(value); + } else { + baseAssignValue(result2, key, [value]); + } + }); + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0; + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1; + } + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : []; + baseEach(collection, function(value) { + result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result2; + }); + var keyBy = createAggregator(function(result2, value, key) { + baseAssignValue(result2, key, value); + }); + function map(collection, iteratee2) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee2, 3)); + } + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined$1 : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + var partition = createAggregator(function(result2, value, key) { + result2[key ? 0 : 1].push(value); + }, function() { + return [[], []]; + }); + function reduce(collection, iteratee2, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3; + return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEach); + } + function reduceRight(collection, iteratee2, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3; + return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEachRight); + } + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + function sampleSize(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n === undefined$1) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined$1; + } + return func(collection, getIteratee(predicate, 3)); + } + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + var now = ctxNow || function() { + return root.Date.now(); + }; + function after(n, func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + n = guard ? undefined$1 : n; + n = func && n == null ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n); + } + function before(n, func) { + var result2; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result2 = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined$1; + } + return result2; + }; + } + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + function curry(func, arity, guard) { + arity = guard ? undefined$1 : arity; + var result2 = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity); + result2.placeholder = curry.placeholder; + return result2; + } + function curryRight(func, arity, guard) { + arity = guard ? undefined$1 : arity; + var result2 = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity); + result2.placeholder = curryRight.placeholder; + return result2; + } + function debounce(func, wait, options) { + var lastArgs, lastThis, maxWait, result2, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = "maxWait" in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function invokeFunc(time) { + var args = lastArgs, thisArg = lastThis; + lastArgs = lastThis = undefined$1; + lastInvokeTime = time; + result2 = func.apply(thisArg, args); + return result2; + } + function leadingEdge(time) { + lastInvokeTime = time; + timerId = setTimeout(timerExpired, wait); + return leading ? invokeFunc(time) : result2; + } + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall; + return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting; + } + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; + return lastCallTime === undefined$1 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait; + } + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + timerId = setTimeout(timerExpired, remainingWait(time)); + } + function trailingEdge(time) { + timerId = undefined$1; + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined$1; + return result2; + } + function cancel() { + if (timerId !== undefined$1) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined$1; + } + function flush() { + return timerId === undefined$1 ? result2 : trailingEdge(now()); + } + function debounced() { + var time = now(), isInvoking = shouldInvoke(time); + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + if (isInvoking) { + if (timerId === undefined$1) { + return leadingEdge(lastCallTime); + } + if (maxing) { + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined$1) { + timerId = setTimeout(timerExpired, wait); + } + return result2; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + function memoize(func, resolver) { + if (typeof func != "function" || resolver != null && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result2 = func.apply(this, args); + memoized.cache = cache.set(key, result2) || cache; + return result2; + }; + memoized.cache = new (memoize.Cache || MapCache)(); + return memoized; + } + memoize.Cache = MapCache; + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: + return !predicate.call(this); + case 1: + return !predicate.call(this, args[0]); + case 2: + return !predicate.call(this, args[0], args[1]); + case 3: + return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + function once(func) { + return before(2, func); + } + var overArgs = castRest(function(func, transforms) { + transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, length = nativeMin(args.length, funcsLength); + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders); + }); + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders); + }); + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes); + }); + function rest(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined$1 ? start : toInteger(start); + return baseRest(func, start); + } + function spread(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], otherArgs = castSlice(args, 0, start); + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading, + maxWait: wait, + trailing + }); + } + function unary(func) { + return ary(func, 1); + } + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + function cloneWith(value, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + function eq(value, other) { + return value === other || value !== value && other !== other; + } + var gt = createRelationalOperation(baseGt); + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + var isArguments = baseIsArguments(function() { + return arguments; + }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + }; + var isArray = Array2.isArray; + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag; + } + var isBuffer = nativeIsBuffer || stubFalse; + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + function isEqual(value, other) { + return baseIsEqual(value, other); + } + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + var result2 = customizer ? customizer(value, other) : undefined$1; + return result2 === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result2; + } + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value); + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + if (!isObject(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + function isInteger(value) { + return typeof value == "number" && value == toInteger(value); + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isObject(value) { + var type2 = typeof value; + return value != null && (type2 == "object" || type2 == "function"); + } + function isObjectLike(value) { + return value != null && typeof value == "object"; + } + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (isMaskable(value)) { + throw new Error2(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + function isNull(value) { + return value === null; + } + function isNil(value) { + return value == null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag; + } + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor; + return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString; + } + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + function isString(value) { + return typeof value == "string" || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag; + } + function isSymbol(value) { + return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag; + } + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + function isUndefined(value) { + return value === undefined$1; + } + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + var lt = createRelationalOperation(baseLt); + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values; + return func(value); + } + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = value < 0 ? -1 : 1; + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + function toInteger(value) { + var result2 = toFinite(value), remainder = result2 % 1; + return result2 === result2 ? remainder ? result2 - remainder : result2 : 0; + } + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + function toNumber(value) { + if (typeof value == "number") { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == "function" ? value.valueOf() : value; + value = isObject(other) ? other + "" : other; + } + if (typeof value != "string") { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ""); + var isBinary = reIsBinary.test(value); + return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; + } + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + function toSafeInteger(value) { + return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0; + } + function toString(value) { + return value == null ? "" : baseToString(value); + } + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + var at = flatRest(baseAt); + function create(prototype, properties) { + var result2 = baseCreate(prototype); + return properties == null ? result2 : baseAssign(result2, properties); + } + var defaults = baseRest(function(object, sources) { + object = Object2(object); + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined$1; + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + if (value === undefined$1 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) { + object[key] = source[key]; + } + } + } + return object; + }); + var defaultsDeep = baseRest(function(args) { + args.push(undefined$1, customDefaultsMerge); + return apply(mergeWith, undefined$1, args); + }); + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + function forIn(object, iteratee2) { + return object == null ? object : baseFor(object, getIteratee(iteratee2, 3), keysIn); + } + function forInRight(object, iteratee2) { + return object == null ? object : baseForRight(object, getIteratee(iteratee2, 3), keysIn); + } + function forOwn(object, iteratee2) { + return object && baseForOwn(object, getIteratee(iteratee2, 3)); + } + function forOwnRight(object, iteratee2) { + return object && baseForOwnRight(object, getIteratee(iteratee2, 3)); + } + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result2 = object == null ? undefined$1 : baseGet(object, path); + return result2 === undefined$1 ? defaultValue : result2; + } + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + var invert = createInverter(function(result2, value, key) { + if (value != null && typeof value.toString != "function") { + value = nativeObjectToString.call(value); + } + result2[value] = key; + }, constant(identity)); + var invertBy = createInverter(function(result2, value, key) { + if (value != null && typeof value.toString != "function") { + value = nativeObjectToString.call(value); + } + if (hasOwnProperty.call(result2, value)) { + result2[value].push(key); + } else { + result2[value] = [key]; + } + }, getIteratee); + var invoke = baseRest(baseInvoke); + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + function mapKeys(object, iteratee2) { + var result2 = {}; + iteratee2 = getIteratee(iteratee2, 3); + baseForOwn(object, function(value, key, object2) { + baseAssignValue(result2, iteratee2(value, key, object2), value); + }); + return result2; + } + function mapValues(object, iteratee2) { + var result2 = {}; + iteratee2 = getIteratee(iteratee2, 3); + baseForOwn(object, function(value, key, object2) { + baseAssignValue(result2, key, iteratee2(value, key, object2)); + }); + return result2; + } + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + var omit = flatRest(function(object, paths) { + var result2 = {}; + if (object == null) { + return result2; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result2); + if (isDeep) { + result2 = baseClone(result2, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result2, paths[length]); + } + return result2; + }); + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + function result(object, path, defaultValue) { + path = castPath(path, object); + var index = -1, length = path.length; + if (!length) { + length = 1; + object = undefined$1; + } + while (++index < length) { + var value = object == null ? undefined$1 : object[toKey(path[index])]; + if (value === undefined$1) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + function setWith(object, path, value, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + return object == null ? object : baseSet(object, path, value, customizer); + } + var toPairs = createToPairs(keys); + var toPairsIn = createToPairs(keysIn); + function transform(object, iteratee2, accumulator) { + var isArr = isArray(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object); + iteratee2 = getIteratee(iteratee2, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor() : []; + } else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object2) { + return iteratee2(accumulator, value, index, object2); + }); + return accumulator; + } + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == "function" ? customizer : undefined$1; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + function clamp(number, lower, upper) { + if (upper === undefined$1) { + upper = lower; + lower = undefined$1; + } + if (upper !== undefined$1) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined$1) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined$1) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + function random(lower, upper, floating) { + if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined$1; + } + if (floating === undefined$1) { + if (typeof upper == "boolean") { + floating = upper; + upper = undefined$1; + } else if (typeof lower == "boolean") { + floating = lower; + lower = undefined$1; + } + } + if (lower === undefined$1 && upper === undefined$1) { + lower = 0; + upper = 1; + } else { + lower = toFinite(lower); + if (upper === undefined$1) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper); + } + return baseRandom(lower, upper); + } + var camelCase = createCompounder(function(result2, word, index) { + word = word.toLowerCase(); + return result2 + (index ? capitalize(word) : word); + }); + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + var length = string.length; + position = position === undefined$1 ? length : baseClamp(toInteger(position), 0, length); + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + function escape(string) { + string = toString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = toString(string); + return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string; + } + var kebabCase = createCompounder(function(result2, word, index) { + return result2 + (index ? "-" : "") + word.toLowerCase(); + }); + var lowerCase = createCompounder(function(result2, word, index) { + return result2 + (index ? " " : "") + word.toLowerCase(); + }); + var lowerFirst = createCaseFirst("toLowerCase"); + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars); + } + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + var strLength = length ? stringSize(string) : 0; + return length && strLength < length ? string + createPadding(length - strLength, chars) : string; + } + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + var strLength = length ? stringSize(string) : 0; + return length && strLength < length ? createPadding(length - strLength, chars) + string : string; + } + function parseInt2(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ""), radix || 0); + } + function repeat(string, n, guard) { + if (guard ? isIterateeCall(string, n, guard) : n === undefined$1) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + function replace() { + var args = arguments, string = toString(args[0]); + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + var snakeCase = createCompounder(function(result2, word, index) { + return result2 + (index ? "_" : "") + word.toLowerCase(); + }); + function split(string, separator, limit) { + if (limit && typeof limit != "number" && isIterateeCall(string, separator, limit)) { + separator = limit = undefined$1; + } + limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && (typeof separator == "string" || separator != null && !isRegExp(separator))) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + var startCase = createCompounder(function(result2, word, index) { + return result2 + (index ? " " : "") + upperFirst(word); + }); + function startsWith(string, target, position) { + string = toString(string); + position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length); + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + function template(string, options, guard) { + var settings = lodash2.templateSettings; + if (guard && isIterateeCall(string, options, guard)) { + options = undefined$1; + } + string = toString(string); + options = assignInWith({}, options, settings, customDefaultsAssignIn); + var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp2((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + (hasOwnProperty.call(options, "sourceURL") ? (options.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = hasOwnProperty.call(options, "variable") && options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result2 = attempt(function() { + return Function2(importsKeys, sourceURL + "return " + source).apply(undefined$1, importsValues); + }); + result2.source = source; + if (isError(result2)) { + throw result2; + } + return result2; + } + function toLower(value) { + return toString(value).toLowerCase(); + } + function toUpper(value) { + return toString(value).toUpperCase(); + } + function trim(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined$1)) { + return string.replace(reTrim, ""); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), chrSymbols = stringToArray(chars), start = charsStartIndex(strSymbols, chrSymbols), end = charsEndIndex(strSymbols, chrSymbols) + 1; + return castSlice(strSymbols, start, end).join(""); + } + function trimEnd(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined$1)) { + return string.replace(reTrimEnd, ""); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), end = charsEndIndex(strSymbols, stringToArray(chars)) + 1; + return castSlice(strSymbols, 0, end).join(""); + } + function trimStart(string, chars, guard) { + string = toString(string); + if (string && (guard || chars === undefined$1)) { + return string.replace(reTrimStart, ""); + } + if (!string || !(chars = baseToString(chars))) { + return string; + } + var strSymbols = stringToArray(string), start = charsStartIndex(strSymbols, stringToArray(chars)); + return castSlice(strSymbols, start).join(""); + } + function truncate(string, options) { + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? toInteger(options.length) : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } + string = toString(string); + var strLength = string.length; + if (hasUnicode(string)) { + var strSymbols = stringToArray(string); + strLength = strSymbols.length; + } + if (length >= strLength) { + return string; + } + var end = length - stringSize(omission); + if (end < 1) { + return omission; + } + var result2 = strSymbols ? castSlice(strSymbols, 0, end).join("") : string.slice(0, end); + if (separator === undefined$1) { + return result2 + omission; + } + if (strSymbols) { + end += result2.length - end; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, substring = result2; + if (!separator.global) { + separator = RegExp2(separator.source, toString(reFlags.exec(separator)) + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + var newEnd = match.index; + } + result2 = result2.slice(0, newEnd === undefined$1 ? end : newEnd); + } + } else if (string.indexOf(baseToString(separator), end) != end) { + var index = result2.lastIndexOf(separator); + if (index > -1) { + result2 = result2.slice(0, index); + } + } + return result2 + omission; + } + function unescape(string) { + string = toString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + var upperCase = createCompounder(function(result2, word, index) { + return result2 + (index ? " " : "") + word.toUpperCase(); + }); + var upperFirst = createCaseFirst("toUpperCase"); + function words(string, pattern, guard) { + string = toString(string); + pattern = guard ? undefined$1 : pattern; + if (pattern === undefined$1) { + return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); + } + return string.match(pattern) || []; + } + var attempt = baseRest(function(func, args) { + try { + return apply(func, undefined$1, args); + } catch (e) { + return isError(e) ? e : new Error2(e); + } + }); + var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { + key = toKey(key); + baseAssignValue(object, key, bind(object[key], object)); + }); + return object; + }); + function cond(pairs) { + var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee(); + pairs = !length ? [] : arrayMap(pairs, function(pair) { + if (typeof pair[1] != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return [toIteratee(pair[0]), pair[1]]; + }); + return baseRest(function(args) { + var index = -1; + while (++index < length) { + var pair = pairs[index]; + if (apply(pair[0], this, args)) { + return apply(pair[1], this, args); + } + } + }); + } + function conforms(source) { + return baseConforms(baseClone(source, CLONE_DEEP_FLAG)); + } + function constant(value) { + return function() { + return value; + }; + } + function defaultTo(value, defaultValue) { + return value == null || value !== value ? defaultValue : value; + } + var flow = createFlow(); + var flowRight = createFlow(true); + function identity(value) { + return value; + } + function iteratee(func) { + return baseIteratee(typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG)); + } + function matches(source) { + return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); + } + var method = baseRest(function(path, args) { + return function(object) { + return baseInvoke(object, path, args); + }; + }); + var methodOf = baseRest(function(object, args) { + return function(path) { + return baseInvoke(object, path, args); + }; + }); + function mixin(object, source, options) { + var props = keys(source), methodNames = baseFunctions(source, props); + if (options == null && !(isObject(source) && (methodNames.length || !props.length))) { + options = source; + source = object; + object = this; + methodNames = baseFunctions(source, keys(source)); + } + var chain2 = !(isObject(options) && "chain" in options) || !!options.chain, isFunc = isFunction(object); + arrayEach(methodNames, function(methodName) { + var func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function() { + var chainAll = this.__chain__; + if (chain2 || chainAll) { + var result2 = object(this.__wrapped__), actions = result2.__actions__ = copyArray(this.__actions__); + actions.push({func, args: arguments, thisArg: object}); + result2.__chain__ = chainAll; + return result2; + } + return func.apply(object, arrayPush([this.value()], arguments)); + }; + } + }); + return object; + } + function noConflict() { + if (root._ === this) { + root._ = oldDash; + } + return this; + } + function noop() { + } + function nthArg(n) { + n = toInteger(n); + return baseRest(function(args) { + return baseNth(args, n); + }); + } + var over = createOver(arrayMap); + var overEvery = createOver(arrayEvery); + var overSome = createOver(arraySome); + function property(path) { + return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return object == null ? undefined$1 : baseGet(object, path); + }; + } + var range = createRange(); + var rangeRight = createRange(true); + function stubArray() { + return []; + } + function stubFalse() { + return false; + } + function stubObject() { + return {}; + } + function stubString() { + return ""; + } + function stubTrue() { + return true; + } + function times(n, iteratee2) { + n = toInteger(n); + if (n < 1 || n > MAX_SAFE_INTEGER) { + return []; + } + var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH); + iteratee2 = getIteratee(iteratee2); + n -= MAX_ARRAY_LENGTH; + var result2 = baseTimes(length, iteratee2); + while (++index < n) { + iteratee2(index); + } + return result2; + } + function toPath(value) { + if (isArray(value)) { + return arrayMap(value, toKey); + } + return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value))); + } + function uniqueId(prefix) { + var id = ++idCounter; + return toString(prefix) + id; + } + var add = createMathOperation(function(augend, addend) { + return augend + addend; + }, 0); + var ceil = createRound("ceil"); + var divide = createMathOperation(function(dividend, divisor) { + return dividend / divisor; + }, 1); + var floor = createRound("floor"); + function max(array) { + return array && array.length ? baseExtremum(array, identity, baseGt) : undefined$1; + } + function maxBy(array, iteratee2) { + return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseGt) : undefined$1; + } + function mean(array) { + return baseMean(array, identity); + } + function meanBy(array, iteratee2) { + return baseMean(array, getIteratee(iteratee2, 2)); + } + function min(array) { + return array && array.length ? baseExtremum(array, identity, baseLt) : undefined$1; + } + function minBy(array, iteratee2) { + return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseLt) : undefined$1; + } + var multiply = createMathOperation(function(multiplier, multiplicand) { + return multiplier * multiplicand; + }, 1); + var round = createRound("round"); + var subtract = createMathOperation(function(minuend, subtrahend) { + return minuend - subtrahend; + }, 0); + function sum(array) { + return array && array.length ? baseSum(array, identity) : 0; + } + function sumBy(array, iteratee2) { + return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0; + } + lodash2.after = after; + lodash2.ary = ary; + lodash2.assign = assign; + lodash2.assignIn = assignIn; + lodash2.assignInWith = assignInWith; + lodash2.assignWith = assignWith; + lodash2.at = at; + lodash2.before = before; + lodash2.bind = bind; + lodash2.bindAll = bindAll; + lodash2.bindKey = bindKey; + lodash2.castArray = castArray; + lodash2.chain = chain; + lodash2.chunk = chunk; + lodash2.compact = compact; + lodash2.concat = concat; + lodash2.cond = cond; + lodash2.conforms = conforms; + lodash2.constant = constant; + lodash2.countBy = countBy; + lodash2.create = create; + lodash2.curry = curry; + lodash2.curryRight = curryRight; + lodash2.debounce = debounce; + lodash2.defaults = defaults; + lodash2.defaultsDeep = defaultsDeep; + lodash2.defer = defer; + lodash2.delay = delay; + lodash2.difference = difference; + lodash2.differenceBy = differenceBy; + lodash2.differenceWith = differenceWith; + lodash2.drop = drop; + lodash2.dropRight = dropRight; + lodash2.dropRightWhile = dropRightWhile; + lodash2.dropWhile = dropWhile; + lodash2.fill = fill; + lodash2.filter = filter; + lodash2.flatMap = flatMap; + lodash2.flatMapDeep = flatMapDeep; + lodash2.flatMapDepth = flatMapDepth; + lodash2.flatten = flatten; + lodash2.flattenDeep = flattenDeep; + lodash2.flattenDepth = flattenDepth; + lodash2.flip = flip; + lodash2.flow = flow; + lodash2.flowRight = flowRight; + lodash2.fromPairs = fromPairs; + lodash2.functions = functions; + lodash2.functionsIn = functionsIn; + lodash2.groupBy = groupBy; + lodash2.initial = initial; + lodash2.intersection = intersection; + lodash2.intersectionBy = intersectionBy; + lodash2.intersectionWith = intersectionWith; + lodash2.invert = invert; + lodash2.invertBy = invertBy; + lodash2.invokeMap = invokeMap; + lodash2.iteratee = iteratee; + lodash2.keyBy = keyBy; + lodash2.keys = keys; + lodash2.keysIn = keysIn; + lodash2.map = map; + lodash2.mapKeys = mapKeys; + lodash2.mapValues = mapValues; + lodash2.matches = matches; + lodash2.matchesProperty = matchesProperty; + lodash2.memoize = memoize; + lodash2.merge = merge; + lodash2.mergeWith = mergeWith; + lodash2.method = method; + lodash2.methodOf = methodOf; + lodash2.mixin = mixin; + lodash2.negate = negate; + lodash2.nthArg = nthArg; + lodash2.omit = omit; + lodash2.omitBy = omitBy; + lodash2.once = once; + lodash2.orderBy = orderBy; + lodash2.over = over; + lodash2.overArgs = overArgs; + lodash2.overEvery = overEvery; + lodash2.overSome = overSome; + lodash2.partial = partial; + lodash2.partialRight = partialRight; + lodash2.partition = partition; + lodash2.pick = pick; + lodash2.pickBy = pickBy; + lodash2.property = property; + lodash2.propertyOf = propertyOf; + lodash2.pull = pull; + lodash2.pullAll = pullAll; + lodash2.pullAllBy = pullAllBy; + lodash2.pullAllWith = pullAllWith; + lodash2.pullAt = pullAt; + lodash2.range = range; + lodash2.rangeRight = rangeRight; + lodash2.rearg = rearg; + lodash2.reject = reject; + lodash2.remove = remove; + lodash2.rest = rest; + lodash2.reverse = reverse; + lodash2.sampleSize = sampleSize; + lodash2.set = set; + lodash2.setWith = setWith; + lodash2.shuffle = shuffle; + lodash2.slice = slice; + lodash2.sortBy = sortBy; + lodash2.sortedUniq = sortedUniq; + lodash2.sortedUniqBy = sortedUniqBy; + lodash2.split = split; + lodash2.spread = spread; + lodash2.tail = tail; + lodash2.take = take; + lodash2.takeRight = takeRight; + lodash2.takeRightWhile = takeRightWhile; + lodash2.takeWhile = takeWhile; + lodash2.tap = tap; + lodash2.throttle = throttle; + lodash2.thru = thru; + lodash2.toArray = toArray; + lodash2.toPairs = toPairs; + lodash2.toPairsIn = toPairsIn; + lodash2.toPath = toPath; + lodash2.toPlainObject = toPlainObject; + lodash2.transform = transform; + lodash2.unary = unary; + lodash2.union = union; + lodash2.unionBy = unionBy; + lodash2.unionWith = unionWith; + lodash2.uniq = uniq; + lodash2.uniqBy = uniqBy; + lodash2.uniqWith = uniqWith; + lodash2.unset = unset; + lodash2.unzip = unzip; + lodash2.unzipWith = unzipWith; + lodash2.update = update; + lodash2.updateWith = updateWith; + lodash2.values = values; + lodash2.valuesIn = valuesIn; + lodash2.without = without; + lodash2.words = words; + lodash2.wrap = wrap; + lodash2.xor = xor; + lodash2.xorBy = xorBy; + lodash2.xorWith = xorWith; + lodash2.zip = zip; + lodash2.zipObject = zipObject; + lodash2.zipObjectDeep = zipObjectDeep; + lodash2.zipWith = zipWith; + lodash2.entries = toPairs; + lodash2.entriesIn = toPairsIn; + lodash2.extend = assignIn; + lodash2.extendWith = assignInWith; + mixin(lodash2, lodash2); + lodash2.add = add; + lodash2.attempt = attempt; + lodash2.camelCase = camelCase; + lodash2.capitalize = capitalize; + lodash2.ceil = ceil; + lodash2.clamp = clamp; + lodash2.clone = clone; + lodash2.cloneDeep = cloneDeep; + lodash2.cloneDeepWith = cloneDeepWith; + lodash2.cloneWith = cloneWith; + lodash2.conformsTo = conformsTo; + lodash2.deburr = deburr; + lodash2.defaultTo = defaultTo; + lodash2.divide = divide; + lodash2.endsWith = endsWith; + lodash2.eq = eq; + lodash2.escape = escape; + lodash2.escapeRegExp = escapeRegExp; + lodash2.every = every; + lodash2.find = find; + lodash2.findIndex = findIndex; + lodash2.findKey = findKey; + lodash2.findLast = findLast; + lodash2.findLastIndex = findLastIndex; + lodash2.findLastKey = findLastKey; + lodash2.floor = floor; + lodash2.forEach = forEach; + lodash2.forEachRight = forEachRight; + lodash2.forIn = forIn; + lodash2.forInRight = forInRight; + lodash2.forOwn = forOwn; + lodash2.forOwnRight = forOwnRight; + lodash2.get = get; + lodash2.gt = gt; + lodash2.gte = gte; + lodash2.has = has; + lodash2.hasIn = hasIn; + lodash2.head = head; + lodash2.identity = identity; + lodash2.includes = includes; + lodash2.indexOf = indexOf; + lodash2.inRange = inRange; + lodash2.invoke = invoke; + lodash2.isArguments = isArguments; + lodash2.isArray = isArray; + lodash2.isArrayBuffer = isArrayBuffer; + lodash2.isArrayLike = isArrayLike; + lodash2.isArrayLikeObject = isArrayLikeObject; + lodash2.isBoolean = isBoolean; + lodash2.isBuffer = isBuffer; + lodash2.isDate = isDate; + lodash2.isElement = isElement; + lodash2.isEmpty = isEmpty; + lodash2.isEqual = isEqual; + lodash2.isEqualWith = isEqualWith; + lodash2.isError = isError; + lodash2.isFinite = isFinite; + lodash2.isFunction = isFunction; + lodash2.isInteger = isInteger; + lodash2.isLength = isLength; + lodash2.isMap = isMap; + lodash2.isMatch = isMatch; + lodash2.isMatchWith = isMatchWith; + lodash2.isNaN = isNaN; + lodash2.isNative = isNative; + lodash2.isNil = isNil; + lodash2.isNull = isNull; + lodash2.isNumber = isNumber; + lodash2.isObject = isObject; + lodash2.isObjectLike = isObjectLike; + lodash2.isPlainObject = isPlainObject; + lodash2.isRegExp = isRegExp; + lodash2.isSafeInteger = isSafeInteger; + lodash2.isSet = isSet; + lodash2.isString = isString; + lodash2.isSymbol = isSymbol; + lodash2.isTypedArray = isTypedArray; + lodash2.isUndefined = isUndefined; + lodash2.isWeakMap = isWeakMap; + lodash2.isWeakSet = isWeakSet; + lodash2.join = join; + lodash2.kebabCase = kebabCase; + lodash2.last = last; + lodash2.lastIndexOf = lastIndexOf; + lodash2.lowerCase = lowerCase; + lodash2.lowerFirst = lowerFirst; + lodash2.lt = lt; + lodash2.lte = lte; + lodash2.max = max; + lodash2.maxBy = maxBy; + lodash2.mean = mean; + lodash2.meanBy = meanBy; + lodash2.min = min; + lodash2.minBy = minBy; + lodash2.stubArray = stubArray; + lodash2.stubFalse = stubFalse; + lodash2.stubObject = stubObject; + lodash2.stubString = stubString; + lodash2.stubTrue = stubTrue; + lodash2.multiply = multiply; + lodash2.nth = nth; + lodash2.noConflict = noConflict; + lodash2.noop = noop; + lodash2.now = now; + lodash2.pad = pad; + lodash2.padEnd = padEnd; + lodash2.padStart = padStart; + lodash2.parseInt = parseInt2; + lodash2.random = random; + lodash2.reduce = reduce; + lodash2.reduceRight = reduceRight; + lodash2.repeat = repeat; + lodash2.replace = replace; + lodash2.result = result; + lodash2.round = round; + lodash2.runInContext = runInContext2; + lodash2.sample = sample; + lodash2.size = size; + lodash2.snakeCase = snakeCase; + lodash2.some = some; + lodash2.sortedIndex = sortedIndex; + lodash2.sortedIndexBy = sortedIndexBy; + lodash2.sortedIndexOf = sortedIndexOf; + lodash2.sortedLastIndex = sortedLastIndex; + lodash2.sortedLastIndexBy = sortedLastIndexBy; + lodash2.sortedLastIndexOf = sortedLastIndexOf; + lodash2.startCase = startCase; + lodash2.startsWith = startsWith; + lodash2.subtract = subtract; + lodash2.sum = sum; + lodash2.sumBy = sumBy; + lodash2.template = template; + lodash2.times = times; + lodash2.toFinite = toFinite; + lodash2.toInteger = toInteger; + lodash2.toLength = toLength; + lodash2.toLower = toLower; + lodash2.toNumber = toNumber; + lodash2.toSafeInteger = toSafeInteger; + lodash2.toString = toString; + lodash2.toUpper = toUpper; + lodash2.trim = trim; + lodash2.trimEnd = trimEnd; + lodash2.trimStart = trimStart; + lodash2.truncate = truncate; + lodash2.unescape = unescape; + lodash2.uniqueId = uniqueId; + lodash2.upperCase = upperCase; + lodash2.upperFirst = upperFirst; + lodash2.each = forEach; + lodash2.eachRight = forEachRight; + lodash2.first = head; + mixin(lodash2, function() { + var source = {}; + baseForOwn(lodash2, function(func, methodName) { + if (!hasOwnProperty.call(lodash2.prototype, methodName)) { + source[methodName] = func; + } + }); + return source; + }(), {chain: false}); + lodash2.VERSION = VERSION; + arrayEach(["bind", "bindKey", "curry", "curryRight", "partial", "partialRight"], function(methodName) { + lodash2[methodName].placeholder = lodash2; + }); + arrayEach(["drop", "take"], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0); + var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone(); + if (result2.__filtered__) { + result2.__takeCount__ = nativeMin(n, result2.__takeCount__); + } else { + result2.__views__.push({ + size: nativeMin(n, MAX_ARRAY_LENGTH), + type: methodName + (result2.__dir__ < 0 ? "Right" : "") + }); + } + return result2; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach(["filter", "map", "takeWhile"], function(methodName, index) { + var type2 = index + 1, isFilter = type2 == LAZY_FILTER_FLAG || type2 == LAZY_WHILE_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee2) { + var result2 = this.clone(); + result2.__iteratees__.push({ + iteratee: getIteratee(iteratee2, 3), + type: type2 + }); + result2.__filtered__ = result2.__filtered__ || isFilter; + return result2; + }; + }); + arrayEach(["head", "last"], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach(["initial", "tail"], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.find = function(predicate) { + return this.filter(predicate).head(); + }; + LazyWrapper.prototype.findLast = function(predicate) { + return this.reverse().find(predicate); + }; + LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { + if (typeof path == "function") { + return new LazyWrapper(this); + } + return this.map(function(value) { + return baseInvoke(value, path, args); + }); + }); + LazyWrapper.prototype.reject = function(predicate) { + return this.filter(negate(getIteratee(predicate))); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = toInteger(start); + var result2 = this; + if (result2.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result2); + } + if (start < 0) { + result2 = result2.takeRight(-start); + } else if (start) { + result2 = result2.drop(start); + } + if (end !== undefined$1) { + end = toInteger(end); + result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start); + } + return result2; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate) { + return this.reverse().takeWhile(predicate).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(MAX_ARRAY_LENGTH); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash2[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName); + if (!lodashFunc) { + return; + } + lodash2.prototype[methodName] = function() { + var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray(value); + var interceptor = function(value2) { + var result3 = lodashFunc.apply(lodash2, arrayPush([value2], args)); + return isTaker && chainAll ? result3[0] : result3; + }; + if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) { + isLazy = useLazy = false; + } + var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid; + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result2 = func.apply(value, args); + result2.__actions__.push({func: thru, args: [interceptor], thisArg: undefined$1}); + return new LodashWrapper(result2, chainAll); + } + if (isUnwrapped && onlyLazy) { + return func.apply(this, args); + } + result2 = this.thru(interceptor); + return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2; + }; + }); + arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) { + var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName); + lodash2.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + var value = this.value(); + return func.apply(isArray(value) ? value : [], args); + } + return this[chainName](function(value2) { + return func.apply(isArray(value2) ? value2 : [], args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash2[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + ""; + if (!hasOwnProperty.call(realNames, key)) { + realNames[key] = []; + } + realNames[key].push({name: methodName, func: lodashFunc}); + } + }); + realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{ + name: "wrapper", + func: undefined$1 + }]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash2.prototype.at = wrapperAt; + lodash2.prototype.chain = wrapperChain; + lodash2.prototype.commit = wrapperCommit; + lodash2.prototype.next = wrapperNext; + lodash2.prototype.plant = wrapperPlant; + lodash2.prototype.reverse = wrapperReverse; + lodash2.prototype.toJSON = lodash2.prototype.valueOf = lodash2.prototype.value = wrapperValue; + lodash2.prototype.first = lodash2.prototype.head; + if (symIterator) { + lodash2.prototype[symIterator] = wrapperToIterator; + } + return lodash2; + }; + var _ = runInContext(); + if (freeModule) { + (freeModule.exports = _)._ = _; + freeExports._ = _; + } else { + root._ = _; + } + }).call(commonjsGlobal); +}); +class InputStream { + constructor(input) { + this.input = input; + this.cursor = 0; + this.line = 1; + this.column = 0; + } + position() { + return Object.freeze({ + cursor: this.cursor, + line: this.line, + column: this.column + }); + } + peek(offset) { + const cursor = lodash.isInteger(offset) ? this.cursor + offset : this.cursor; + return this.input.charAt(cursor); + } + next() { + const c = this.input.charAt(this.cursor++); + if (c === "\n") { + this.line++; + this.column = 0; + } else { + this.column++; + } + return c; + } + eof() { + return this.peek() === ""; + } + err(msg) { + throw new Error(`${msg} (${this.line}:${this.column})`); + } +} +var inputStream = (input) => { + const i = new InputStream(input); + const InputStreamProxy = { + position() { + return i.position(); + }, + peek() { + return i.peek(...arguments); + }, + next() { + return i.next(); + }, + eof() { + return i.eof(); + }, + err() { + return i.err(...arguments); + } + }; + return InputStreamProxy; +}; +const HEX_PATTERN = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; +const not = (p) => (c) => !p(c); +const is_char = (c) => (cc) => c === cc; +const is_whitespace = (c) => " \r\n ".indexOf(c) >= 0; +const is_newline = (c) => c === "\n"; +const is_operator = (c) => "+-*/%=&|!~><^".indexOf(c) >= 0; +const is_operator_repeatable = (c) => "&|=".indexOf(c) >= 0; +const is_punctuation = (c) => ",;(){}[]:#.".indexOf(c) >= 0; +const is_digit = (c) => /[0-9]/i.test(c); +const is_comment_start = (input) => input.peek() === "/" && (input.peek(1) === "/" || input.peek(1) === "*"); +const is_ident_start = (c) => /[a-z_]/i.test(c); +const is_ident = (c) => /[a-z0-9_-]/i.test(c); +const is_number_start = (input) => is_digit(input.peek()) || input.peek() === "." && is_digit(input.peek(1)); +const is_hex = (input) => { + let hex = input.peek(); + if (hex === "#") { + let _3 = false; + let _6 = false; + while (hex.length < 7) { + const c = input.peek(hex.length); + if (lodash.isEmpty(c)) + break; + hex += c; + if (hex.length === 4) + _3 = HEX_PATTERN.test(hex); + if (hex.length === 7) + _6 = HEX_PATTERN.test(hex); + } + return _6 ? 6 : _3 ? 3 : false; + } + return false; +}; +class TokenStream { + constructor(input) { + invariant2(lodash.isPlainObject(input) && lodash.has(input, "next"), "TokenStream requires an InputStream"); + this.input = input; + this.tokens = []; + } + createToken(type2, value, start) { + return Object.freeze({ + type: type2, + value, + start, + next: this.input.position() + }); + } + peek(offset) { + if (!this.tokens.length) { + const token = this.read_next(); + if (token) + this.tokens.push(token); + } + if (!offset) + return this.tokens[0]; + if (offset < this.tokens.length) + return this.tokens[offset]; + while (this.tokens.length <= offset) { + const token = this.read_next(); + if (token) + this.tokens.push(token); + else + break; + } + return this.tokens[offset]; + } + next() { + const token = this.tokens.shift(); + return token || this.read_next(); + } + eof() { + return typeof this.peek() === "undefined"; + } + err() { + return this.input.err(...arguments); + } + read_next() { + if (this.input.eof()) + return null; + const c = this.input.peek(); + if (is_whitespace(c)) { + return this.read_whitespace(); + } + if (is_comment_start(this.input)) { + return this.read_comment(); + } + if (is_number_start(this.input)) { + return this.read_number(); + } + const hex_length = is_hex(this.input); + if (hex_length) { + return this.read_hex(hex_length); + } + if (is_punctuation(c)) { + return this.read_punctuation(); + } + if (is_ident_start(c)) { + return this.read_ident(); + } + if (is_operator(c)) { + return this.read_operator(); + } + if (c === '"' || c === "'") { + return this.read_string(c); + } + if (c === "@") { + return this.read_atkeyword(); + } + if (c === "$") { + return this.read_variable(); + } + this.err(`Can't handle character: "${c}"`); + } + read_while(predicate) { + let s = ""; + while (!this.input.eof() && predicate(this.input.peek())) { + s += this.input.next(); + } + return s; + } + read_escaped(end) { + let escaped = false; + let str = ""; + this.input.next(); + while (!this.input.eof()) { + const c = this.input.next(); + if (escaped) { + str += c; + escaped = false; + } else if (c === "\\") { + str += c; + escaped = true; + } else if (c === end) { + break; + } else { + str += c; + } + } + return str; + } + read_whitespace() { + const start = this.input.position(); + const value = this.read_while(is_whitespace); + return this.createToken("space", value, start); + } + read_comment() { + const start = this.input.position(); + this.input.next(); + switch (this.input.next()) { + case "/": + return this.read_comment_single(start); + case "*": + return this.read_comment_multi(start); + } + } + read_comment_single(start) { + const value = this.read_while(not(is_newline)); + return this.createToken("comment_singleline", value, start); + } + read_comment_multi(start) { + let prev = ""; + let value = ""; + while (!this.input.eof()) { + const next = this.input.next(); + if (next === "/" && prev === "*") + break; + value += prev; + prev = next; + } + return this.createToken("comment_multiline", value, start); + } + read_punctuation() { + const start = this.input.position(); + const value = this.input.next(); + return this.createToken("punctuation", value, start); + } + read_operator() { + const start = this.input.position(); + const c = this.input.peek(); + const value = is_operator_repeatable(c) ? this.read_while(is_char(c)) : this.input.next(); + return this.createToken("operator", value, start); + } + read_ident() { + const start = this.input.position(); + const value = this.read_while(is_ident); + return this.createToken("identifier", value, start); + } + read_string(c) { + const start = this.input.position(); + const value = this.read_escaped(c); + let type2 = "string"; + if (c === '"') + type2 = "string_double"; + if (c === "'") + type2 = "string_single"; + return this.createToken(type2, value, start); + } + read_number() { + const start = this.input.position(); + let hasPoint = false; + const value = this.read_while((c) => { + if (c === ".") { + if (hasPoint) + return false; + hasPoint = true; + return true; + } + return is_digit(c); + }); + return this.createToken("number", value, start); + } + read_hex(length) { + const start = this.input.position(); + this.input.next(); + let value = ""; + for (let i = 0; i < length; i++) { + value += this.input.next(); + } + return this.createToken("color_hex", value, start); + } + read_atkeyword() { + const start = this.input.position(); + this.input.next(); + const value = this.read_while(is_ident); + return this.createToken("atkeyword", value, start); + } + read_variable() { + const start = this.input.position(); + this.input.next(); + const value = this.read_while(is_ident); + return this.createToken("variable", value, start); + } +} +var tokenStream = (input) => { + const t = new TokenStream(input); + const TokenStreamProxy = { + peek() { + return t.peek(...arguments); + }, + next() { + return t.next(); + }, + eof() { + return t.eof(); + }, + err() { + return t.err(...arguments); + }, + all() { + const tokens = []; + while (!t.eof()) + tokens.push(t.next()); + return tokens; + } + }; + return TokenStreamProxy; +}; +class Parser { + constructor(tokens) { + this.tokens = tokens; + } + createNode(type2, value, start, next) { + return {type: type2, value, start, next}; + } + is_type(type2, ...values) { + const t = this.tokens.peek(); + if (!values.length) + return t ? type2.test(t.type) : false; + return values.reduce((a, c, i) => { + const t2 = this.tokens.peek(i); + return !t2 ? false : a && type2.test(t2.type) && t2.value === c; + }, true); + } + is_space() { + return this.is_type(/space/); + } + is_comment() { + return this.is_type(/comment/); + } + is_punctuation() { + return this.is_type(/punctuation/, ...arguments); + } + is_operator() { + return this.is_type(/operator/, ...arguments); + } + is_identifier() { + return this.is_type(/identifier/, ...arguments); + } + is_atkeyword() { + return this.is_type(/atkeyword/, ...arguments); + } + is_interpolation() { + return this.is_punctuation("#", "{"); + } + skip_type(type2, isType, ...chars) { + if (isType.apply(this, chars)) { + return {start: this.tokens.peek(), next: this.tokens.next()}; + } else { + this.tokens.err(`Expecting ${type2}: "${chars.join("")}"`); + } + } + skip_punctuation() { + return this.skip_type("punctuation", this.is_punctuation, ...arguments); + } + skip_operator() { + return this.skip_type("operator", this.is_operator, ...arguments); + } + skip_atkeyword() { + return this.skip_type("atkeyword", this.is_atkeyword); + } + unexpected() { + this.tokens.err(`Unexpected token: "${JSON.stringify(this.input.peek())}"`); + } + parse_stylesheet() { + const value = []; + while (!this.tokens.eof()) { + const node = this.parse_node(); + if (lodash.isArray(node)) { + value.push(...node); + } else { + value.push(node); + } + } + return this.createNode("stylesheet", value); + } + parse_node() { + if (this.is_space() || this.is_comment()) + return this.tokens.next(); + const value = []; + const maybe_declaration = (punctuation) => { + let expandedPseudo = false; + if (punctuation === ";") { + const pseudoIndex = lodash.findIndex(value, { + type: "pseudo_class" + }); + if (pseudoIndex > 0) { + const a = value[pseudoIndex]; + const b = this.createNode("punctuation", ":", a.start, lodash.first(a.value).start); + const nodes = [b].concat(a.value); + value.splice(pseudoIndex, 1, ...nodes); + expandedPseudo = true; + } + } + const puncIndex = lodash.findIndex(value, { + type: "punctuation", + value: ":" + }); + if (puncIndex >= 0) { + const maybeSpace = value[puncIndex + 1]; + if (maybeSpace.type === "space" || expandedPseudo) { + const start = lodash.first(value).start; + let next = lodash.last(value).next; + const property_ = lodash.take(value, puncIndex); + const propertyNode = this.createNode("property", property_, lodash.first(property_).start, lodash.last(property_).next); + const value_ = lodash.drop(value, puncIndex + 1); + if (punctuation === "{") { + const block = this.parse_block(); + value_.push(block); + next = block.next; + } + const valueNode = this.createNode("value", value_, lodash.first(value_).start, lodash.last(value_).next); + const declarationValue = [propertyNode, value[puncIndex], valueNode]; + if (punctuation === ";") { + const {start: start2} = this.skip_punctuation(";"); + declarationValue.push(start2); + next = next.start; + } + return this.createNode("declaration", declarationValue, start, next); + } + } + return false; + }; + while (!this.tokens.eof()) { + if (this.is_atkeyword()) { + return value.concat(this.parse_at_rule()); + } + value.push(this.parse_atom()); + if (this.is_punctuation("{")) { + if (value.length) { + return maybe_declaration("{") || this.parse_rule(value); + } else { + return value.concat(this.parse_block()); + } + } + if (this.is_punctuation(";")) { + return maybe_declaration(";"); + } + } + return value; + } + parse_expression(predicate) { + let value = []; + let declaration = []; + while (true) { + if (this.tokens.eof() || !predicate()) + break; + if (this.is_punctuation(":") && declaration.length) { + value.push(this.parse_declaration(declaration)); + value = lodash.xor(value, declaration); + declaration = []; + } + if (this.tokens.eof() || !predicate()) + break; + const atom = this.parse_atom(); + value.push(atom); + switch (atom.type) { + case "space": + case "punctuation": + break; + default: + declaration.push(atom); + } + } + return value; + } + parse_atom() { + return this.maybe_function(() => { + if (this.is_punctuation("(")) { + return this.parse_wrapped("parentheses", "(", ")"); + } + if (this.is_interpolation()) { + return this.parse_interolation(); + } + if (this.is_punctuation("[")) { + return this.parse_wrapped("attribute", "[", "]"); + } + if (this.is_punctuation(".")) { + return this.parse_selector("class", "."); + } + if (this.is_punctuation("#")) { + return this.parse_selector("id", "#"); + } + if (this.is_punctuation("::")) { + return this.parse_selector("pseudo_element", ":"); + } + if (this.is_punctuation(":")) { + const next = this.tokens.peek(1); + if (next.type === "identifier" || next.type === "punctuation" && next.value === "#") { + return this.parse_selector("pseudo_class", ":"); + } + } + return this.tokens.next(); + }); + } + parse_declaration(property) { + const {start: firstSeparator} = this.skip_punctuation(":"); + let secondSeparator; + const value = this.parse_expression(() => { + if (this.is_punctuation(";")) { + secondSeparator = this.tokens.next(); + return false; + } + if (this.is_punctuation(",")) { + secondSeparator = this.tokens.next(); + return false; + } + if (this.is_punctuation(")")) + return false; + return true; + }); + const propertyNode = this.createNode("property", property, lodash.first(property).start, lodash.last(property).next); + const valueNode = this.createNode("value", value, lodash.first(value).start, lodash.last(value).next); + const declarationValue = [propertyNode, firstSeparator, valueNode]; + if (secondSeparator) + declarationValue.push(secondSeparator); + return this.createNode("declaration", declarationValue, lodash.first(property).start, lodash.last(value).next); + } + parse_wrapped(type2, open, close, _start) { + const {start} = this.skip_punctuation(open); + const value = this.parse_expression(() => !this.is_punctuation(close)); + const {next} = this.skip_punctuation(close); + return this.createNode(type2, value, (_start || start).start, next.next); + } + parse_block() { + const {start} = this.skip_punctuation("{"); + const value = []; + while (!this.tokens.eof() && !this.is_punctuation("}")) { + const node = this.parse_node(); + if (lodash.isArray(node)) { + value.push(...node); + } else { + value.push(node); + } + } + const {next} = this.skip_punctuation("}"); + if (this.is_punctuation(";")) { + this.skip_punctuation(";"); + } + return this.createNode("block", value, start.start, next.next); + } + parse_arguments(type2) { + const {start} = this.skip_punctuation("("); + let value = []; + if (type2 === "pseudo_class") { + while (!this.tokens.eof() && !this.is_punctuation(")")) { + value.push(this.parse_atom()); + } + } else { + while (!this.tokens.eof() && !this.is_punctuation(")")) { + value = value.concat(this.parse_expression(() => { + if (this.is_punctuation(",")) + return false; + if (this.is_punctuation(")")) + return false; + return true; + })); + if (this.is_punctuation(",")) { + value.push(this.tokens.next()); + } + } + } + const {next} = this.skip_punctuation(")"); + return this.createNode("arguments", value, start.start, next.next); + } + maybe_function(node) { + node = node(); + const types = ["identifier", "function", "interpolation", "pseudo_class"]; + return this.is_punctuation("(") && lodash.includes(types, node.type) ? this.parse_function(node) : node; + } + parse_function(node) { + const args = this.parse_arguments(node.type); + return this.createNode("function", [node, args], node.start, args.next); + } + parse_interolation() { + const {start} = this.skip_punctuation("#"); + return this.parse_wrapped("interpolation", "{", "}", start); + } + parse_at_rule() { + const {start} = this.skip_atkeyword(); + const value = [start]; + if (this.is_space()) + value.push(this.tokens.next()); + if (this.is_identifier()) + value.push(this.tokens.next()); + while (!this.tokens.eof()) { + if (this.is_punctuation("(") && /mixin|include|function/.test(start.value)) { + value.push(this.parse_arguments()); + } + if (this.is_punctuation("{")) { + value.push(this.parse_block()); + break; + } + if (this.is_punctuation(";")) { + value.push(this.tokens.next()); + break; + } else { + value.push(this.parse_atom()); + } + } + return this.createNode("atrule", value, start.start, lodash.last(value).next); + } + parse_rule(selectors) { + const selector = this.createNode("selector", selectors, lodash.first(selectors).start, lodash.last(selectors).next); + const block = this.parse_block(); + return this.createNode("rule", [selector, block], selector.start, block.next); + } + parse_selector(type2, punctuation) { + const {start} = this.skip_punctuation(punctuation); + if (this.is_punctuation(":")) { + this.skip_punctuation(":"); + } + const value = []; + let next = this.is_interpolation() ? this.parse_interolation() : this.tokens.next(); + while (next.type === "identifier" || next.type === "interpolation" || next.type === "operator") { + value.push(next); + next = this.is_interpolation() ? this.parse_interolation() : this.tokens.peek(); + if (!next) + break; + if (next.type === "identifier") + this.tokens.next(); + if (next.type === "operator") + this.tokens.next(); + } + if (!value.length) { + this.tokens.err(`Selector ("${type2}") expected "identifier" or "interpolation"`); + } + return this.createNode(type2, value, start.start, lodash.last(value).next); + } +} +var parse = (tokenStream2) => { + invariant2(lodash.isPlainObject(tokenStream2) && lodash.has(tokenStream2, "next"), "Parser requires a TokenStream"); + const parser = new Parser(tokenStream2); + return parser.parse_stylesheet(); +}; +const type = { + arguments: (n) => "(" + walkValue(n.value) + ")", + atkeyword: (n) => "@" + n.value, + attribute: (n) => "[" + walkValue(n.value) + "]", + block: (n) => "{" + walkValue(n.value) + "}", + class: (n) => "." + walkValue(n.value), + color_hex: (n) => "#" + n.value, + id: (n) => "#" + walkValue(n.value), + interpolation: (n) => "#{" + walkValue(n.value) + "}", + comment_multiline: (n) => "/*" + n.value + "*/", + comment_singleline: (n) => "//" + n.value, + parentheses: (n) => "(" + walkValue(n.value) + ")", + pseudo_class: (n) => ":" + walkValue(n.value), + psuedo_element: (n) => "::" + walkValue(n.value), + string_double: (n) => `"${n.value}"`, + string_single: (n) => `'${n.value}'`, + variable: (n) => "$" + n.value +}; +const walkNode = (node) => { + if (type[node.type]) + return type[node.type](node); + if (lodash.isString(node.value)) + return node.value; + if (lodash.isArray(node.value)) + return walkValue(node.value); + return ""; +}; +const walkValue = (value) => { + if (!lodash.isArray(value)) + return ""; + return value.reduce((s, node) => { + return s + walkNode(node); + }, ""); +}; +var stringify = (node) => walkNode(node); +const parse$1 = (css) => parse(tokenStream(inputStream(css))); +const stringify$1 = (node) => stringify(node); +var lib = { + parse: parse$1, + stringify: stringify$1 +}; +export default lib; +var parse$2 = lib.parse; +var stringify$2 = lib.stringify; +export {lib as __moduleExports, parse$2 as parse, stringify$2 as stringify}; diff --git a/src/vendor/cdn.skypack.dev/scss-parser@1.0.6.js b/src/vendor/cdn.skypack.dev/scss-parser@1.0.6.js new file mode 100644 index 00000000000..4c4d7dabc12 --- /dev/null +++ b/src/vendor/cdn.skypack.dev/scss-parser@1.0.6.js @@ -0,0 +1,16 @@ +/* + * Skypack CDN - scss-parser@1.0.6 + * + * Learn more: + * 📙 Package Documentation: https://www.skypack.dev/view/scss-parser + * 📘 Skypack Documentation: https://www.skypack.dev/docs + * + * Pinned URL: (Optimized for Production) + * ▶️ Normal: https://cdn.skypack.dev/pin/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/mode=imports/optimized/scss-parser.js + * ⏩ Minified: https://cdn.skypack.dev/pin/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/mode=imports,min/optimized/scss-parser.js + * + */ + +// Browser-Optimized Imports (Don't directly import the URLs below in your application!) +export * from '/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js'; +export {default} from '/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js'; diff --git a/src/vendor/import_map.json b/src/vendor/import_map.json index 51288c6c192..7cc87be0a69 100644 --- a/src/vendor/import_map.json +++ b/src/vendor/import_map.json @@ -20,7 +20,6 @@ "cliffy/command/command.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/command/command.ts", "fmt/colors.ts": "./deno.land/std@0.217.0/fmt/colors.ts", "cliffy/prompt/select.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/prompt/select.ts", - "cliffy/prompt/confirm.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts", "fs/expand_glob.ts": "./deno.land/std@0.217.0/fs/expand_glob.ts", "fs/exists.ts": "./deno.land/std@0.217.0/fs/exists.ts", "encoding/base64.ts": "./deno.land/std@0.217.0/encoding/base64.ts", @@ -39,7 +38,6 @@ "deno_dom/src/dom/dom-parser.ts": "./deno.land/x/deno_dom@v0.1.35-alpha/src/dom/dom-parser.ts", "deno_dom/src/api.ts": "./deno.land/x/deno_dom@v0.1.35-alpha/src/api.ts", "deno_dom/src/dom/node.ts": "./deno.land/x/deno_dom@v0.1.35-alpha/src/dom/node.ts", - "colors": "./deno.land/std@0.217.0/fmt/colors.ts", "streams/mod.ts": "./deno.land/std@0.217.0/streams/mod.ts", "crypto/mod.ts": "./deno.land/std@0.217.0/crypto/mod.ts", "blueimpMd5": "./cdn.skypack.dev/blueimp-md5@2.19.0.js", @@ -68,6 +66,7 @@ "path/mod.ts": "./deno.land/std@0.217.0/path/mod.ts", "async/mod.ts": "./deno.land/std@0.217.0/async/mod.ts", "dotenv/mod.ts": "./deno.land/std@0.217.0/dotenv/mod.ts", + "scss-parser": "./cdn.skypack.dev/scss-parser@1.0.6.js", "fmt/printf.ts": "./deno.land/std@0.217.0/fmt/printf.ts", "yaml/schema.ts": "./deno.land/std@0.217.0/yaml/schema.ts", "yaml/type.ts": "./deno.land/std@0.217.0/yaml/type.ts", @@ -83,12 +82,14 @@ "xml/mod.ts": "./deno.land/x/xml@2.1.1/mod.ts", "path/dirname.ts": "./deno.land/std@0.217.0/path/dirname.ts", "xmlp/mod.ts": "./deno.land/x/xmlp@v0.2.8/mod.ts", + "cliffy/prompt/confirm.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts", "io/copy.ts": "./deno.land/std@0.217.0/io/copy.ts", "archive/tar.ts": "./deno.land/std@0.217.0/archive/tar.ts", "cliffy/prompt/input.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/prompt/input.ts", "encoding/hex.ts": "./deno.land/std@0.217.0/encoding/hex.ts", "cliffy/prompt/secret.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/prompt/secret.ts", "another_cookiejar/mod.ts": "./deno.land/x/another_cookiejar@v5.0.3/mod.ts", + "cliffy/command/_errors.ts": "./deno.land/x/cliffy@v1.0.0-rc.3/command/_errors.ts", "https://deno.land/std@0.93.0/path/mod.ts": "./deno.land/std@0.204.0/path/mod.ts", "binary-search-bounds": "./cdn.skypack.dev/binary-search-bounds@2.0.5.js", "slimdom": "./cdn.skypack.dev/slimdom@4.2.0.js", @@ -194,6 +195,7 @@ "/-/mensch@v0.3.4-bYdFVPGjq4ZCCd5bQOiD/dist=es2019,mode=imports/optimized/mensch.js": "./cdn.skypack.dev/-/mensch@v0.3.4-bYdFVPGjq4ZCCd5bQOiD/dist=es2019,mode=imports/optimized/mensch.js", "/-/slick@v1.12.2-aV7vJdJVxGxCoP6YSykY/dist=es2019,mode=imports/unoptimized/parser.js": "./cdn.skypack.dev/-/slick@v1.12.2-aV7vJdJVxGxCoP6YSykY/dist=es2019,mode=imports/unoptimized/parser.js", "/-/entities@v4.3.0-V4vIlnoYfSBRg1gj9BOL/dist=es2019,mode=imports/optimized/entities/lib/escape.js": "./cdn.skypack.dev/-/entities@v4.3.0-V4vIlnoYfSBRg1gj9BOL/dist=es2019,mode=imports/optimized/entities/lib/escape.js", + "/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js": "./cdn.skypack.dev/-/invariant@v2.2.4-dATvH51LFSHlzMqhAQS8/dist=es2019,mode=imports/optimized/invariant.js", "/-/whynot@v5.0.0-TIWeI93neceQKiPCfmA6/dist=es2019,mode=imports/optimized/whynot.js": "./cdn.skypack.dev/-/whynot@v5.0.0-TIWeI93neceQKiPCfmA6/dist=es2019,mode=imports/optimized/whynot.js", "/-/@observablehq/parser@v4.5.0-rWZiNfab8flhVomtfVvr/dist=es2019,mode=imports/optimized/@observablehq/parser.js": "./cdn.skypack.dev/-/@observablehq/parser@v4.5.0-rWZiNfab8flhVomtfVvr/dist=es2019,mode=imports/optimized/@observablehq/parser.js", "/-/acorn-class-fields@v1.0.0-VEggkLxq9gMrdwRuKkzZ/dist=es2019,mode=imports/optimized/acorn-class-fields.js": "./cdn.skypack.dev/-/acorn-class-fields@v1.0.0-VEggkLxq9gMrdwRuKkzZ/dist=es2019,mode=imports/optimized/acorn-class-fields.js", @@ -221,6 +223,7 @@ "/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniq.js": "./cdn.skypack.dev/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniq.js", "/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniqBy.js": "./cdn.skypack.dev/-/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/dist=es2019,mode=imports/unoptimized/uniqBy.js", "/-/moment-guess@v1.2.4-bDXl7KQy0hLGNuGhyGb4/dist=es2019,mode=imports/optimized/moment-guess.js": "./cdn.skypack.dev/-/moment-guess@v1.2.4-bDXl7KQy0hLGNuGhyGb4/dist=es2019,mode=imports/optimized/moment-guess.js", + "/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js": "./cdn.skypack.dev/-/scss-parser@v1.0.6-hrwwdU1eImlkqs8SqYeB/dist=es2019,mode=imports/optimized/scss-parser.js", "/-/slimdom@v4.2.0-QzuHPU3P67qdOzczKt6u/dist=es2019,mode=imports/optimized/slimdom.js": "./cdn.skypack.dev/-/slimdom@v4.2.0-QzuHPU3P67qdOzczKt6u/dist=es2019,mode=imports/optimized/slimdom.js" } } diff --git a/tools/sass-variable-explainer/fix-dot-svg.js b/tools/sass-variable-explainer/fix-dot-svg.js new file mode 100644 index 00000000000..d78007fb446 --- /dev/null +++ b/tools/sass-variable-explainer/fix-dot-svg.js @@ -0,0 +1,9 @@ +const desiredWidth = 800; +for (const svg of Array.from(document.querySelectorAll("svg"))) { + const viewBox = svg.getAttribute("viewBox").split(" "); + svg.setAttribute("width", String(desiredWidth)); + svg.setAttribute( + "height", + String((desiredWidth / parseFloat(viewBox[2])) * parseFloat(viewBox[3])) + ); +} diff --git a/tools/sass-variable-explainer/hello.qmd b/tools/sass-variable-explainer/hello.qmd new file mode 100644 index 00000000000..cd18b0e26e8 --- /dev/null +++ b/tools/sass-variable-explainer/hello.qmd @@ -0,0 +1,13 @@ +--- +format: + # html: + # theme: cosmo + html: + theme: + - cosmo + - tweaks.scss +--- + +## Hello + + \ No newline at end of file diff --git a/tools/sass-variable-explainer/main.qmd b/tools/sass-variable-explainer/main.qmd new file mode 100644 index 00000000000..b9d1ed1f09a --- /dev/null +++ b/tools/sass-variable-explainer/main.qmd @@ -0,0 +1,26 @@ +--- +title: Explain my SCSS variables pls ok thx +keep-ipynb: true +--- + +````{python} +#| echo: false +#| output: asis +import re +import subprocess +import json +import tempfile + +filename = "hello-1.scss" + +output = subprocess.run( + ["deno", "run", "--allow-all", "print-dependency-graph.ts", filename], + capture_output = True).stdout.decode('utf-8') + +print(output) + +## Our DOT svg engine is a bit broken in determining good sizes, so we will help it here. +print("""\n\n```{=html} + +```""") +```` \ No newline at end of file diff --git a/tools/sass-variable-explainer/print-dependency-graph.ts b/tools/sass-variable-explainer/print-dependency-graph.ts new file mode 100644 index 00000000000..9e9d157aeb4 --- /dev/null +++ b/tools/sass-variable-explainer/print-dependency-graph.ts @@ -0,0 +1,119 @@ +import { parse } from "npm:scss-parser"; +import { assert } from "jsr:@std/assert"; +import * as prettier from "npm:prettier"; +import { propagateDeclarationTypes } from "./sass-analyzer/declaration-types.ts"; +import { getVariableDependencies } from "./sass-analyzer/get-dependencies.ts"; +import { cleanSassAst } from "./sass-analyzer/clean-ast.ts"; +import { makeParserModule } from "./sass-analyzer/parse.ts"; + +export const getSassAst = makeParserModule(parse, prettier.format).getSassAst; + +const drawColorDependencyGraph = (ast: any) => { + const declarations = propagateDeclarationTypes(ast); + + let labelCount = 0; + const labels: Map = new Map(); + const dotNodeName = (name: string) => { + if (labels.has(name)) { + return { id: labels.get(name) }; + } + const newName = `N${labelCount++}`; + labels.set(name, newName); + return { id: newName, nodeDecl: `${newName}[label="${name}"]` }; + } + + console.log("```{dot}"); + console.log("digraph G {\n rankdir=LR;\n"); + console.log(" splines=false;"); + console.log(" node [shape=rectangle, color=gray]"); + console.log(" edge [color=gray]"); + + const varDeps = getVariableDependencies(declarations); + const inverseVarDeps = new Map>(); + const origins = new Map>(); + const addToSetMap = (map: Map>, key: string, value: string) => { + if (!map.has(key)) { + map.set(key, new Set()); + } + map.get(key)!.add(value); + } + + for (const [name, deps] of varDeps) { + // update origin sets + const node = deps.node; + const origin = node?.annotation?.origin ?? "unknown"; + addToSetMap(origins, origin, name); + // update inverse dependencies + for (const dep of deps.dependencies) { + if (declarations.get(name)?.valueType !== "color" || + declarations.get(dep)?.valueType !== "color") { + continue; + } + addToSetMap(inverseVarDeps, dep, name); + } + } + let subgraphCount = 0; + for (const [name, vars] of origins) { + if (name === "unknown") { + continue; + } + subgraphCount++; + console.log(`subgraph subgraph_${subgraphCount} {`); + for (const varName of vars) { + // only show numbered colors if they have inverse dependencies + if (varName.match(/^.+-[0-9]00$/) && !inverseVarDeps.get(varName)?.size) { + continue; + } + const { nodeDecl: sourceNodeDecl } = dotNodeName(varName); + if (!sourceNodeDecl) { + throw new Error("multiple origins for a variable? " + varName); + } + assert(sourceNodeDecl); + console.log(` ${sourceNodeDecl}`); + } + console.log(` label = "${name}"`); + console.log(` color=red`); + console.log("}"); + } + + for (const [name, deps] of varDeps) { + if (deps.node.valueType !== "color") { + continue; + } + // only show numbered colors if they have inverse dependencies + if (name.match(/^.+-[0-9]00$/) && !inverseVarDeps.get(name)?.size) { + continue; + } + for (const dep of deps.dependencies) { + if (declarations.get(dep)?.valueType !== "color") { + continue; + } + const {id: sourceId, nodeDecl: sourceNodeDecl } = dotNodeName(dep); + const {id: targetId, nodeDecl: targetNodeDecl } = dotNodeName(name); + if (sourceNodeDecl) { + console.log(` ${sourceNodeDecl}`); + } + if (targetNodeDecl) { + console.log(` ${targetNodeDecl}`); + } + + console.log(` ${sourceId} -> ${targetId}`); + } + } + + console.log("}"); + console.log("```"); +} + +if (import.meta.main) { + const ast = await getSassAst(Deno.readTextFileSync(Deno.args[0] || "/dev/stdin")); + let cleaned = cleanSassAst(ast); + drawColorDependencyGraph(cleaned); + // const declarations = propagateDeclarationTypes(cleaned); + // for (const [name, node] of declarations) { + // if (node.valueType === "color") { + // console.log(name, node.line); + // } + // // console.log(name, node); + // } +} \ No newline at end of file diff --git a/tools/sass-variable-explainer/process-scss.ts b/tools/sass-variable-explainer/process-scss.ts new file mode 100644 index 00000000000..7c1150d710b --- /dev/null +++ b/tools/sass-variable-explainer/process-scss.ts @@ -0,0 +1,151 @@ +import { getSassAst } from "./sass-analyze.ts"; +import { walk } from "./sass-analyzer/ast-utils.ts"; + +let contents = Deno.readTextFileSync(Deno.args[0] || "/dev/stdin"); +const ast = getSassAst(contents); + +type Matcher = number | ((v: unknown) => unknown); + +const isType = (type: string): Matcher => { + return (v: unknown) => { + if (!v || typeof v !== "object") return false; + if ((v as Record).type === type) { return v; } else { return false }; + }; +} + +const getSingleValueOfType = (type: string): Matcher => { + return (v: unknown) => { + if (!v || typeof v !== "object") return false; + const value = (v as Record).value; + if (!Array.isArray(value)) return false; + const valuesOfType = value.filter((v) => (v as Record).type === type); + if (valuesOfType.length !== 1) return false; + return valuesOfType[0]; + }; +} + +const isDefault = (v: unknown): Matcher => { + return (v: unknown) => { + if (!v || typeof v !== "object") return false; + if ((v as Record).type !== "value") return false; + const value = (v as Record).value as any[]; + if (value[value.length - 1].type !== "identifier" || value[value.length - 1].value !== "default") return false; + if (value[value.length - 2].type !== "operator" || value[value.length - 2].value !== "!") return false; + return v; + } +} + +const match = (param: unknown, matcher: Matcher[]): unknown => { + if (!param || typeof param !== "object") return undefined; + if (matcher.length === 0) return param; + const obj = param as Record; + const [key, ...rest] = matcher; + if (typeof key === "function") { + const result = key(obj); + if (!result) return undefined; + return match(result, rest); + } else if (typeof key === "number") { + if (!(Array.isArray(obj.value))) { + return undefined; + } + return match(obj.value[key], rest); + } +} + +type Dependency = { + name: string; + references: string[]; +}; + +const getDependencies = (ast: any): Dependency[] => { + const dependencies: any[] = []; + + for (const entry of ast.value) { + const variableNameMatcher = [ + isType("declaration"), + 0, + isType("property"), + 0, + isType("variable"), + ]; + const variableNameNode = match(entry, variableNameMatcher); + if (!variableNameNode) { + continue; + } + const variableValueMatcher = [ + isType("declaration"), + getSingleValueOfType("value"), + ]; + const variableValueNode = match(entry, variableValueMatcher); + if (!variableValueNode) { + continue; + } + + // console.log((variableNameNode as any).type); + // console.log(variableValueNode); // (variableValueNode as any).type); + const variableName = (variableNameNode as { value: string }).value; + + const references: string[] = []; + + const walker = (node: any) => { + const ifStmt = [ + isType("function"), + 0, + isType("identifier"), + (v: any) => v.value === "if" && v, + ]; + if (match(node, ifStmt)) { + // this thing really is not a parser, it's a glorified tokenizer + + const tokenStream = node.value[1].value.filter( + (x: any) => x.type !== "space" && + x.type !== "comment_singleline" && + x.type !== "comment_multiline"); + // split on comma: { type: "punctuation", value: "," } + let currentArg: any[] = []; + let firstArg = true; + for (const token of tokenStream) { + if (token.type === "punctuation" && token.value === ",") { + if (firstArg) { + firstArg = false; + } else { + walk(currentArg, walker); + } + currentArg = []; + } else { + currentArg.push(token); + } + } + if (!firstArg) { + walk(currentArg, walker); + } + return false; + } + if (node.type === "variable") { + references.push(node.value); + } + return true; + }; + + walk(variableValueNode, walker); + + if (references.length) { + dependencies.push({ name: variableName, references }); + } + } + return dependencies; +} + +const dependencies = getDependencies(ast); + +const getTypeAnalysis = (ast: any) => { + // now we try to figure out variable types as best we can + const variableTypes: Record = {}; + for (const entry of ast.value) { + } +} + + +console.log(JSON.stringify({ + dependencies +}, null, 2)); \ No newline at end of file diff --git a/tools/sass-variable-explainer/sass-analyzer/ast-utils.ts b/tools/sass-variable-explainer/sass-analyzer/ast-utils.ts new file mode 100644 index 00000000000..b74bda68437 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/ast-utils.ts @@ -0,0 +1,69 @@ +export const walk = (node: any, cb: (node: any) => unknown) => { + if (!node || typeof node !== "object") return; + if (!cb(node)) { + return; + }; + for (const key of Object.keys(node)) { + walk(node[key], cb); + } +} + +export const withType = (node: any, func: (ast: any) => any) => { + if (!node?.type) { + return node; + } + return func(node); +} + +export const withTypeAndArray = (node: any, func: (ast: any) => any) => { + if (!node?.type) { + return node; + } + if (!node?.children || !Array.isArray(node.children)) { + return node; + } + return func(node); +} + +export const filterDeep = (outer: any, cb: (v: any) => boolean): any => + withType(outer, (ast: any) => { + return Object.fromEntries(Object.entries(ast).map(([k, v]) => { + if (Array.isArray(v)) { + return [k, v.filter(cb).map((v: any) => filterDeep(v, cb))]; + } else if (v && typeof v === "object") { + return [k, filterDeep(v, cb)]; + } else { + return [k, v]; + } + })); + }); + + export const mapDeep = (outer: any, cb: (mapped: any) => any): any => + withType(outer, (ast: any) => { + if (Array.isArray(ast.children)) { + ast.children = ast.children.map((v: any) => mapDeep(v, cb)); + } + if (Array.isArray(ast.value)) { + ast.value = ast.value.map((v: any) => mapDeep(v, cb)); + } + return cb(ast); + }); + +export const collect = (outer: any, cb: (v: any) => boolean): any[] => { + const results: any = []; + walk(outer, (node: any) => { + if (cb(node)) { + results.push(node); + } + return true; + }); + return results; +} + +export const annotateNode = (node: any, annotation: Record) => { + if (!node.annotation) { + node.annotation = {}; + } + Object.assign(node.annotation, annotation); + return node; +} \ No newline at end of file diff --git a/tools/sass-variable-explainer/sass-analyzer/clean-ast.ts b/tools/sass-variable-explainer/sass-analyzer/clean-ast.ts new file mode 100644 index 00000000000..34784bb3f9e --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/clean-ast.ts @@ -0,0 +1,56 @@ +import { withTypeAndArray, filterDeep, mapDeep } from "./ast-utils.ts"; +import { isRealContent, isNotPunctuation } from "./remove-nonsemantic-entries.ts"; +import { simplifyLineInfo } from "./line-info.ts"; +import { explicitlyTagDefaultValues } from "./default-declarations.ts"; +import { fixImmediateTypes, tagNamedColors, tagColorConstructors, findDimensionValues } from "./value-types.ts"; +import { groupArguments } from "./group-arguments.ts"; +import { forwardAnnotations } from "./forward-annotations.ts"; + +const valueArrayToObjectKeys = (outer: any) => + withTypeAndArray(outer, (node: any) => { + const keys = node.children.map((v: any) => v.type); + if (keys.length !== new Set(keys).size) { + return node; + } + return { + ...node, + ...Object.fromEntries(node.children + .map((v: any) => { + const key = v.type; + let children = v.children; + return [key, {...v, children}]; + })), + }; + }); + +export const cleanSassAst = (ast: any) => { + // we now attempt to turn this glorified lexer into a real AST + + // before everything else, we associate declarations with the + // annotations that tell us which part of the theming system + // they belong to + ast = forwardAnnotations(ast); + + // before clearing out the punctuation, group arguments + ast = filterDeep(ast, isRealContent); + ast = mapDeep(ast, groupArguments); + + // clear out all the gunk from the AST + ast = filterDeep(ast, isNotPunctuation); + + ast = mapDeep(ast, simplifyLineInfo); + ast = mapDeep(ast, explicitlyTagDefaultValues); + ast = mapDeep(ast, findDimensionValues); + ast = mapDeep(ast, fixImmediateTypes); + ast = mapDeep(ast, tagColorConstructors); + ast = mapDeep(ast, tagNamedColors); + + // if the value array looks like an array of keys and values, + // insert those values into the parent object + // additionally, in these properties, if the value is an array + // with a single element, remove the array and just use the + // element. + ast = mapDeep(ast, valueArrayToObjectKeys); + + return ast; +} diff --git a/tools/sass-variable-explainer/sass-analyzer/css-information.ts b/tools/sass-variable-explainer/sass-analyzer/css-information.ts new file mode 100644 index 00000000000..9cf2bac0728 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/css-information.ts @@ -0,0 +1,186 @@ +export const units: Set = new Set([ + // found in 2024-07-29 + // length https://developer.mozilla.org/en-US/docs/Web/CSS/length, + "cap", "ic", "lh", "rcap", "rch", "rex", "ric", "rlh", "vb", "vi", "cqw", + "cqh", "cqi", "cqmin", "cqmax", + "Q", + "rem", "em", "px", "pt", "pc", "cm", "mm", "in", "ex", "ch", "vw", "vh", "vmin", "vmax", + // angle https://developer.mozilla.org/en-US/docs/Web/CSS/angle + "deg", "grad", "rad", "turn", + // time https://developer.mozilla.org/en-US/docs/Web/CSS/time + "s", "ms", + // resolution https://developer.mozilla.org/en-US/docs/Web/CSS/resolution + "dpi", "dpcm", "dppx", "x", + // frequency https://developer.mozilla.org/en-US/docs/Web/CSS/frequency + "Hz", "kHz" +]); + +export const namedColors = new Set([ + "black", + "silver", + "gray", + "white", + "maroon", + "red", + "purple", + "fuchsia", + "green", + "lime", + "olive", + "yellow", + "navy", + "blue", + "teal", + "aqua", + "aliceblue", + "antiquewhite", + "aqua", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanchedalmond", + "blue", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflowerblue", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkgrey", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategray", + "darkslategrey", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dimgrey", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "fuchsia", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "gray", + "green", + "greenyellow", + "grey", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrodyellow", + "lightgray", + "lightgreen", + "lightgrey", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategray", + "lightslategrey", + "lightsteelblue", + "lightyellow", + "lime", + "limegreen", + "linen", + "magenta", + "maroon", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "navy", + "oldlace", + "olive", + "olivedrab", + "orange", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "purple", + "rebeccapurple", + "red", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "silver", + "skyblue", + "slateblue", + "slategray", + "slategrey", + "snow", + "springgreen", + "steelblue", + "tan", + "teal", + "thistle", + "tomato", + "transparent", + "turquoise", + "violet", + "wheat", + "white", + "whitesmoke", + "yellow", + "yellowgreen", + + "currentcolor" // this is a bit of a hack, but it's used in color contexts +]); diff --git a/tools/sass-variable-explainer/sass-analyzer/declaration-types.ts b/tools/sass-variable-explainer/sass-analyzer/declaration-types.ts new file mode 100644 index 00000000000..f4fea5fdad1 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/declaration-types.ts @@ -0,0 +1,204 @@ +export const propagateDeclarationTypes = (ast: any) => { + + const declarationsToTrack = new Map(); + + const typesToSkip = new Set([ + "identifier", "boolean", + "number", "dimension", "percentage", + "string", "string_double", "string_single"]); + + const namesToIgnore: Set = new Set([ + "title-banner-image", // with this hack, we can assume all other instances of 'null' are color + "theme", + "theme-name", + "enable-grid-classes", + "enable-cssgrid", + "nav-tabs-link-active-border-color", + "navbar-light-bg", + "navbar-dark-bg", + "navbar-light-color", + "navbar-light-hover-color", + "navbar-light-active-color", + "navbar-light-disabled-color", + "navbar-light-toggler-icon-bg", + "navbar-light-toggler-border-color", + "navbar-light-brand-color", + "navbar-light-brand-hover-color", + "navbar-dark-color", + "navbar-dark-hover-color", + "navbar-dark-active-color", + "navbar-dark-disabled-color", + "navbar-dark-toggler-icon-bg", + "navbar-dark-toggler-border-color", + "navbar-dark-brand-color", + "navbar-dark-brand-hover-color", + ]); + + const speciallyKnownTypes: Record = { + "link-color": "color", + "input-border-color": "color", + "title-banner-color": "color", + "theme": "string", + }; + + for (const node of ast.children) { + if (node?.type !== "declaration") { + continue; + } + + // ignore declarations that have documented + // non-standard !default rules because of the + // way we set if() conditions in our SCSS + const varName = node?.property?.variable?.value; + if (namesToIgnore.has(varName)) { + continue; + } + const varValue = node?.value?.value; + if (declarationsToTrack.has(varName)) { + const prevDeclaration = declarationsToTrack.get(varName); + if (prevDeclaration?.value?.isDefault && + node?.value?.isDefault) { + // pass + } else if (!prevDeclaration?.value?.isDefault && + !node?.value?.isDefault) { + declarationsToTrack.set(varName, node); + } else { + // are these special cases? + if (speciallyKnownTypes[varName]) { + node.valueType = speciallyKnownTypes[varName]; + declarationsToTrack.set(varName, node); + } else { + console.log("Warning: variable redeclaration with conflicting default settings"); + console.log("variable: ", varName); + console.log("lines ", prevDeclaration?.line, node?.line); + } + } + } else { + declarationsToTrack.set(varName, node); + } + } + + const valueTypeMap: Record = { + "number": "number", + "boolean": "boolean", + "string": "string", + "dimension": "dimension", + "percentage": "percentage", + "identifier": "identifier", + "color_hex": "color", + "named_color": "color", + "string_double": "string", + "string_single": "string", + "null": "color", // This is specific to our themes, and requires excluding 'title-banner-image' above + }; + + const functionTypeResolver: Record string | undefined> = { + "theme-contrast": (_: any) => "color", + "quote": (_: any) => "string", + "url": (_: any) => "string", + "tint-color": (_: any) => "color", + "shade-color": (_: any) => "color", + "lighten": (_: any) => "color", + "darken": (_: any) => "color", + "mix": (_: any) => "color", + "shift-color": (_: any) => "color", + "linear-gradient": (_: any) => "image", + "color-contrast": (_: any) => "color", + "translate3d": (_: any) => "transform-function", + "rotate": (_: any) => "transform-function", + "translate": (_: any) => "transform-function", + "scale": (_: any) => "transform-function", + "calc": (_: any) => "calc-value", // this can be a number, percentage, or dimension, but we don't presently care + "add": (_: any) => "__unimplemented__", + "subtract": (_: any) => "__unimplemented__", + "brightness": (_: any) => "filter", + "minmax": (_: any) => "grid-template", + "var": (valueNode: any) => "__unimplemented__", + + // This is used in bslib as an instance of the hack described here: + // https://css-tricks.com/when-sass-and-new-css-features-collide/ + // it's truly atrocious and we'll never be able to track this kind of thing properly, + // but we can at least make sure it doesn't break the rest of the analysis + "Min": (_: any) => "__unimplemented__", + + "theme-override-value": (valueNode: any) => { + const defaultValue = valueNode?.arguments?.children[2]; + if (defaultValue && typeForValue(defaultValue)) { + return typeForValue(defaultValue); + } else { + return undefined; + } + }, + "if": (valueNode: any) => { + const _condition = valueNode?.arguments?.children[0]; + const trueValue = valueNode?.arguments?.children[1]; + const falseValue = valueNode?.arguments?.children[2]; + // we will assume type consistency for now + if (trueValue) { + const trueType = typeForValue(trueValue); + if (trueType) { + return trueType; + } + } + if (falseValue) { + const falseType = typeForValue(falseValue); + if (falseType) { + return falseType; + } + } + return undefined; + } + } + + const typeForValue = (valueNode: any): string | undefined => { + const nodeValueType = valueNode?.type; + if (valueTypeMap[nodeValueType]) { + return valueTypeMap[nodeValueType]; + } + if (nodeValueType === "variable") { + const nodeVariableName = valueNode?.value; + if (!declarationsToTrack.has(nodeVariableName) && !namesToIgnore.has(nodeVariableName)) { + console.log("Warning: variable used before declaration"); + console.log("variable: ", nodeVariableName, valueNode.line); + return undefined; + } else { + const valueType = declarationsToTrack.get(nodeVariableName)?.valueType; + if (valueType) { + return valueType; + } + } + } + if (nodeValueType === "function") { + const functionName = valueNode?.identifier?.value; + if (functionTypeResolver[functionName]) { + return functionTypeResolver[functionName](valueNode); + } + } + } + + // tag all declarations with values of known types + for (const [name, node] of declarationsToTrack) { + if (node?.value?.type === "value") { + const valueType = node.value.value[0].valueType || typeForValue(node.value.value[0]); + if (valueType) { + node.valueType = valueType; + } + } + } + return declarationsToTrack; + + // // now warn about variables with unknown types + // for (const [name, node] of declarationsToTrack) { + // if (node.valueType === "color") { + // console.log(name, node.line) + // } + // if (!node.valueType && node.value.value.length === 1) { + // // ignore unknown types for multi-value declarations, assume they're arrays which we don't care about. + // if (node.value.value[0]?.type === "parentheses") { + // continue; + // } + // console.log("Warning: variable with unknown type"); + // console.log("variable: ", name, node); + // } + // } +} diff --git a/tools/sass-variable-explainer/sass-analyzer/default-declarations.ts b/tools/sass-variable-explainer/sass-analyzer/default-declarations.ts new file mode 100644 index 00000000000..1fcb3601cc2 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/default-declarations.ts @@ -0,0 +1,24 @@ +import { withType } from './ast-utils.ts'; + +// FIXME in SCSS, _declarations_ have a `!default` flag, not _values_ +// but the parser we have puts the `!default` flag on the values +// we need to lift it up to the declaration level + +export const explicitlyTagDefaultValues = (outer: any) => + withType(outer, (node: any) => { + const l = node.value?.length; + if (node?.type !== "value" || l < 2) { + return node; + } + if (node.value[l - 1]?.type !== "identifier" || + node.value[l - 1]?.value !== "default" || + node.value[l - 2]?.type !== "operator" || + node.value[l - 2]?.value !== "!") { + return node; + } + return { + ...node, + value: node.value.slice(0, -2), + isDefault: true, + }; + }); \ No newline at end of file diff --git a/tools/sass-variable-explainer/sass-analyzer/forward-annotations.ts b/tools/sass-variable-explainer/sass-analyzer/forward-annotations.ts new file mode 100644 index 00000000000..ae6ad584480 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/forward-annotations.ts @@ -0,0 +1,33 @@ +import { annotateNode } from './ast-utils.ts'; + +export const forwardAnnotations = (ast: any) => { + const pragmaAnnotation = "quarto-scss-analysis-annotation"; + const currentAnnotation: Record = {}; + let hasAnnotations: boolean = false + for (const node of ast.children) { + if (node.type === "comment_singleline") { + const value = node?.value?.trim(); + if (value.startsWith(pragmaAnnotation)) { + let payload: Record = {}; + try { + payload = JSON.parse(value.slice(pragmaAnnotation.length).trim()); + } catch (e) { + console.error("Could not parse annotation payload", e); + continue; + } + for (const [key, value] of Object.entries(payload)) { + if (value === null) { + delete currentAnnotation[key]; + } else { + currentAnnotation[key] = value; + } + } + hasAnnotations = Object.keys(currentAnnotation).length > 0; + } + } + if (node.type === "declaration" && hasAnnotations) { + annotateNode(node, currentAnnotation); + } + } + return ast; +} diff --git a/tools/sass-variable-explainer/sass-analyzer/get-dependencies.ts b/tools/sass-variable-explainer/sass-analyzer/get-dependencies.ts new file mode 100644 index 00000000000..7247937a5d5 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/get-dependencies.ts @@ -0,0 +1,36 @@ +import { walk } from "./ast-utils.ts"; +// import { assert } from "jsr:@std/assert"; + +const assert = (condition: any) => { + if (!condition) { + throw new Error("Assertion failed"); + } +} + +export const getVariableDependencies = (declarations: Map) => { + const dependencies = new Map + }>(); + for (const [name, node] of declarations) { + assert(node?.type === "declaration"); + const varName = node?.property?.variable?.value; + assert(varName === name); + if (!dependencies.has(varName)) { + dependencies.set(varName, {node: node, dependencies: new Set()}); + } + const varValue = node?.value; + walk(varValue, (inner: any) => { + if (inner?.type === "variable") { + const innerName = inner?.value; + if (!innerName) { + console.log(inner); + throw new Error("stop") + } + dependencies.get(varName)!.dependencies.add(innerName); + } + return true; + }); + } + return dependencies; +} \ No newline at end of file diff --git a/tools/sass-variable-explainer/sass-analyzer/group-arguments.ts b/tools/sass-variable-explainer/sass-analyzer/group-arguments.ts new file mode 100644 index 00000000000..108c0136f0c --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/group-arguments.ts @@ -0,0 +1,45 @@ +import { withType } from './ast-utils.ts'; + +// FIXME in SCSS, _declarations_ have a `!default` flag, not _values_ +// but the parser we have puts the `!default` flag on the values +// we need to lift it up to the declaration level + +export const groupArguments = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "function") { + return node; + } + const newArguments: any[] = []; + const newGroup = (): any => { + return { + type: "node_group", + start: node.start, // just so that simplifyLineInfo can handle it later + next: node.next, + children: [], + }; + } + let thisArgument = newGroup(); + const flushGroup = () => { + if (thisArgument.children.length > 1) { + newArguments.push(thisArgument); + } else { + newArguments.push(thisArgument.children[0]); + } + thisArgument = newGroup(); + } + if (node.children.length < 2) { + throw new Error("function node has no arguments"); + } + for (const arg of node.children[1].children) { + if (arg.type === "punctuation" && arg.value === ",") { + flushGroup(); + } else { + thisArgument.children.push(arg); + } + } + if (thisArgument.children.length > 0) { + flushGroup(); + } + node.children[1].children = newArguments; + return node; + }); diff --git a/tools/sass-variable-explainer/sass-analyzer/line-info.ts b/tools/sass-variable-explainer/sass-analyzer/line-info.ts new file mode 100644 index 00000000000..1af8936af98 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/line-info.ts @@ -0,0 +1,16 @@ +import { withType } from './ast-utils.ts'; + +export const simplifyLineInfo = (outer: any) => + withType(outer, (node: any) => { + const start = node?.start; + const next = node?.next; + + return { + ...node, + start: undefined, + next: undefined, + line: start?.line, + lineEnd: next?.line, + } + }); + diff --git a/tools/sass-variable-explainer/sass-analyzer/parse-web.ts b/tools/sass-variable-explainer/sass-analyzer/parse-web.ts new file mode 100644 index 00000000000..b35c26979ff --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/parse-web.ts @@ -0,0 +1,7 @@ +import { parse } from 'https://cdn.skypack.dev/scss-parser/'; +// seems impossible to get prettier to work in the browser +// import prettier from 'https://cdn.skypack.dev/prettier'; +// import * as prettier from "https://esm.sh/prettier@3.3.3"; // skypack crashes with prettier +import { makeParserModule } from "./parse.ts"; + +export const getSassAst = makeParserModule(parse, (s: string) => s).getSassAst; \ No newline at end of file diff --git a/tools/sass-variable-explainer/sass-analyzer/parse.ts b/tools/sass-variable-explainer/sass-analyzer/parse.ts new file mode 100644 index 00000000000..554826c8268 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/parse.ts @@ -0,0 +1,58 @@ +// our attempt at factoring out a clean parser +// that works in Deno and on the web + +import { walk } from "./ast-utils.ts"; + +export const makeParserModule = ( + parse: any, + prettierFormat: any +) => { + return { + getSassAst: async (contents: string) => { + // scss-parser doesn't support the `...` operator and it breaks their parser oO, so we remove it. + // our analysis doesn't need to know about it. + contents = contents.replaceAll("...", "_dot_dot_dot"); + // it also doesn't like some valid ways to do '@import url' + contents = contents.replaceAll("@import url", "//@import url"); + + // the scss-parser also apparently breaks on Quarto's SCSS unless it's + // been prettified first :shrug: + contents = await prettierFormat(contents, { parser: "scss" }); + + // Create an AST from a string of SCSS + // and convert it to a plain JSON object + const ast = JSON.parse(JSON.stringify(parse(contents))); + + if (!(ast.type === "stylesheet")) { + throw new Error("Expected AST to have type 'stylesheet'"); + }; + if (!Array.isArray(ast.value)) { + throw new Error("Expected AST to have an array value"); + } + + // rename 'value' to 'children' + // because they also use 'value' for the value of a property + + // this is the only place we'll use 'walk' instead of the + // more explicit 'mapDeep' and 'filterValuesDeep' functions + // below, which will then assume 'children' + + walk(ast, (node: any) => { + if (Array.isArray(node)) { + return true; + } + if (["value", "identifier", "operator"].includes(node?.type)) { + return true; + } + if (!node?.value || !Array.isArray(node.value)) { + return true; + } + node.children = node.value; + delete node.value; + return true; + }); + + return ast; + } + } +} diff --git a/tools/sass-variable-explainer/sass-analyzer/remove-nonsemantic-entries.ts b/tools/sass-variable-explainer/sass-analyzer/remove-nonsemantic-entries.ts new file mode 100644 index 00000000000..c11e63ee448 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/remove-nonsemantic-entries.ts @@ -0,0 +1,19 @@ +export const isRealContent = (v: any) => { + if (!v?.type) { + return true; + } + if (["space", "comment_singleline", "comment_multiline"].includes(v.type)) { + return false; + } + return true; +} + +export const isNotPunctuation = (v: any) => { + if (!v?.type) { + return true; + } + if (v.type === "punctuation") { + return false; + } + return true +} diff --git a/tools/sass-variable-explainer/sass-analyzer/sass-ui.qmd b/tools/sass-variable-explainer/sass-analyzer/sass-ui.qmd new file mode 100644 index 00000000000..ea08b0baf08 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/sass-ui.qmd @@ -0,0 +1,217 @@ +--- +title: SASS color variable explainer +theme: yeti +echo: false +--- + +```{ojs} +import { getSassAst } from "./parse-web.ts"; +import { cleanSassAst } from "./clean-ast.ts"; +import { propagateDeclarationTypes } from "./declaration-types.ts"; +import { getVariableDependencies } from "./get-dependencies.ts"; + +// https://observablehq.com/@observablehq/synchronized-inputs +function set(input, value) { + input.value = value; + input.dispatchEvent(new Event("input", {bubbles: true})); +} + +changeVarNameClickHandler = ((value) => { + return () => { + set(viewof varName, value) + return false; + }; +}); + +viewof sourceFile = Inputs.file({label: "SCSS file:"}) +source = { + if (sourceFile === null) { + return ` +$var1: #ff0000 !default; +$var2: darken($var1, 20%) !default; +`; + } else { + return sourceFile.text(); + } +} +matchAnnotation = x => x.match(/\/\/ quarto-scss-analysis-annotation (.*)/); +sourceLines = source.split("\n"); +colorValues = { + const result = new Map(); + try { + // ugly + const cssAnnotation = sourceLines.filter(matchAnnotation).pop(); + const matches = JSON.parse(matchAnnotation(cssAnnotation)[1])['css-vars']; + for (const match of matches) { + const [_, name, color] = match.match(/--quarto-scss-export-(.*): (.*)$/); + result.set(name, color.replace(/;$/, "")); + } + } catch (e) {} + return result; +} + +renderCssRect = (dep) => { + const span = document.createElement('span'); + span.style.position = 'relative'; + span.style.top = '-2px'; + span.style.zIndex = '-1000'; // makes this work well in Inputs.table + span.innerHTML = ``; + return span; +} + +deps = { + let ast = cleanSassAst(await getSassAst(source)); + ast = propagateDeclarationTypes(ast); + return getVariableDependencies(ast); +} + +selectedDependency = deps.get(varName) ?? (selectedItems.length === 1 ? deps.get(selectedItems[0][0]) : undefined) + +selectedDependencyChains = { + const dep = selectedDependency; + if (dep === undefined) { + return []; + } + const chains = []; + const buildChain = (dep, lst) => { + if (lst === undefined) { + lst = []; + } + if (dep === undefined) { return; } + const needsPush = dep.node?.valueType === 'color'; + if (needsPush) { + lst.push(dep.node.property.variable.value); + } + if (dep.dependencies.size === 0) { + chains.push([...lst]); + } else { + for (const subdep of dep.dependencies) { + buildChain(deps.get(subdep), lst); + } + } + if (needsPush) { + lst.pop(); + } + } + buildChain(dep); + return chains; +} +``` + +--- + +```{ojs} +selectedDependencyTitle = { + if (selectedDependency === undefined) { + return htl.html`
Select a single variable to analyze
`; + } else { + return htl.html`
Variable analysis for ${selectedDependency?.node?.property?.variable?.value ?? "unknown"}
`; + } +} +renderedAnalysis = { + deps; + debugger; + const result = htl.html`
`; + if (!selectedDependencyChains.length) { + return result; + } + + + if (selectedDependency?.node?.property?.variable?.value) { + const valueDiv = htl.html`
Value:
`; + valueDiv.appendChild(renderCssRect(selectedDependency?.node?.property?.variable?.value)); + result.appendChild(valueDiv); + } + + if (selectedDependency?.node?.annotation?.origin) { + result.appendChild(htl.html`
Origin: ${selectedDependency?.node?.annotation?.origin}
`); + } + + const lineEnd = Math.max( + selectedDependency?.node?.lineEnd ?? -Infinity, + selectedDependency?.node?.property?.lineEnd ?? -Infinity, + selectedDependency?.node?.value?.lineEnd ?? -Infinity, + ); + if (selectedDependency?.node?.line !== undefined && lineEnd !== -Infinity) { + result.appendChild(htl.html`
SCSS source
`); + const snippet = sourceLines.slice(selectedDependency?.node?.line - 1, lineEnd).join("\n"); + result.appendChild(htl.html`
${snippet}
`) + } + + + // Dependencies + result.appendChild(htl.html`
Dependencies:
`); + const depsDiv = htl.html`
`; + result.appendChild(depsDiv); + const seenDependencies = new Set([]); + const renderChain = (chain) => { + const result = htl.html`
`; + let i = 0; + for (let i = 0; i < chain.length; ++i) { + const element = chain[i]; + const opacity = seenDependencies.has(element) ? 0.2 : 1.0; + seenDependencies.add(element); + if (i > 0) { + result.appendChild(htl.html``); + } + const wrapperSpan = htl.html``; + wrapperSpan.appendChild(renderCssRect(element)); + const spanWithSpace = htl.html` `; + wrapperSpan.appendChild(spanWithSpace); + const link = htl.html`${element}` + link.onclick = changeVarNameClickHandler(element); + wrapperSpan.appendChild(link); + result.appendChild(wrapperSpan); + } + return result; + } + + let addedChains = false; + for (const chain of selectedDependencyChains) { + if (chain.length > 1) { + depsDiv.appendChild(renderChain(chain)); + addedChains = true; + } + } + if (!addedChains) { + depsDiv.appendChild(htl.html`None`); + } + return result; +} +``` + +--- + +```{ojs} +selectedItems = Array + .from(colorValues) + .filter(v => !varName.length ? true : v[0].includes(varName)) +viewof varName = Inputs.text({"label": "Name:"}); +colorValueTable = { + // const result = htl.html`
`; + // result.appendChild(htl.html`NameValue`); + // const body = htl.html``; + const items = selectedItems + .toSorted((a, b) => a[0].localeCompare(b[0])) + .map(v => { + const left = htl.html``; + left.appendChild(htl.html`${v[0]}`) + left.onclick = changeVarNameClickHandler(v[0]); + const right = htl.html``; + right.appendChild(renderCssRect(v[0])); + right.appendChild(htl.html` ${v[1]}`) + return { + name: left, + value: right + } + }); + return Inputs.table(items, { + format: { + name: (x) => x, + value: (x) => x + } + }); +} +``` + +${selectedItems.length} SCSS color variables found. diff --git a/tools/sass-variable-explainer/sass-analyzer/value-types.ts b/tools/sass-variable-explainer/sass-analyzer/value-types.ts new file mode 100644 index 00000000000..662574d6905 --- /dev/null +++ b/tools/sass-variable-explainer/sass-analyzer/value-types.ts @@ -0,0 +1,134 @@ +import { withType } from "./ast-utils.ts"; +import { namedColors, units } from "./css-information.ts"; + +const typedImmediateValues: Record = { + false: { type: "boolean", value: false }, + true: { type: "boolean", value: true }, + null: { type: "null", value: null }, +} + +export const fixImmediateTypes = (outer: any) => + withType(outer, (node: any) => { + if (node.type === "identifier" && typedImmediateValues[node.value]) { + return {...node, ...typedImmediateValues[node.value]}; + } + return node; + }); + +export const tagNamedColors = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "identifier" || !namedColors.has(node?.value)) { + return node; + } + return { + ...node, + type: "named_color", + }; + }); + +export const tagColorConstructors = (outer: any) => + withType(outer, (node: any) => { + if (node.type !== "function") { + return node; + } + const name = node.children[0].value; + if (node.children[0].type !== "identifier" || !name) { + return node; + } + const colorConstructors = new Set([ + "rgb", "rgba", "hsl", "hsla", + ]); + if (colorConstructors.has(name)) { + return { + ...node, + valueType: "color", + }; + } + return node; + }); + + // this also finds percentages +export const findDimensionValues = (outer: any) => + withType(outer, (node: any) => { + const replace = (value: any[]) => { + const newValues = []; + for (let i = 0; i < value.length; ++i) { + const thisValue = value[i]; + const nextValue = value[i + 1]; + if (thisValue?.type === "number" && + nextValue?.type === "identifier" && + units.has(nextValue?.value)) { + newValues.push({ + ...thisValue, + type: "dimension", + unit: nextValue.value, + }); + ++i; + } else if (thisValue?.type === "number" && + nextValue?.type === "operator" && + nextValue?.value === "%") { + // this might be chancy if there's stuff like (3 % 2) floating around + // I couldn't find any in our .scss files, but :grimace: + newValues.push({ + ...thisValue, + type: "percentage", + }); + ++i; + } else { + newValues.push(thisValue); + } + } + return newValues; + } + if (node.type === "value" && Array.isArray(node.value)) { + return { + ...node, + value: replace(node.value), + }; + } + if (node.type === "node_group") { + return { + ...node, + children: replace(node.children), + } + } + return node; + // if (node?.type !== "value") { + // return node; + // } + // const value = node?.value; + // if (!Array.isArray(value)) { + // return node; + // } + // const newValues = []; + // for (let i = 0; i < value.length; ++i) { + // const thisValue = value[i]; + // const nextValue = value[i + 1]; + // if (thisValue?.type === "number" && + // nextValue?.type === "identifier" && + // units.has(nextValue?.value)) { + // newValues.push({ + // ...thisValue, + // type: "dimension", + // unit: nextValue.value, + // }); + // ++i; + // } else if (thisValue?.type === "number" && + // nextValue?.type === "operator" && + // nextValue?.value === "%") { + // // this might be chancy if there's stuff like (3 % 2) floating around + // // I couldn't find any in our .scss files, but :grimace: + // newValues.push({ + // ...thisValue, + // type: "percentage", + // }); + // ++i; + // } else { + // newValues.push(thisValue); + // } + // } + // return { + // ...node, + // value: newValues, + // }; + }); diff --git a/tools/sass-variable-explainer/walk.ts b/tools/sass-variable-explainer/walk.ts new file mode 100644 index 00000000000..e69de29bb2d