UNPKG

@stencil/core

Version:

A Compiler for Web Components and Progressive Web Apps

1 lines • 290 kB
{"version":3,"file":"index.cjs","sources":["../src/utils/constants.ts","../src/utils/helpers.ts","../src/utils/message-utils.ts","../src/utils/path.ts","../src/utils/output-target.ts","../src/utils/result.ts","../src/utils/util.ts","../src/utils/validation.ts","../src/declarations/stencil-public-compiler.ts","../src/cli/config-flags.ts","../src/cli/parse-flags.ts","../src/cli/find-config.ts","../src/cli/load-compiler.ts","../src/cli/logs.ts","../src/cli/check-version.ts","../src/cli/task-prerender.ts","../src/cli/task-watch.ts","../src/cli/telemetry/helpers.ts","../src/cli/ionic-config.ts","../src/cli/telemetry/shouldTrack.ts","../src/cli/telemetry/telemetry.ts","../src/cli/task-build.ts","../src/cli/task-docs.ts","../src/cli/task-generate.ts","../src/cli/task-telemetry.ts","../src/cli/task-help.ts","../src/cli/task-info.ts","../src/cli/task-serve.ts","../src/cli/task-test.ts","../src/cli/run.ts"],"sourcesContent":["export const enum MEMBER_FLAGS {\n String = 1 << 0,\n Number = 1 << 1,\n Boolean = 1 << 2,\n Any = 1 << 3,\n Unknown = 1 << 4,\n\n State = 1 << 5,\n Method = 1 << 6,\n Event = 1 << 7,\n Element = 1 << 8,\n\n ReflectAttr = 1 << 9,\n Mutable = 1 << 10,\n\n Prop = String | Number | Boolean | Any | Unknown,\n HasAttribute = String | Number | Boolean | Any,\n PropLike = Prop | State,\n}\n\nexport const enum EVENT_FLAGS {\n Cancellable = 1 << 0,\n Composed = 1 << 1,\n Bubbles = 1 << 2,\n}\n\nexport const enum LISTENER_FLAGS {\n Passive = 1 << 0,\n Capture = 1 << 1,\n\n TargetDocument = 1 << 2,\n TargetWindow = 1 << 3,\n TargetBody = 1 << 4,\n\n /**\n * @deprecated Prevented from new apps, but left in for older collections\n */\n TargetParent = 1 << 5,\n}\n\nexport const enum HOST_FLAGS {\n hasConnected = 1 << 0,\n hasRendered = 1 << 1,\n isWaitingForChildren = 1 << 2,\n isConstructingInstance = 1 << 3,\n isQueuedForUpdate = 1 << 4,\n hasInitializedComponent = 1 << 5,\n hasLoadedComponent = 1 << 6,\n isWatchReady = 1 << 7,\n isListenReady = 1 << 8,\n needsRerender = 1 << 9,\n\n // DEV ONLY\n devOnRender = 1 << 10,\n devOnDidLoad = 1 << 11,\n}\n\n/**\n * A set of flags used for bitwise calculations against {@link ComponentRuntimeMeta#$flags$}.\n *\n * These flags should only be used in conjunction with {@link ComponentRuntimeMeta#$flags$}.\n * They should _not_ be used for calculations against other fields/numbers\n */\nexport const enum CMP_FLAGS {\n /**\n * Used to determine if a component is using the shadow DOM.\n * e.g. `shadow: true | {}` is set on the `@Component()` decorator\n */\n shadowDomEncapsulation = 1 << 0,\n /**\n * Used to determine if a component is using scoped stylesheets\n * e.g. `scoped: true` is set on the `@Component()` decorator\n */\n scopedCssEncapsulation = 1 << 1,\n /**\n * Used to determine if a component does not use the shadow DOM _and_ has `<slot/>` tags in its markup.\n */\n hasSlotRelocation = 1 << 2,\n // TODO(STENCIL-854): Remove code related to legacy shadowDomShim field\n // Note that when we remove this field we should consider whether we need to\n // retain a placeholder here, since if we want to have compatibility between\n // different versions of the runtime then we'll need to not shift the values\n // of the other higher flags down\n /**\n * Determines if a shim for the shadow DOM is necessary.\n *\n * The shim should only be needed if a component requires {@link shadowDomEncapsulation} and if any output\n * target-specific criteria are met. Refer to this flag's usage to determine each output target's criteria.\n */\n needsShadowDomShim = 1 << 3,\n /**\n * Determines if `delegatesFocus` is enabled for a component that uses the shadow DOM.\n * e.g. `shadow: { delegatesFocus: true }` is set on the `@Component()` decorator\n */\n shadowDelegatesFocus = 1 << 4,\n /**\n * Determines if `mode` is set on the `@Component()` decorator\n */\n hasMode = 1 << 5,\n // TODO(STENCIL-854): Remove code related to legacy shadowDomShim field\n /**\n * Determines if styles must be scoped due to either:\n * 1. A component is using scoped stylesheets ({@link scopedCssEncapsulation})\n * 2. A component is using the shadow DOM _and_ the output target's rules for requiring a shadow DOM shim have been\n * met ({@link needsShadowDomShim})\n */\n needsScopedEncapsulation = scopedCssEncapsulation | needsShadowDomShim,\n}\n\n/**\n * Default style mode id\n */\nexport const DEFAULT_STYLE_MODE = '$';\n\n/**\n * Reusable empty obj/array\n * Don't add values to these!!\n */\nexport const EMPTY_OBJ: any = {};\n\n/**\n * Namespaces\n */\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const HTML_NS = 'http://www.w3.org/1999/xhtml';\nexport const XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/**\n * File names and value\n */\nexport const COLLECTION_MANIFEST_FILE_NAME = 'collection-manifest.json';\n\n/**\n * Constant for the 'copy' output target\n */\nexport const COPY = 'copy';\n/**\n * Constant for the 'custom' output target\n */\nexport const CUSTOM = 'custom';\n/**\n * Constant for the 'dist' output target\n */\nexport const DIST = 'dist';\n/**\n * Constant for the 'dist-collection' output target\n */\nexport const DIST_COLLECTION = 'dist-collection';\n/**\n * Constant for the 'dist-custom-elements' output target\n */\nexport const DIST_CUSTOM_ELEMENTS = 'dist-custom-elements';\n\n/**\n * Constant for the 'dist-types' output target\n */\nexport const DIST_TYPES = 'dist-types';\n/**\n * Constant for the 'dist-hydrate-script' output target\n */\nexport const DIST_HYDRATE_SCRIPT = 'dist-hydrate-script';\n/**\n * Constant for the 'dist-lazy' output target\n */\nexport const DIST_LAZY = 'dist-lazy';\n/**\n * Constant for the 'dist-lazy-loader' output target\n */\nexport const DIST_LAZY_LOADER = 'dist-lazy-loader';\n/**\n * Constant for the 'dist-global-styles' output target\n */\nexport const DIST_GLOBAL_STYLES = 'dist-global-styles';\n/**\n * Constant for the 'docs-custom' output target\n */\nexport const DOCS_CUSTOM = 'docs-custom';\n/**\n * Constant for the 'docs-json' output target\n */\nexport const DOCS_JSON = 'docs-json';\n/**\n * Constant for the 'docs-readme' output target\n */\nexport const DOCS_README = 'docs-readme';\n/**\n * Constant for the 'docs-vscode' output target\n */\nexport const DOCS_VSCODE = 'docs-vscode';\n/**\n * Constant for the 'stats' output target\n */\nexport const STATS = 'stats';\n/**\n * Constant for the 'www' output target\n */\nexport const WWW = 'www';\n\n/**\n * Valid output targets to specify in a Stencil config.\n *\n * Note that there are some output targets (e.g. `DIST_TYPES`) which are\n * programmatically set as output targets by the compiler when other output\n * targets (in that case `DIST`) are set, but which are _not_ supported in a\n * Stencil config. This is enforced in the output target validation code.\n */\nexport const VALID_CONFIG_OUTPUT_TARGETS = [\n // DIST\n WWW,\n DIST,\n DIST_COLLECTION,\n DIST_CUSTOM_ELEMENTS,\n DIST_LAZY,\n DIST_HYDRATE_SCRIPT,\n\n // DOCS\n DOCS_JSON,\n DOCS_README,\n DOCS_VSCODE,\n DOCS_CUSTOM,\n\n // MISC\n COPY,\n CUSTOM,\n STATS,\n] as const;\n\nexport const GENERATED_DTS = 'components.d.ts';\n","export const isDef = (v: any) => v != null;\n\n/**\n * Convert a string from PascalCase to dash-case\n *\n * @param str the string to convert\n * @returns a converted string\n */\nexport const toDashCase = (str: string): string =>\n str\n .replace(/([A-Z0-9])/g, (match) => ` ${match[0]}`)\n .trim()\n .split(' ')\n .join('-')\n .toLowerCase();\n\n/**\n * Convert a string from dash-case / kebab-case to PascalCase (or CamelCase,\n * or whatever you call it!)\n *\n * @param str a string to convert\n * @returns a converted string\n */\nexport const dashToPascalCase = (str: string): string =>\n str\n .toLowerCase()\n .split('-')\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n/**\n * Convert a string to 'camelCase'\n *\n * @param str the string to convert\n * @returns the converted string\n */\nexport const toCamelCase = (str: string) => {\n const pascalCase = dashToPascalCase(str);\n return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);\n};\n\n/**\n * Capitalize the first letter of a string\n *\n * @param str the string to capitalize\n * @returns a capitalized string\n */\nexport const toTitleCase = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1);\n\n/**\n * This is just a no-op, don't expect it to do anything.\n */\nexport const noop = (): any => {\n /* noop*/\n};\n\n/**\n * Check whether a value is a 'complex type', defined here as an object or a\n * function.\n *\n * @param o the value to check\n * @returns whether it's a complex type or not\n */\nexport const isComplexType = (o: unknown): boolean => {\n // https://jsperf.com/typeof-fn-object/5\n o = typeof o;\n return o === 'object' || o === 'function';\n};\n\n/**\n * Sort an array without mutating it in-place (as `Array.prototype.sort`\n * unfortunately does)\n *\n * @param array the array you'd like to sort\n * @param prop a function for deriving sortable values (strings or numbers)\n * from array members\n * @returns a new array of all items `x` in `array` ordered by `prop(x)`\n */\nexport const sortBy = <T>(array: T[], prop: (item: T) => string | number): T[] => {\n return array.slice().sort((a, b) => {\n const nameA = prop(a);\n const nameB = prop(b);\n if (nameA < nameB) return -1;\n if (nameA > nameB) return 1;\n return 0;\n });\n};\n\n/**\n * A polyfill of sorts for `Array.prototype.flat` which will return the result\n * of calling that method if present and, if not, return an equivalent based on\n * `Array.prototype.reduce`.\n *\n * @param array the array to flatten (one level)\n * @returns a flattened array\n */\nexport const flatOne = <T>(array: T[][]): T[] => {\n if (array.flat) {\n return array.flat(1);\n }\n return array.reduce((result, item) => {\n result.push(...item);\n return result;\n }, [] as T[]);\n};\n\n/**\n * Deduplicate an array, retaining items at the earliest position in which\n * they appear.\n *\n * So `unique([1,3,2,1,1,4])` would be `[1,3,2,4]`.\n *\n * @param array the array to deduplicate\n * @param predicate an optional function used to generate the key used to\n * determine uniqueness\n * @returns a new, deduplicated array\n */\nexport const unique = <T, K>(array: T[], predicate: (item: T) => K = (i) => i as any): T[] => {\n const set = new Set();\n return array.filter((item) => {\n const key = predicate(item);\n if (key == null) {\n return true;\n }\n if (set.has(key)) {\n return false;\n }\n set.add(key);\n return true;\n });\n};\n\n/**\n * A utility for building an object from an iterable very similar to\n * `Object.fromEntries`\n *\n * @param entries an iterable object holding entries (key-value tuples) to\n * plop into a new object\n * @returns an object containing those entries\n */\nexport const fromEntries = <V>(entries: IterableIterator<[string, V]>) => {\n const object: Record<string, V> = {};\n for (const [key, value] of entries) {\n object[key] = value;\n }\n return object;\n};\n\n/**\n * Based on a given object, create a new object which has only the specified\n * key-value pairs included in it.\n *\n * @param obj the object from which to take values\n * @param keys a set of keys to take\n * @returns an object mapping `key` to `obj[key]` if `obj[key]` is truthy for\n * every `key` in `keys`\n */\nexport const pluck = (obj: { [key: string]: any }, keys: string[]) => {\n return keys.reduce(\n (final, key) => {\n if (obj[key]) {\n final[key] = obj[key];\n }\n return final;\n },\n {} as { [key: string]: any },\n );\n};\n\nconst isDefined = (v: any): v is NonNullable<typeof v> => v !== null && v !== undefined;\nexport const isBoolean = (v: any): v is boolean => typeof v === 'boolean';\nexport const isFunction = (v: any): v is Function => typeof v === 'function';\nexport const isNumber = (v: any): v is number => typeof v === 'number';\nexport const isObject = (val: Object): val is Object =>\n val != null && typeof val === 'object' && Array.isArray(val) === false;\nexport const isString = (v: any): v is string => typeof v === 'string';\nexport const isIterable = <T>(v: any): v is Iterable<T> => isDefined(v) && isFunction(v[Symbol.iterator]);\nexport const isPromise = <T = any>(v: any): v is Promise<T> =>\n !!v && (typeof v === 'object' || typeof v === 'function') && typeof v.then === 'function';\n","import type * as d from '../declarations';\nimport { isString } from './helpers';\n\n/**\n * Builds a template `Diagnostic` entity for a build error. The created `Diagnostic` is returned, and have little\n * detail attached to it regarding the specifics of the error - it is the responsibility of the caller of this method\n * to attach the specifics of the error message.\n *\n * The created `Diagnostic` is pushed to the `diagnostics` argument as a side effect of calling this method.\n *\n * @param diagnostics the existing diagnostics that the created template `Diagnostic` should be added to\n * @returns the created `Diagnostic`\n */\nexport const buildError = (diagnostics?: d.Diagnostic[]): d.Diagnostic => {\n const diagnostic: d.Diagnostic = {\n level: 'error',\n type: 'build',\n header: 'Build Error',\n messageText: 'build error',\n relFilePath: undefined,\n absFilePath: undefined,\n lines: [],\n };\n\n if (diagnostics) {\n diagnostics.push(diagnostic);\n }\n\n return diagnostic;\n};\n\n/**\n * Builds a template `Diagnostic` entity for a build warning. The created `Diagnostic` is returned, and have little\n * detail attached to it regarding the specifics of the warning - it is the responsibility of the caller of this method\n * to attach the specifics of the warning message.\n *\n * The created `Diagnostic` is pushed to the `diagnostics` argument as a side effect of calling this method.\n *\n * @param diagnostics the existing diagnostics that the created template `Diagnostic` should be added to\n * @returns the created `Diagnostic`\n */\nexport const buildWarn = (diagnostics: d.Diagnostic[]): d.Diagnostic => {\n const diagnostic: d.Diagnostic = {\n level: 'warn',\n type: 'build',\n header: 'Build Warn',\n messageText: 'build warn',\n lines: [],\n };\n\n diagnostics.push(diagnostic);\n\n return diagnostic;\n};\n\n/**\n * Create a diagnostic message suited for representing an error in a JSON\n * file. This includes information about the exact lines in the JSON file which\n * caused the error and the path to the file.\n *\n * @param compilerCtx the current compiler context\n * @param diagnostics a list of diagnostics used as a return param\n * @param jsonFilePath the path to the JSON file where the error occurred\n * @param msg the error message\n * @param jsonField the key for the field which caused the error, used for finding\n * the error line in the original JSON file\n * @returns a reference to the newly-created diagnostic\n */\nexport const buildJsonFileError = (\n compilerCtx: d.CompilerCtx,\n diagnostics: d.Diagnostic[],\n jsonFilePath: string,\n msg: string,\n jsonField: string,\n) => {\n const err = buildError(diagnostics);\n err.messageText = msg;\n err.absFilePath = jsonFilePath;\n\n if (typeof jsonField === 'string') {\n try {\n const jsonStr = compilerCtx.fs.readFileSync(jsonFilePath);\n const lines = jsonStr.replace(/\\r/g, '\\n').split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const txtLine = lines[i];\n const txtIndex = txtLine.indexOf(jsonField);\n\n if (txtIndex > -1) {\n const warnLine: d.PrintLine = {\n lineIndex: i,\n lineNumber: i + 1,\n text: txtLine,\n errorCharStart: txtIndex,\n errorLength: jsonField.length,\n };\n err.lineNumber = warnLine.lineNumber;\n err.columnNumber = txtIndex + 1;\n err.lines.push(warnLine);\n\n if (i >= 0) {\n const beforeWarnLine: d.PrintLine = {\n lineIndex: warnLine.lineIndex - 1,\n lineNumber: warnLine.lineNumber - 1,\n text: lines[i - 1],\n errorCharStart: -1,\n errorLength: -1,\n };\n err.lines.unshift(beforeWarnLine);\n }\n\n if (i < lines.length) {\n const afterWarnLine: d.PrintLine = {\n lineIndex: warnLine.lineIndex + 1,\n lineNumber: warnLine.lineNumber + 1,\n text: lines[i + 1],\n errorCharStart: -1,\n errorLength: -1,\n };\n err.lines.push(afterWarnLine);\n }\n\n break;\n }\n }\n } catch (e) {}\n }\n\n return err;\n};\n\n/**\n * Builds a diagnostic from an `Error`, appends it to the `diagnostics` parameter, and returns the created diagnostic\n * @param diagnostics the series of diagnostics the newly created diagnostics should be added to\n * @param err the error to derive information from in generating the diagnostic\n * @param msg an optional message to use in place of `err` to generate the diagnostic\n * @returns the generated diagnostic\n */\nexport const catchError = (diagnostics: d.Diagnostic[], err: Error | null | undefined, msg?: string): d.Diagnostic => {\n const diagnostic: d.Diagnostic = {\n level: 'error',\n type: 'build',\n header: 'Build Error',\n messageText: 'build error',\n lines: [],\n };\n\n if (isString(msg)) {\n diagnostic.messageText = msg.length ? msg : 'UNKNOWN ERROR';\n } else if (err != null) {\n if (err.stack != null) {\n diagnostic.messageText = err.stack.toString();\n } else {\n if (err.message != null) {\n diagnostic.messageText = err.message.length ? err.message : 'UNKNOWN ERROR';\n } else {\n diagnostic.messageText = err.toString();\n }\n }\n }\n\n if (diagnostics != null && !shouldIgnoreError(diagnostic.messageText)) {\n diagnostics.push(diagnostic);\n }\n\n return diagnostic;\n};\n\n/**\n * Determine if the provided diagnostics have any build errors\n * @param diagnostics the diagnostics to inspect\n * @returns true if any of the diagnostics in the list provided are errors that did not occur at runtime. false\n * otherwise.\n */\nexport const hasError = (diagnostics: d.Diagnostic[]): boolean => {\n if (diagnostics == null || diagnostics.length === 0) {\n return false;\n }\n return diagnostics.some((d) => d.level === 'error' && d.type !== 'runtime');\n};\n\n/**\n * Determine if the provided diagnostics have any warnings\n * @param diagnostics the diagnostics to inspect\n * @returns true if any of the diagnostics in the list provided are warnings. false otherwise.\n */\nexport const hasWarning = (diagnostics: d.Diagnostic[]): boolean => {\n if (diagnostics == null || diagnostics.length === 0) {\n return false;\n }\n return diagnostics.some((d) => d.level === 'warn');\n};\n\nexport const shouldIgnoreError = (msg: any) => {\n return msg === TASK_CANCELED_MSG;\n};\n\nexport const TASK_CANCELED_MSG = `task canceled`;\n","import path from 'path';\n\n/**\n * Convert Windows backslash paths to slash paths: foo\\\\bar ➔ foo/bar\n * Forward-slash paths can be used in Windows as long as they're not\n * extended-length paths and don't contain any non-ascii characters.\n * This was created since the path methods in Node.js outputs \\\\ paths on Windows.\n * @param path the Windows-based path to convert\n * @param relativize whether or not a relative path should have `./` prepended\n * @returns the converted path\n */\nexport const normalizePath = (path: string, relativize = true): string => {\n if (typeof path !== 'string') {\n throw new Error(`invalid path to normalize`);\n }\n path = normalizeSlashes(path.trim());\n\n const components = pathComponents(path, getRootLength(path));\n const reducedComponents = reducePathComponents(components);\n const rootPart = reducedComponents[0];\n const secondPart = reducedComponents[1];\n const normalized = rootPart + reducedComponents.slice(1).join('/');\n\n if (normalized === '') {\n return '.';\n }\n if (\n rootPart === '' &&\n secondPart &&\n path.includes('/') &&\n !secondPart.startsWith('.') &&\n !secondPart.startsWith('@') &&\n relativize\n ) {\n return './' + normalized;\n }\n return normalized;\n};\n\nconst normalizeSlashes = (path: string) => path.replace(backslashRegExp, '/');\n\nconst altDirectorySeparator = '\\\\';\nconst urlSchemeSeparator = '://';\nconst backslashRegExp = /\\\\/g;\n\nconst reducePathComponents = (components: readonly string[]) => {\n if (!Array.isArray(components) || components.length === 0) {\n return [];\n }\n const reduced = [components[0]];\n for (let i = 1; i < components.length; i++) {\n const component = components[i];\n if (!component) continue;\n if (component === '.') continue;\n if (component === '..') {\n if (reduced.length > 1) {\n if (reduced[reduced.length - 1] !== '..') {\n reduced.pop();\n continue;\n }\n } else if (reduced[0]) continue;\n }\n reduced.push(component);\n }\n return reduced;\n};\n\nconst getRootLength = (path: string) => {\n const rootLength = getEncodedRootLength(path);\n return rootLength < 0 ? ~rootLength : rootLength;\n};\n\nconst getEncodedRootLength = (path: string): number => {\n if (!path) return 0;\n const ch0 = path.charCodeAt(0);\n\n // POSIX or UNC\n if (ch0 === CharacterCodes.slash || ch0 === CharacterCodes.backslash) {\n if (path.charCodeAt(1) !== ch0) return 1; // POSIX: \"/\" (or non-normalized \"\\\")\n\n const p1 = path.indexOf(ch0 === CharacterCodes.slash ? '/' : altDirectorySeparator, 2);\n if (p1 < 0) return path.length; // UNC: \"//server\" or \"\\\\server\"\n\n return p1 + 1; // UNC: \"//server/\" or \"\\\\server\\\"\n }\n\n // DOS\n if (isVolumeCharacter(ch0) && path.charCodeAt(1) === CharacterCodes.colon) {\n const ch2 = path.charCodeAt(2);\n if (ch2 === CharacterCodes.slash || ch2 === CharacterCodes.backslash) return 3; // DOS: \"c:/\" or \"c:\\\"\n if (path.length === 2) return 2; // DOS: \"c:\" (but not \"c:d\")\n }\n\n // URL\n const schemeEnd = path.indexOf(urlSchemeSeparator);\n if (schemeEnd !== -1) {\n const authorityStart = schemeEnd + urlSchemeSeparator.length;\n const authorityEnd = path.indexOf('/', authorityStart);\n if (authorityEnd !== -1) {\n // URL: \"file:///\", \"file://server/\", \"file://server/path\"\n // For local \"file\" URLs, include the leading DOS volume (if present).\n // Per https://www.ietf.org/rfc/rfc1738.txt, a host of \"\" or \"localhost\" is a\n // special case interpreted as \"the machine from which the URL is being interpreted\".\n const scheme = path.slice(0, schemeEnd);\n const authority = path.slice(authorityStart, authorityEnd);\n if (\n scheme === 'file' &&\n (authority === '' || authority === 'localhost') &&\n isVolumeCharacter(path.charCodeAt(authorityEnd + 1))\n ) {\n const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);\n if (volumeSeparatorEnd !== -1) {\n if (path.charCodeAt(volumeSeparatorEnd) === CharacterCodes.slash) {\n // URL: \"file:///c:/\", \"file://localhost/c:/\", \"file:///c%3a/\", \"file://localhost/c%3a/\"\n return ~(volumeSeparatorEnd + 1);\n }\n if (volumeSeparatorEnd === path.length) {\n // URL: \"file:///c:\", \"file://localhost/c:\", \"file:///c$3a\", \"file://localhost/c%3a\"\n // but not \"file:///c:d\" or \"file:///c%3ad\"\n return ~volumeSeparatorEnd;\n }\n }\n }\n return ~(authorityEnd + 1); // URL: \"file://server/\", \"http://server/\"\n }\n return ~path.length; // URL: \"file://server\", \"http://server\"\n }\n\n // relative\n return 0;\n};\n\nconst isVolumeCharacter = (charCode: number) =>\n (charCode >= CharacterCodes.a && charCode <= CharacterCodes.z) ||\n (charCode >= CharacterCodes.A && charCode <= CharacterCodes.Z);\n\nconst getFileUrlVolumeSeparatorEnd = (url: string, start: number) => {\n const ch0 = url.charCodeAt(start);\n if (ch0 === CharacterCodes.colon) return start + 1;\n if (ch0 === CharacterCodes.percent && url.charCodeAt(start + 1) === CharacterCodes._3) {\n const ch2 = url.charCodeAt(start + 2);\n if (ch2 === CharacterCodes.a || ch2 === CharacterCodes.A) return start + 3;\n }\n return -1;\n};\n\nconst pathComponents = (path: string, rootLength: number) => {\n const root = path.substring(0, rootLength);\n const rest = path.substring(rootLength).split('/');\n const restLen = rest.length;\n if (restLen > 0 && !rest[restLen - 1]) {\n rest.pop();\n }\n return [root, ...rest];\n};\n\n/**\n * Same as normalizePath(), expect it'll also strip any query strings\n * from the path name. So /dir/file.css?tag=cmp-a becomes /dir/file.css\n * @param p the path to normalize\n * @returns the normalized path, sans any query strings\n */\nexport const normalizeFsPath = (p: string) => normalizePath(p.split('?')[0].replace(/\\0/g, ''));\n\nexport const normalizeFsPathQuery = (importPath: string) => {\n const pathParts = importPath.split('?');\n const filePath = normalizePath(pathParts[0]);\n const ext = filePath.split('.').pop().toLowerCase();\n const params = pathParts.length > 1 ? new URLSearchParams(pathParts[1]) : null;\n const format = params ? params.get('format') : null;\n\n return {\n filePath,\n ext,\n format,\n };\n};\n\nconst enum CharacterCodes {\n a = 0x61,\n A = 0x41,\n z = 0x7a,\n Z = 0x5a,\n _3 = 0x33,\n\n backslash = 0x5c, // \\\n colon = 0x3a, // :\n dot = 0x2e, // .\n percent = 0x25, // %\n slash = 0x2f, // /\n}\n\n/**\n * A wrapped version of node.js' {@link path.relative} which adds our custom\n * normalization logic. This solves the relative path between `from` and `to`!\n *\n * @throws the underlying node.js function can throw if either path is not a\n * string\n * @param from the path where relative resolution starts\n * @param to the destination path\n * @returns the resolved relative path\n */\nexport function relative(from: string, to: string): string {\n return normalizePath(path.relative(from, to), false);\n}\n\n/**\n * A wrapped version of node.js' {@link path.join} which adds our custom\n * normalization logic. This joins all the arguments (path fragments) into a\n * single path.\n *\n * @throws the underlying node function will throw if any argument is not a\n * string\n * @param paths the paths to join together\n * @returns a joined path!\n */\nexport function join(...paths: string[]): string {\n return normalizePath(path.join(...paths), false);\n}\n","import { flatOne, normalizePath, sortBy } from '@utils';\nimport { basename, dirname, join, relative } from 'path';\n\nimport type * as d from '../declarations';\nimport {\n COPY,\n CUSTOM,\n DIST,\n DIST_COLLECTION,\n DIST_CUSTOM_ELEMENTS,\n DIST_GLOBAL_STYLES,\n DIST_HYDRATE_SCRIPT,\n DIST_LAZY,\n DIST_LAZY_LOADER,\n DIST_TYPES,\n DOCS_CUSTOM,\n DOCS_JSON,\n DOCS_README,\n DOCS_VSCODE,\n GENERATED_DTS,\n STATS,\n VALID_CONFIG_OUTPUT_TARGETS,\n WWW,\n} from './constants';\n\nexport const relativeImport = (pathFrom: string, pathTo: string, ext?: string, addPrefix = true) => {\n let relativePath = relative(dirname(pathFrom), dirname(pathTo));\n if (addPrefix) {\n if (relativePath === '') {\n relativePath = '.';\n } else if (relativePath[0] !== '.') {\n relativePath = './' + relativePath;\n }\n }\n return normalizePath(`${relativePath}/${basename(pathTo, ext)}`);\n};\n\nexport const getComponentsDtsSrcFilePath = (config: d.ValidatedConfig) => join(config.srcDir, GENERATED_DTS);\n\nexport const getComponentsDtsTypesFilePath = (outputTarget: d.OutputTargetDist | d.OutputTargetDistTypes) =>\n join(outputTarget.typesDir, GENERATED_DTS);\n\nexport const isOutputTargetDist = (o: d.OutputTarget): o is d.OutputTargetDist => o.type === DIST;\n\nexport const isOutputTargetDistCollection = (o: d.OutputTarget): o is d.OutputTargetDistCollection =>\n o.type === DIST_COLLECTION;\n\nexport const isOutputTargetDistCustomElements = (o: d.OutputTarget): o is d.OutputTargetDistCustomElements =>\n o.type === DIST_CUSTOM_ELEMENTS;\n\nexport const isOutputTargetCopy = (o: d.OutputTarget): o is d.OutputTargetCopy => o.type === COPY;\n\nexport const isOutputTargetDistLazy = (o: d.OutputTarget): o is d.OutputTargetDistLazy => o.type === DIST_LAZY;\n\nexport const isOutputTargetDistLazyLoader = (o: d.OutputTarget): o is d.OutputTargetDistLazyLoader =>\n o.type === DIST_LAZY_LOADER;\n\nexport const isOutputTargetDistGlobalStyles = (o: d.OutputTarget): o is d.OutputTargetDistGlobalStyles =>\n o.type === DIST_GLOBAL_STYLES;\n\nexport const isOutputTargetHydrate = (o: d.OutputTarget): o is d.OutputTargetHydrate => o.type === DIST_HYDRATE_SCRIPT;\n\nexport const isOutputTargetCustom = (o: d.OutputTarget): o is d.OutputTargetCustom => o.type === CUSTOM;\n\nexport const isOutputTargetDocs = (\n o: d.OutputTarget,\n): o is d.OutputTargetDocsJson | d.OutputTargetDocsReadme | d.OutputTargetDocsVscode | d.OutputTargetDocsCustom =>\n o.type === DOCS_README || o.type === DOCS_JSON || o.type === DOCS_CUSTOM || o.type === DOCS_VSCODE;\n\nexport const isOutputTargetDocsReadme = (o: d.OutputTarget): o is d.OutputTargetDocsReadme => o.type === DOCS_README;\n\nexport const isOutputTargetDocsJson = (o: d.OutputTarget): o is d.OutputTargetDocsJson => o.type === DOCS_JSON;\n\nexport const isOutputTargetDocsCustom = (o: d.OutputTarget): o is d.OutputTargetDocsCustom => o.type === DOCS_CUSTOM;\n\nexport const isOutputTargetDocsVscode = (o: d.OutputTarget): o is d.OutputTargetDocsVscode => o.type === DOCS_VSCODE;\n\nexport const isOutputTargetWww = (o: d.OutputTarget): o is d.OutputTargetWww => o.type === WWW;\n\nexport const isOutputTargetStats = (o: d.OutputTarget): o is d.OutputTargetStats => o.type === STATS;\n\nexport const isOutputTargetDistTypes = (o: d.OutputTarget): o is d.OutputTargetDistTypes => o.type === DIST_TYPES;\n\n/**\n * Checks whether or not the supplied output target's type matches one of the eligible primary\n * package output target types (i.e. it can have `isPrimaryPackageOutputTarget: true` in its config).\n *\n * @param o The output target to check.\n * @returns Whether the output target type is one of the \"primary\" output targets.\n */\nexport const isEligiblePrimaryPackageOutputTarget = (o: d.OutputTarget): o is d.EligiblePrimaryPackageOutputTarget =>\n isOutputTargetDist(o) ||\n isOutputTargetDistCollection(o) ||\n isOutputTargetDistCustomElements(o) ||\n isOutputTargetDistTypes(o);\n\n/**\n * Retrieve the Stencil component compiler metadata from a collection of Stencil {@link Module}s\n * @param moduleFiles the collection of `Module`s to retrieve the metadata from\n * @returns the metadata, lexicographically sorted by the tag names of the components\n */\nexport const getComponentsFromModules = (moduleFiles: d.Module[]): d.ComponentCompilerMeta[] =>\n sortBy(flatOne(moduleFiles.map((m) => m.cmps)), (c: d.ComponentCompilerMeta) => c.tagName);\n\n// Given a ReadonlyArray of strings we can derive a union type from them\n// by getting `typeof ARRAY[number]`, i.e. the type of all values returns\n// by number keys.\ntype ValidConfigOutputTarget = (typeof VALID_CONFIG_OUTPUT_TARGETS)[number];\n\n/**\n * Check whether a given output target is a valid one to be set in a Stencil config\n *\n * @param targetType the type which we want to check\n * @returns whether or not the targetType is a valid, configurable output target.\n */\nexport function isValidConfigOutputTarget(targetType: string): targetType is ValidConfigOutputTarget {\n // unfortunately `includes` is typed on `ReadonlyArray<T>` as `(el: T):\n // boolean` so a `string` cannot be passed to `includes` on a\n // `ReadonlyArray` 😢 thus we `as any`\n //\n // see microsoft/TypeScript#31018 for some discussion of this\n return VALID_CONFIG_OUTPUT_TARGETS.includes(targetType as any);\n}\n","/**\n * A Result wraps up a success state and a failure state, allowing you to\n * return a single type from a function and discriminate between the two\n * possible states in a principled way.\n *\n * Using it could look something like this:\n *\n * ```ts\n * import { result } from '@utils';\n *\n * const mightFail = (input: number): Result<number, string> => {\n * try {\n * let value: number = calculateSomethingWithInput(input);\n * return result.ok(value);\n * } catch (e) {\n * return result.err(e.message);\n * }\n * }\n *\n * const sumResult = mightFail(2);\n *\n * const msg = result.map(sumResult, (sum: number) => `the sum was: ${sum}`);\n * ```\n *\n * A few utility methods are defined in this module, like `map` and `unwrap`,\n * which are (probably obviously) inspired by the correspond methods on\n * `std::result::Result` in Rust.\n */\nexport type Result<OnSuccess, OnFailure> = Ok<OnSuccess> | Err<OnFailure>;\n\n/**\n * Type for the Ok state of a Result\n */\ntype Ok<T> = {\n isOk: true;\n isErr: false;\n value: T;\n};\n\n/**\n * Type for the Err state of a Result\n */\ntype Err<T> = {\n isOk: false;\n isErr: true;\n value: T;\n};\n\n/**\n * Create an `Ok` given a value. This doesn't do any checking that the value is\n * 'ok-ish' since doing so would make an undue assumption about what is 'ok'.\n * Instead, this trusts the user to determine, at the call site, whether\n * something is `ok()` or `err()`.\n *\n * @param value the value to wrap up in an `Ok`\n * @returns an Ok wrapping the value\n */\nexport const ok = <T>(value: T): Ok<T> => ({\n isOk: true,\n isErr: false,\n value,\n});\n\n/**\n * Create an `Err` given a value.\n *\n * @param value the value to wrap up in an `Err`\n * @returns an Ok wrapping the value\n */\nexport const err = <T>(value: T): Err<T> => ({\n isOk: false,\n isErr: true,\n value,\n});\n\n/**\n * Map across a `Result`.\n *\n * If it's `Ok`, unwraps the value, applies the supplied function, and returns\n * the result, wrapped in `Ok` again. This could involve changing the type of\n * the wrapped value, for instance:\n *\n * ```ts\n * import { result } from \"@utils\";\n *\n * const myResult: Result<string, string> = result.ok(\"monads???\");\n * const updatedResult = result.map(myResult, wrappedString => (\n * wrappedString.split(\"\").length\n * ));\n * ```\n *\n * after the `result.map` call the type of `updatedResult` will now be\n * `Result<number, string>`.\n *\n * If it's `Err`, just return the same value.\n *\n * This lets the programmer trigger an action, or transform a value, only if an\n * earlier operation succeeded, short-circuiting instead if an error occurred.\n *\n * @param result a `Result` value which we want to map across\n * @param fn a function for handling the `Ok` case for the `Result`\n * @returns a new `Result`, with the a new wrapped value (if `Ok`) or the\n * same (if `Err)\n */\nexport function map<T1, T2, E>(result: Result<T1, E>, fn: (t: T1) => Promise<T2>): Promise<Result<T2, E>>;\nexport function map<T1, T2, E>(result: Result<T1, E>, fn: (t: T1) => T2): Result<T2, E>;\nexport function map<T1, T2, E>(\n result: Result<T1, E>,\n fn: ((t: T1) => T2) | ((t: T1) => Promise<T2>),\n): Promise<Result<T2, E>> | Result<T2, E> {\n if (result.isOk) {\n const val = fn(result.value);\n if (val instanceof Promise) {\n return val.then((newVal) => ok(newVal));\n } else {\n return ok(val);\n }\n }\n\n if (result.isErr) {\n // unwrapping the error is necessary here for typechecking\n // but you and I both know its type hasn't changed a bit!\n const value = result.value;\n return err(value);\n }\n\n throw 'should never get here';\n}\n\n/**\n * Unwrap a {@link Result}, return the value inside if it is an `Ok` and\n * throw with the wrapped value if it is an `Err`.\n *\n * @throws with the wrapped value if it is an `Err`.\n * @param result a result to peer inside of\n * @returns the wrapped value, if `Ok`\n */\nexport const unwrap = <T, E>(result: Result<T, E>): T => {\n if (result.isOk) {\n return result.value;\n } else {\n throw result.value;\n }\n};\n\n/**\n * Unwrap a {@link Result}, return the value inside if it is an `Err` and\n * throw with the wrapped value if it is an `Ok`.\n *\n * @throws with the wrapped value if it is an `Ok`.\n * @param result a result to peer inside of\n * @returns the wrapped value, if `Err`\n */\nexport const unwrapErr = <T, E>(result: Result<T, E>): E => {\n if (result.isErr) {\n return result.value;\n } else {\n throw result.value;\n }\n};\n","import type * as d from '../declarations';\nimport { dashToPascalCase, isString, toDashCase } from './helpers';\nimport { buildError } from './message-utils';\n\n/**\n * A set of JSDoc tags which should be excluded from JSDoc comments\n * included in output typedefs.\n */\nconst SUPPRESSED_JSDOC_TAGS: ReadonlyArray<string> = ['virtualProp', 'slot', 'part', 'internal'];\n\n/**\n * Create a stylistically-appropriate JS variable name from a filename\n *\n * If the filename has any of the special characters \"?\", \"#\", \"&\" and \"=\" it\n * will take the string before the left-most instance of one of those\n * characters.\n *\n * @param fileName the filename which serves as starting material\n * @returns a JS variable name based on the filename\n */\nexport const createJsVarName = (fileName: string): string => {\n if (isString(fileName)) {\n fileName = fileName.split('?')[0];\n fileName = fileName.split('#')[0];\n fileName = fileName.split('&')[0];\n fileName = fileName.split('=')[0];\n fileName = toDashCase(fileName);\n fileName = fileName.replace(/[|;$%@\"<>()+,.{}_\\!\\/\\\\]/g, '-');\n fileName = dashToPascalCase(fileName);\n\n if (fileName.length > 1) {\n fileName = fileName[0].toLowerCase() + fileName.slice(1);\n } else {\n fileName = fileName.toLowerCase();\n }\n\n if (fileName.length > 0 && !isNaN(fileName[0] as any)) {\n fileName = '_' + fileName;\n }\n }\n return fileName;\n};\n\n/**\n * Determines if a given file path points to a type declaration file (ending in .d.ts) or not. This function is\n * case-insensitive in its heuristics.\n * @param filePath the path to check\n * @returns `true` if the given `filePath` points to a type declaration file, `false` otherwise\n */\nexport const isDtsFile = (filePath: string): boolean => {\n const parts = filePath.toLowerCase().split('.');\n if (parts.length > 2) {\n return parts[parts.length - 2] === 'd' && parts[parts.length - 1] === 'ts';\n }\n return false;\n};\n\n/**\n * Generate the preamble to be placed atop the main file of the build\n * @param config the Stencil configuration file\n * @returns the generated preamble\n */\nexport const generatePreamble = (config: d.Config): string => {\n const { preamble } = config;\n\n if (!preamble) {\n return '';\n }\n\n // generate the body of the JSDoc-style comment\n const preambleComment: string[] = preamble.split('\\n').map((l) => ` * ${l}`);\n\n preambleComment.unshift(`/*!`);\n preambleComment.push(` */`);\n\n return preambleComment.join('\\n');\n};\n\nconst lineBreakRegex = /\\r?\\n|\\r/g;\nexport function getTextDocs(docs: d.CompilerJsDoc | undefined | null) {\n if (docs == null) {\n return '';\n }\n return `${docs.text.replace(lineBreakRegex, ' ')}\n${docs.tags\n .filter((tag) => tag.name !== 'internal')\n .map((tag) => `@${tag.name} ${(tag.text || '').replace(lineBreakRegex, ' ')}`)\n .join('\\n')}`.trim();\n}\n\n/**\n * Adds a doc block to a string\n * @param str the string to add a doc block to\n * @param docs the compiled JS docs\n * @param indentation number of spaces to indent the block with\n * @returns the doc block\n */\nexport function addDocBlock(str: string, docs?: d.CompilerJsDoc, indentation: number = 0): string {\n if (!docs) {\n return str;\n }\n\n return [formatDocBlock(docs, indentation), str].filter(Boolean).join(`\\n`);\n}\n\n/**\n * Formats the given compiled docs to a JavaScript doc block\n * @param docs the compiled JS docs\n * @param indentation number of spaces to indent the block with\n * @returns the formatted doc block\n */\nfunction formatDocBlock(docs: d.CompilerJsDoc, indentation: number = 0): string {\n const textDocs = getDocBlockLines(docs);\n if (!textDocs.filter(Boolean).length) {\n return '';\n }\n\n const spaces = new Array(indentation + 1).join(' ');\n\n return [spaces + '/**', ...textDocs.map((line) => spaces + ` * ${line}`), spaces + ' */'].join(`\\n`);\n}\n\n/**\n * Get all lines which are part of the doc block\n *\n * @param docs the compiled JS docs\n * @returns list of lines part of the doc block\n */\nfunction getDocBlockLines(docs: d.CompilerJsDoc): string[] {\n return [\n ...docs.text.split(lineBreakRegex),\n ...docs.tags\n .filter((tag) => !SUPPRESSED_JSDOC_TAGS.includes(tag.name))\n .map((tag) => `@${tag.name} ${tag.text || ''}`.split(lineBreakRegex)),\n ]\n .flat()\n .filter(Boolean);\n}\n\n/**\n * Retrieve a project's dependencies from the current build context\n * @param buildCtx the current build context to query for a specific package\n * @returns a list of package names the project is dependent on\n */\nconst getDependencies = (buildCtx: d.BuildCtx): ReadonlyArray<string> =>\n Object.keys(buildCtx?.packageJson?.dependencies ?? {}).filter((pkgName) => !SKIP_DEPS.includes(pkgName));\n\n/**\n * Utility to determine whether a project has a dependency on a package\n * @param buildCtx the current build context to query for a specific package\n * @param depName the name of the dependency/package\n * @returns `true` if the project has a dependency a packaged with the provided name, `false` otherwise\n */\nexport const hasDependency = (buildCtx: d.BuildCtx, depName: string): boolean => {\n return getDependencies(buildCtx).includes(depName);\n};\n\nexport const readPackageJson = async (config: d.ValidatedConfig, compilerCtx: d.CompilerCtx, buildCtx: d.BuildCtx) => {\n try {\n const pkgJson = await compilerCtx.fs.readFile(config.packageJsonFilePath);\n\n if (pkgJson) {\n const parseResults = parsePackageJson(pkgJson, config.packageJsonFilePath);\n if (parseResults.diagnostic) {\n buildCtx.diagnostics.push(parseResults.diagnostic);\n } else {\n buildCtx.packageJson = parseResults.data;\n }\n }\n } catch (e) {\n if (!config.outputTargets.some((o) => o.type.includes('dist'))) {\n const diagnostic = buildError(buildCtx.diagnostics);\n diagnostic.header = `Missing \"package.json\"`;\n diagnostic.messageText = `Valid \"package.json\" file is required for distribution: ${config.packageJsonFilePath}`;\n }\n }\n};\n\n/**\n * A type that describes the result of parsing a `package.json` file's contents\n */\nexport type ParsePackageJsonResult = {\n diagnostic: d.Diagnostic | null;\n data: any | null;\n filePath: string;\n};\n\n/**\n * Parse a string read from a `package.json` file\n * @param pkgJsonStr the string read from a `package.json` file\n * @param pkgJsonFilePath the path to the already read `package.json` file\n * @returns the results of parsing the provided contents of the `package.json` file\n */\nexport const parsePackageJson = (pkgJsonStr: string, pkgJsonFilePath: string): ParsePackageJsonResult => {\n const parseResult: ParsePackageJsonResult = {\n diagnostic: null,\n data: null,\n filePath: pkgJsonFilePath,\n };\n\n try {\n parseResult.data = JSON.parse(pkgJsonStr);\n } catch (e) {\n parseResult.diagnostic = buildError();\n parseResult.diagnostic.absFilePath = isString(pkgJsonFilePath) ? pkgJsonFilePath : undefined;\n parseResult.diagnostic.header = `Error Parsing JSON`;\n if (e instanceof Error) {\n parseResult.diagnostic.messageText = e.message;\n }\n }\n\n return parseResult;\n};\n\nconst SKIP_DEPS = ['@stencil/core'];\n\n/**\n * Check whether a string is a member of a ReadonlyArray<string>\n *\n * We need a little helper for this because unfortunately `includes` is typed\n * on `ReadonlyArray<T>` as `(el: T): boolean` so a `string` cannot be passed\n * to `includes` on a `ReadonlyArray` 😢 thus we have a little helper function\n * where we do the type coercion just once.\n *\n * see microsoft/TypeScript#31018 for some discussion of this\n *\n * @param readOnlyArray the array we're checking\n * @param maybeMember a value which is possibly a member of the array\n * @returns whether the array contains the member or not\n */\nexport const readOnlyArrayHasStringMember = <T extends string>(\n readOnlyArray: ReadonlyArray<T>,\n maybeMember: T | string,\n): maybeMember is T => readOnlyArray.includes(maybeMember as (typeof readOnlyArray)[number]);\n","/**\n * Validates that a component tag meets required naming conventions to be used for a web component\n * @param tag the tag to validate\n * @returns an error message if the tag has an invalid name, undefined if the tag name passes all checks\n */\nexport const validateComponentTag = (tag: string): string | undefined => {\n // we want to check this first since we call some String.prototype methods below\n if (typeof tag !== 'string') {\n return `Tag \"${tag}\" must be a string type`;\n }\n if (tag !== tag.trim()) {\n return `Tag can not contain white spaces`;\n }\n if (tag !== tag.toLowerCase()) {\n return `Tag can not contain upper case characters`;\n }\n if (tag.length === 0) {\n return `Received empty tag value`;\n }\n\n if (tag.indexOf(' ') > -1) {\n return `\"${tag}\" tag cannot contain a space`;\n }\n\n if (tag.indexOf(',') > -1) {\n return `\"${tag}\" tag cannot be used for multiple tags`;\n }\n\n const invalidChars = tag.replace(/\\w|-/g, '');\n if (invalidChars !== '') {\n return `\"${tag}\" tag contains invalid characters: ${invalidChars}`;\n }\n\n if (tag.indexOf('-') === -1) {\n return `\"${tag}\" tag must contain a dash (-) to work as a valid web component`;\n }\n\n if (tag.indexOf('--') > -1) {\n return `\"${tag}\" tag cannot contain multiple dashes (--) next to each other`;\n }\n\n if (tag.indexOf('-') === 0) {\n return `\"${tag}\" tag cannot start with a dash (-)`;\n }\n\n if (tag.lastIndexOf('-') === tag.length - 1) {\n return `\"${tag}\" tag cannot end with a dash (-)`;\n }\n return undefined;\n};\n","import type { ConfigFlags } from '../cli/config-flags';\nimport type { PrerenderUrlResults, PrintLine } from '../internal';\nimport type { JsonDocs } from './stencil-public-docs';\n\nexport * from './stencil-public-docs';\n\n/**\n * https://stenciljs.com/docs/config/\n */\nexport interface StencilConfig {\n /**\n * By default, Stencil will attempt to optimize small scripts by inlining them in HTML. Setting\n * this flag to `false` will prevent this optimization and keep all scripts separate from HTML.\n */\n allowInlineScripts?: boolean;\n /**\n * By setting `autoprefixCss` to `true`, Stencil will use the appropriate config to automatically\n * prefix css. For example, developers can write modern and standard css properties, such as\n * \"transform\", and Stencil will automatically add in the prefixed version, such as \"-webkit-transform\".\n * As of Stencil v2, autoprefixing CSS is no longer the default.\n * Defaults to `false`\n */\n autoprefixCss?: boolean | any;\n\n /**\n * By default, Stencil will statically analyze the application and generate a component graph of\n * how all the components are interconnected.\n *\n * From the component graph it is able to best decide how components should be grouped\n * depending on their usage with one another within the app.\n * By doing so it's able to bundle components together in order to reduce network requests.\n * However, bundles can be manually generated using the bundles config.\n *\n * The bundles config is an array of objects that represent how components are grouped together\n * in lazy-loaded bundles.\n * This config is rarely needed as Stencil handles this automatically behind the scenes.\n */\n bundles?: ConfigBundle[];\n\n /**\n * Stencil will cache build results in order to speed up rebuilds.\n * To disable this feature, set enableCache to false.\n */\n enableCache?: boolean;\n /**\n * The directory where sub-directories will be created for caching when `enableCache` is set\n * `true` or if using Stencil's Screenshot Connector.\n *\n * @default '.stencil'\n *\n * @example\n *\n * A Stencil config like the following:\n * ```ts\n * export const config = {\n * ...,\n * enableCache: true,\n * cacheDir: '.cache',\n * testing: {\n * screenshotConnector: 'connector.js'\n * }\n * }\n * ```\n *\n * Will result in the following file structure:\n * ```tree\n * stencil-project-root\n * └── .cache\n * ├── .build <-- Where build related file caching is written\n * |\n * └── screenshot-cache.json <-- Where screenshot caching is written\n * ```\n */\n cacheDir?: string;\n\n /**\n * Stencil is traditionally used to compile many components into an app,\n * and each component comes with its own compartmentalized styles.\n * However, it's still common to have styles which should be \"global\" across all components and the website.\n * A global CSS file is often useful to set CSS Variables.\n *\n * Additionally, the globalStyle config can be used to precompile styles with Sass, PostCSS, etc.\n * Below is an example folder structure containing a webapp's global