2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018-present, Yuxi (Evan) You
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+80
View File
@@ -0,0 +1,80 @@
# @vue/compiler-sfc
> Lower level utilities for compiling Vue Single File Components
**Note: as of 3.2.13+, this package is included as a dependency of the main `vue` package and can be accessed as `vue/compiler-sfc`. This means you no longer need to explicitly install this package and ensure its version match that of `vue`'s. Just use the main `vue/compiler-sfc` deep import instead.**
This package contains lower level utilities that you can use if you are writing a plugin / transform for a bundler or module system that compiles Vue Single File Components (SFCs) into JavaScript. It is used in [vue-loader](https://github.com/vuejs/vue-loader) and [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue).
## API
The API is intentionally low-level due to the various considerations when integrating Vue SFCs in a build system:
- Separate hot-module replacement (HMR) for script, template and styles
- template updates should not reset component state
- style updates should be performed without component re-render
- Leveraging the tool's plugin system for pre-processor handling. e.g. `<style lang="scss">` should be processed by the corresponding webpack loader.
- In some cases, transformers of each block in an SFC do not share the same execution context. For example, when used with `thread-loader` or other parallelized configurations, the template sub-loader in `vue-loader` may not have access to the full SFC and its descriptor.
The general idea is to generate a facade module that imports the individual blocks of the component. The trick is the module imports itself with different query strings so that the build system can handle each request as "virtual" modules:
```
+--------------------+
| |
| script transform |
+----->+ |
| +--------------------+
|
+--------------------+ | +--------------------+
| | | | |
| facade transform +----------->+ template transform |
| | | | |
+--------------------+ | +--------------------+
|
| +--------------------+
+----->+ |
| style transform |
| |
+--------------------+
```
Where the facade module looks like this:
```js
// main script
import script from '/project/foo.vue?vue&type=script'
// template compiled to render function
import { render } from '/project/foo.vue?vue&type=template&id=xxxxxx'
// css
import '/project/foo.vue?vue&type=style&index=0&id=xxxxxx'
// attach render function to script
script.render = render
// attach additional metadata
// some of these should be dev only
script.__file = 'example.vue'
script.__scopeId = 'xxxxxx'
// additional tooling-specific HMR handling code
// using __VUE_HMR_API__ global
export default script
```
### High Level Workflow
1. In facade transform, parse the source into descriptor with the `parse` API and generate the above facade module code based on the descriptor;
2. In script transform, use `compileScript` to process the script. This handles features like `<script setup>` and CSS variable injection. Alternatively, this can be done directly in the facade module (with the code inlined instead of imported), but it will require rewriting `export default` to a temp variable (a `rewriteDefault` convenience API is provided for this purpose) so additional options can be attached to the exported object.
3. In template transform, use `compileTemplate` to compile the raw template into render function code.
4. In style transform, use `compileStyle` to compile raw CSS to handle `<style scoped>`, `<style module>` and CSS variable injection.
Options needed for these APIs can be passed via the query string.
For detailed API references and options, check out the source type definitions. For actual usage of these APIs, check out [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue) or [vue-loader](https://github.com/vuejs/vue-loader/tree/next).
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,543 @@
import * as _babel_types from '@babel/types';
import { Statement, Expression, TSType, Node, Program, CallExpression, ObjectPattern, TSModuleDeclaration, TSPropertySignature, TSMethodSignature, TSCallSignatureDeclaration, TSFunctionType } from '@babel/types';
import { RootNode, CompilerOptions, CodegenResult, ParserOptions, CompilerError, SourceLocation, BindingMetadata as BindingMetadata$1 } from '@vue/compiler-core';
export { BindingMetadata, CompilerError, CompilerOptions, extractIdentifiers, generateCodeFrame, isInDestructureAssignment, isStaticProperty, walkIdentifiers } from '@vue/compiler-core';
import { RawSourceMap } from 'source-map-js';
import { ParserPlugin } from '@babel/parser';
export { parse as babelParse } from '@babel/parser';
import { Result, LazyResult } from 'postcss';
import MagicString from 'magic-string';
export { default as MagicString } from 'magic-string';
import TS from 'typescript';
export interface AssetURLTagConfig {
[name: string]: string[];
}
export interface AssetURLOptions {
/**
* If base is provided, instead of transforming relative asset urls into
* imports, they will be directly rewritten to absolute urls.
*/
base?: string | null;
/**
* If true, also processes absolute urls.
*/
includeAbsolute?: boolean;
tags?: AssetURLTagConfig;
}
export interface TemplateCompiler {
compile(source: string | RootNode, options: CompilerOptions): CodegenResult;
parse(template: string, options: ParserOptions): RootNode;
}
export interface SFCTemplateCompileResults {
code: string;
ast?: RootNode;
preamble?: string;
source: string;
tips: string[];
errors: (string | CompilerError)[];
map?: RawSourceMap;
}
export interface SFCTemplateCompileOptions {
source: string;
ast?: RootNode;
filename: string;
id: string;
scoped?: boolean;
slotted?: boolean;
isProd?: boolean;
ssr?: boolean;
ssrCssVars?: string[];
inMap?: RawSourceMap;
compiler?: TemplateCompiler;
compilerOptions?: CompilerOptions;
preprocessLang?: string;
preprocessOptions?: any;
/**
* In some cases, compiler-sfc may not be inside the project root (e.g. when
* linked or globally installed). In such cases a custom `require` can be
* passed to correctly resolve the preprocessors.
*/
preprocessCustomRequire?: (id: string) => any;
/**
* Configure what tags/attributes to transform into asset url imports,
* or disable the transform altogether with `false`.
*/
transformAssetUrls?: AssetURLOptions | AssetURLTagConfig | boolean;
}
export declare function compileTemplate(options: SFCTemplateCompileOptions): SFCTemplateCompileResults;
export interface SFCScriptCompileOptions {
/**
* Scope ID for prefixing injected CSS variables.
* This must be consistent with the `id` passed to `compileStyle`.
*/
id: string;
/**
* Production mode. Used to determine whether to generate hashed CSS variables
*/
isProd?: boolean;
/**
* Enable/disable source map. Defaults to true.
*/
sourceMap?: boolean;
/**
* https://babeljs.io/docs/en/babel-parser#plugins
*/
babelParserPlugins?: ParserPlugin[];
/**
* A list of files to parse for global types to be made available for type
* resolving in SFC macros. The list must be fully resolved file system paths.
*/
globalTypeFiles?: string[];
/**
* Compile the template and inline the resulting render function
* directly inside setup().
* - Only affects `<script setup>`
* - This should only be used in production because it prevents the template
* from being hot-reloaded separately from component state.
*/
inlineTemplate?: boolean;
/**
* Generate the final component as a variable instead of default export.
* This is useful in e.g. @vitejs/plugin-vue where the script needs to be
* placed inside the main module.
*/
genDefaultAs?: string;
/**
* Options for template compilation when inlining. Note these are options that
* would normally be passed to `compiler-sfc`'s own `compileTemplate()`, not
* options passed to `compiler-dom`.
*/
templateOptions?: Partial<SFCTemplateCompileOptions>;
/**
* Hoist <script setup> static constants.
* - Only enables when one `<script setup>` exists.
* @default true
*/
hoistStatic?: boolean;
/**
* (**Experimental**) Enable reactive destructure for `defineProps`
* @default false
*/
propsDestructure?: boolean;
/**
* File system access methods to be used when resolving types
* imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten
* to use a virtual file system for use in browsers (e.g. in REPLs)
*/
fs?: {
fileExists(file: string): boolean;
readFile(file: string): string | undefined;
realpath?(file: string): string;
};
/**
* Transform Vue SFCs into custom elements.
*/
customElement?: boolean | ((filename: string) => boolean);
}
interface ImportBinding {
isType: boolean;
imported: string;
local: string;
source: string;
isFromSetup: boolean;
isUsedInTemplate: boolean;
}
/**
* Compile `<script setup>`
* It requires the whole SFC descriptor because we need to handle and merge
* normal `<script>` + `<script setup>` if both are present.
*/
export declare function compileScript(sfc: SFCDescriptor, options: SFCScriptCompileOptions): SFCScriptBlock;
export interface SFCParseOptions {
filename?: string;
sourceMap?: boolean;
sourceRoot?: string;
pad?: boolean | 'line' | 'space';
ignoreEmpty?: boolean;
compiler?: TemplateCompiler;
templateParseOptions?: ParserOptions;
/**
* TODO remove in 3.5
* @deprecated use `templateParseOptions: { prefixIdentifiers: false }` instead
*/
parseExpressions?: boolean;
}
export interface SFCBlock {
type: string;
content: string;
attrs: Record<string, string | true>;
loc: SourceLocation;
map?: RawSourceMap;
lang?: string;
src?: string;
}
export interface SFCTemplateBlock extends SFCBlock {
type: 'template';
ast?: RootNode;
}
export interface SFCScriptBlock extends SFCBlock {
type: 'script';
setup?: string | boolean;
bindings?: BindingMetadata$1;
imports?: Record<string, ImportBinding>;
scriptAst?: _babel_types.Statement[];
scriptSetupAst?: _babel_types.Statement[];
warnings?: string[];
/**
* Fully resolved dependency file paths (unix slashes) with imported types
* used in macros, used for HMR cache busting in @vitejs/plugin-vue and
* vue-loader.
*/
deps?: string[];
}
export interface SFCStyleBlock extends SFCBlock {
type: 'style';
scoped?: boolean;
module?: string | boolean;
}
export interface SFCDescriptor {
filename: string;
source: string;
template: SFCTemplateBlock | null;
script: SFCScriptBlock | null;
scriptSetup: SFCScriptBlock | null;
styles: SFCStyleBlock[];
customBlocks: SFCBlock[];
cssVars: string[];
/**
* whether the SFC uses :slotted() modifier.
* this is used as a compiler optimization hint.
*/
slotted: boolean;
/**
* compare with an existing descriptor to determine whether HMR should perform
* a reload vs. re-render.
*
* Note: this comparison assumes the prev/next script are already identical,
* and only checks the special case where <script setup lang="ts"> unused import
* pruning result changes due to template changes.
*/
shouldForceReload: (prevImports: Record<string, ImportBinding>) => boolean;
}
export interface SFCParseResult {
descriptor: SFCDescriptor;
errors: (CompilerError | SyntaxError)[];
}
export declare function parse(source: string, options?: SFCParseOptions): SFCParseResult;
type PreprocessLang = 'less' | 'sass' | 'scss' | 'styl' | 'stylus';
export interface SFCStyleCompileOptions {
source: string;
filename: string;
id: string;
scoped?: boolean;
trim?: boolean;
isProd?: boolean;
inMap?: RawSourceMap;
preprocessLang?: PreprocessLang;
preprocessOptions?: any;
preprocessCustomRequire?: (id: string) => any;
postcssOptions?: any;
postcssPlugins?: any[];
/**
* @deprecated use `inMap` instead.
*/
map?: RawSourceMap;
}
/**
* Aligns with postcss-modules
* https://github.com/css-modules/postcss-modules
*/
interface CSSModulesOptions {
scopeBehaviour?: 'global' | 'local';
generateScopedName?: string | ((name: string, filename: string, css: string) => string);
hashPrefix?: string;
localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly';
exportGlobals?: boolean;
globalModulePaths?: RegExp[];
}
export interface SFCAsyncStyleCompileOptions extends SFCStyleCompileOptions {
isAsync?: boolean;
modules?: boolean;
modulesOptions?: CSSModulesOptions;
}
export interface SFCStyleCompileResults {
code: string;
map: RawSourceMap | undefined;
rawResult: Result | LazyResult | undefined;
errors: Error[];
modules?: Record<string, string>;
dependencies: Set<string>;
}
export declare function compileStyle(options: SFCStyleCompileOptions): SFCStyleCompileResults;
export declare function compileStyleAsync(options: SFCAsyncStyleCompileOptions): Promise<SFCStyleCompileResults>;
export declare function rewriteDefault(input: string, as: string, parserPlugins?: ParserPlugin[]): string;
/**
* Utility for rewriting `export default` in a script block into a variable
* declaration so that we can inject things into it
*/
export declare function rewriteDefaultAST(ast: Statement[], s: MagicString, as: string): void;
type PropsDestructureBindings = Record<string, // public prop key
{
local: string;
default?: Expression;
}>;
export declare function extractRuntimeProps(ctx: TypeResolveContext): string | undefined;
interface ModelDecl {
type: TSType | undefined;
options: string | undefined;
identifier: string | undefined;
runtimeOptionNodes: Node[];
}
declare enum BindingTypes {
/**
* returned from data()
*/
DATA = "data",
/**
* declared as a prop
*/
PROPS = "props",
/**
* a local alias of a `<script setup>` destructured prop.
* the original is stored in __propsAliases of the bindingMetadata object.
*/
PROPS_ALIASED = "props-aliased",
/**
* a let binding (may or may not be a ref)
*/
SETUP_LET = "setup-let",
/**
* a const binding that can never be a ref.
* these bindings don't need `unref()` calls when processed in inlined
* template expressions.
*/
SETUP_CONST = "setup-const",
/**
* a const binding that does not need `unref()`, but may be mutated.
*/
SETUP_REACTIVE_CONST = "setup-reactive-const",
/**
* a const binding that may be a ref.
*/
SETUP_MAYBE_REF = "setup-maybe-ref",
/**
* bindings that are guaranteed to be refs
*/
SETUP_REF = "setup-ref",
/**
* declared by other options, e.g. computed, inject
*/
OPTIONS = "options",
/**
* a literal constant, e.g. 'foo', 1, true
*/
LITERAL_CONST = "literal-const"
}
type BindingMetadata = {
[key: string]: BindingTypes | undefined;
} & {
__isScriptSetup?: boolean;
__propsAliases?: Record<string, string>;
};
export declare class ScriptCompileContext {
descriptor: SFCDescriptor;
options: Partial<SFCScriptCompileOptions>;
isJS: boolean;
isTS: boolean;
isCE: boolean;
scriptAst: Program | null;
scriptSetupAst: Program | null;
source: string;
filename: string;
s: MagicString;
startOffset: number | undefined;
endOffset: number | undefined;
scope?: TypeScope;
globalScopes?: TypeScope[];
userImports: Record<string, ImportBinding>;
hasDefinePropsCall: boolean;
hasDefineEmitCall: boolean;
hasDefineExposeCall: boolean;
hasDefaultExportName: boolean;
hasDefaultExportRender: boolean;
hasDefineOptionsCall: boolean;
hasDefineSlotsCall: boolean;
hasDefineModelCall: boolean;
propsCall: CallExpression | undefined;
propsDecl: Node | undefined;
propsRuntimeDecl: Node | undefined;
propsTypeDecl: Node | undefined;
propsDestructureDecl: ObjectPattern | undefined;
propsDestructuredBindings: PropsDestructureBindings;
propsDestructureRestId: string | undefined;
propsRuntimeDefaults: Node | undefined;
emitsRuntimeDecl: Node | undefined;
emitsTypeDecl: Node | undefined;
emitDecl: Node | undefined;
modelDecls: Record<string, ModelDecl>;
optionsRuntimeDecl: Node | undefined;
bindingMetadata: BindingMetadata;
helperImports: Set<string>;
helper(key: string): string;
/**
* to be exposed on compiled script block for HMR cache busting
*/
deps?: Set<string>;
/**
* cache for resolved fs
*/
fs?: NonNullable<SFCScriptCompileOptions['fs']>;
constructor(descriptor: SFCDescriptor, options: Partial<SFCScriptCompileOptions>);
getString(node: Node, scriptSetup?: boolean): string;
error(msg: string, node: Node, scope?: TypeScope): never;
}
export type SimpleTypeResolveOptions = Partial<Pick<SFCScriptCompileOptions, 'globalTypeFiles' | 'fs' | 'babelParserPlugins' | 'isProd'>>;
/**
* TypeResolveContext is compatible with ScriptCompileContext
* but also allows a simpler version of it with minimal required properties
* when resolveType needs to be used in a non-SFC context, e.g. in a babel
* plugin. The simplest context can be just:
* ```ts
* const ctx: SimpleTypeResolveContext = {
* filename: '...',
* source: '...',
* options: {},
* error() {},
* ast: []
* }
* ```
*/
export type SimpleTypeResolveContext = Pick<ScriptCompileContext, 'source' | 'filename' | 'error' | 'helper' | 'getString' | 'propsTypeDecl' | 'propsRuntimeDefaults' | 'propsDestructuredBindings' | 'emitsTypeDecl' | 'isCE'> & Partial<Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps' | 'fs'>> & {
ast: Statement[];
options: SimpleTypeResolveOptions;
};
export type TypeResolveContext = ScriptCompileContext | SimpleTypeResolveContext;
type Import = Pick<ImportBinding, 'source' | 'imported'>;
interface WithScope {
_ownerScope: TypeScope;
}
type ScopeTypeNode = Node & WithScope & {
_ns?: TSModuleDeclaration & WithScope;
};
declare class TypeScope {
filename: string;
source: string;
offset: number;
imports: Record<string, Import>;
types: Record<string, ScopeTypeNode>;
declares: Record<string, ScopeTypeNode>;
constructor(filename: string, source: string, offset?: number, imports?: Record<string, Import>, types?: Record<string, ScopeTypeNode>, declares?: Record<string, ScopeTypeNode>);
isGenericScope: boolean;
resolvedImportSources: Record<string, string>;
exportedTypes: Record<string, ScopeTypeNode>;
exportedDeclares: Record<string, ScopeTypeNode>;
}
interface MaybeWithScope {
_ownerScope?: TypeScope;
}
interface ResolvedElements {
props: Record<string, (TSPropertySignature | TSMethodSignature) & {
_ownerScope: TypeScope;
}>;
calls?: (TSCallSignatureDeclaration | TSFunctionType)[];
}
/**
* Resolve arbitrary type node to a list of type elements that can be then
* mapped to runtime props or emits.
*/
export declare function resolveTypeElements(ctx: TypeResolveContext, node: Node & MaybeWithScope & {
_resolvedElements?: ResolvedElements;
}, scope?: TypeScope, typeParameters?: Record<string, Node>): ResolvedElements;
/**
* @private
*/
export declare function registerTS(_loadTS: () => typeof TS): void;
/**
* @private
*/
export declare function invalidateTypeCache(filename: string): void;
export declare function inferRuntimeType(ctx: TypeResolveContext, node: Node & MaybeWithScope, scope?: TypeScope): string[];
export declare function extractRuntimeEmits(ctx: TypeResolveContext): Set<string>;
export declare const version: string;
export declare const parseCache: Map<string, SFCParseResult>;
export declare const errorMessages: {
0: string;
1: string;
2: string;
3: string;
4: string;
5: string;
6: string;
7: string;
8: string;
9: string;
10: string;
11: string;
12: string;
13: string;
14: string;
15: string;
16: string;
17: string;
18: string;
19: string;
20: string;
21: string;
22: string;
23: string;
24: string;
25: string;
26: string;
27: string;
28: string;
29: string;
30: string;
31: string;
32: string;
33: string;
34: string;
35: string;
36: string;
37: string;
38: string;
39: string;
40: string;
41: string;
42: string;
43: string;
44: string;
45: string;
46: string;
47: string;
48: string;
49: string;
50: string;
51: string;
52: string;
53: string;
};
export declare const walk: any;
/**
* @deprecated this is preserved to avoid breaking vite-plugin-vue < 5.0
* with reactivityTransform: true. The desired behavior should be silently
* ignoring the option instead of breaking.
*/
export declare const shouldTransformRef: () => boolean;
File diff suppressed because one or more lines are too long
@@ -0,0 +1,67 @@
{
"name": "@vue/compiler-sfc",
"version": "3.4.21",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",
"types": "dist/compiler-sfc.d.ts",
"files": [
"dist"
],
"exports": {
".": {
"types": "./dist/compiler-sfc.d.ts",
"node": "./dist/compiler-sfc.cjs.js",
"module": "./dist/compiler-sfc.esm-browser.js",
"import": "./dist/compiler-sfc.esm-browser.js",
"require": "./dist/compiler-sfc.cjs.js"
},
"./*": "./*"
},
"buildOptions": {
"name": "VueCompilerSFC",
"formats": [
"cjs",
"esm-browser"
],
"prod": false,
"enableNonBrowserBranches": true
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/core.git",
"directory": "packages/compiler-sfc"
},
"keywords": [
"vue"
],
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/core/issues"
},
"homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme",
"dependencies": {
"@babel/parser": "^7.23.9",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.7",
"postcss": "^8.4.35",
"source-map-js": "^1.0.2",
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-ssr": "3.4.21",
"@vue/compiler-core": "3.4.21",
"@vue/shared": "3.4.21"
},
"devDependencies": {
"@babel/types": "^7.23.9",
"@vue/consolidate": "^1.0.0",
"hash-sum": "^2.0.0",
"lru-cache": "10.1.0",
"merge-source-map": "^1.1.0",
"minimatch": "^9.0.3",
"postcss-modules": "^6.0.0",
"postcss-selector-parser": "^6.0.15",
"pug": "^3.0.2",
"sass": "^1.71.1"
}
}
+65
View File
@@ -0,0 +1,65 @@
var lookup = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 62, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
]
function base64Decode (source, target) {
var sourceLength = source.length
var paddingLength = (source[sourceLength - 2] === '=' ? 2 : (source[sourceLength - 1] === '=' ? 1
: 0))
var tmp
var byteIndex = 0
var baseLength = (sourceLength - paddingLength) & 0xfffffffc
for (var i = 0; i < baseLength; i += 4) {
tmp = (lookup[source.charCodeAt(i)] << 18) |
(lookup[source.charCodeAt(i + 1)] << 12) |
(lookup[source.charCodeAt(i + 2)] << 6) |
(lookup[source.charCodeAt(i + 3)])
target[byteIndex++] = (tmp >> 16) & 0xFF
target[byteIndex++] = (tmp >> 8) & 0xFF
target[byteIndex++] = (tmp) & 0xFF
}
if (paddingLength === 1) {
tmp = (lookup[source.charCodeAt(i)] << 10) |
(lookup[source.charCodeAt(i + 1)] << 4) |
(lookup[source.charCodeAt(i + 2)] >> 2)
target[byteIndex++] = (tmp >> 8) & 0xFF
target[byteIndex++] = tmp & 0xFF
}
if (paddingLength === 2) {
tmp = (lookup[source.charCodeAt(i)] << 2) | (lookup[source.charCodeAt(i + 1)] >> 4)
target[byteIndex++] = tmp & 0xFF
}
}
export default {
getRandomValues (arr) {
if (!(
arr instanceof Int8Array ||
arr instanceof Uint8Array ||
arr instanceof Int16Array ||
arr instanceof Uint16Array ||
arr instanceof Int32Array ||
arr instanceof Uint32Array ||
arr instanceof Uint8ClampedArray
)) {
throw new Error('Expected an integer array')
}
if (arr.byteLength > 65536) {
throw new Error('Can only request a maximum of 65536 bytes')
}
var crypto = uni.requireNativePlugin('DCloud-Crypto')
base64Decode(crypto.getRandomValues(arr.byteLength), new Uint8Array(arr.buffer, arr.byteOffset,
arr.byteLength))
return arr
}
}
+34
View File
@@ -0,0 +1,34 @@
label,
scroll-view,
swiper-item,
view {
display: flex;
flex-direction: column;
flex-shrink: 0;
flex-grow: 0;
flex-basis: auto;
align-items: stretch;
align-content: flex-start;
}
image,
input,
scroll-view,
swiper,
swiper-item,
text,
textarea,
video,
view {
position: relative;
border: 0 solid #000;
box-sizing: border-box;
}
swiper-item {
position: absolute;
}
button {
margin: 0;
}
+13
View File
@@ -0,0 +1,13 @@
Copyright 2012 OneHealth Solutions, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+410
View File
@@ -0,0 +1,410 @@
# preprocess
[![NPM][npm-image]][npm-url]
[![Linux Build Status][linux-ci-image]][linux-ci-url] [![Windows Build Status][windows-ci-image]][windows-ci-url] [![Coverage Status][coverage-image]][coverage-url] [![dependencies][deps-image]][deps-url] [![dev-dependencies][dev-deps-image]][dev-deps-url]
Preprocess HTML, JavaScript, and other files with directives based off custom or ENV configuration
## Configuration
Install via npm:
```bash
$ npm install --save preprocess
```
## What does it look like?
```html
<head>
<title>Your App</title>
<!-- @if NODE_ENV='production' -->
<script src="some/production/lib/like/analytics.js"></script>
<!-- @endif -->
</head>
<body>
<!-- @ifdef DEBUG -->
<h1>Debugging mode - <!-- @echo RELEASE_TAG --> </h1>
<!-- @endif -->
<p>
<!-- @include welcome_message.txt -->
</p>
</body>
```
```js
var configValue = '/* @echo FOO */' || 'default value';
// @ifdef DEBUG
someDebuggingCall()
// @endif
```
## Directive syntax
### Basic example
The most basic usage is for files that only have two states, non-processed and processed.
In this case, your `@exclude` directives are removed after preprocessing
```html
<body>
<!-- @exclude -->
<header>You're on dev!</header>
<!-- @endexclude -->
</body>
```
After build
```html
<body>
</body>
```
### All directives
- `@if VAR='value'` / `@endif`
This will include the enclosed block if your test passes
- `@ifdef VAR` / `@endif`
This will include the enclosed block if VAR is defined (typeof !== 'undefined')
- `@ifndef VAR` / `@endif`
This will include the enclosed block if VAR is not defined (typeof === 'undefined')
- `@include`
This will include the source from an external file. If the included source ends with a newline then the
following line will be space indented to the level the @include was found.
- `@include-static`
Works the same way as `@include` but doesn't process the included file recursively. Is useful if a large
file has to be included and the recursive processing is not necessary or would otherwise take too long.
- `@extend file.html` / `@endextend`
This will use the source from the external file indicated with the `@extend` tag to wrap the enclosed block.
- `@extendable`
This tag is used to indicate the location in a file referenced using `@extend` where the block enclosed by `@extend` will be populated.
- `@exclude` / `@endexclude`
This will remove the enclosed block upon processing
- `@echo VAR`
This will include the environment variable VAR into your source
- `@foreach $VAR in ARR` / `@endfor`
This will repeat the enclosed block for each value in the Array or Object in ARR. Each value in ARR can be interpolated into the resulting content with $VAR.
- `@exec FUNCTION([param1, param2...])`
This will execute the environment FUNCTION with its parameters and echo the result into your source. The parameter
could be a string or a reference to another environment variable.
### Extended html Syntax
This is useful for more fine grained control of your files over multiple
environment configurations. You have access to simple tests of any variable within the context (or ENV, if not supplied)
```html
<body>
<!-- @if NODE_ENV!='production' -->
<header>You're on dev!</header>
<!-- @endif -->
<!-- @if NODE_ENV='production' -->
<script src="some/production/javascript.js"></script>
<!-- @endif -->
<script>
var fingerprint = '<!-- @echo COMMIT_HASH -->' || 'DEFAULT';
</script>
<script src="<!-- @exec static_path('another/production/javascript.js') -->"></script>
</body>
```
With a `NODE_ENV` set to `production` and `0xDEADBEEF` in
`COMMIT_HASH` this will be built to look like
```html
<body>
<script src="some/production/javascript.js"></script>
<script>
var fingerprint = '0xDEADBEEF' || 'DEFAULT';
</script>
<script src="http://cdn2.my.domain.com/another/javascript.js"></script>
</body>
```
With NODE_ENV not set or set to dev and nothing in COMMIT_HASH,
the built file will be
```html
<body>
<header>You're on dev!</header>
<script>
var fingerprint = '' || 'DEFAULT';
</script>
<script src="http://localhost/myapp/statics/another/javascript.js"></script>
</body>
```
You can also have conditional blocks that are hidden by default by using the
fictional `!>` end tag instead of `-->` after your condition:
```html
<!-- @if true !>
<p>Process was run!</p>
<!-- @endif -->
```
### JavaScript, CSS, C, Java Syntax
Extended syntax below, but will work without specifying a test
```js
normalFunction();
//@exclude
superExpensiveDebugFunction()
//@endexclude
anotherFunction('/* @echo USERNAME */');
```
Built with a NODE_ENV of production :
```js
normalFunction();
anotherFunction('jsoverson');
```
Like HTML, you can have conditional blocks that are hidden by default by ending the directive with a `**` instead of `*/`
```js
angular.module('myModule', ['dep1'
, 'dep2'
/* @if NODE_ENV='production' **
, 'prod_dep'
/* @endif */
/* @exclude **
, 'debug_dep'
/* @endexclude */
]);
```
_Note: Hidden by default blocks only work with block comments (`/* */`) but not with line comments (`//`)._
CSS example
```css
body {
/* @if NODE_ENV=='development' */
background-color: red;
/* @endif */
}
// @include util.css
```
(CSS preprocessing supports single line comment style directives)
### Shell, PHP
```bash
#!/bin/bash
# @include util.sh
```
## API
### preprocess(source[, context[, options]]) -> preprocessedSource
Preprocesses a source provided as a string and returns the preprocessed source.
#### source
Type: `String` (mandatory)
The source to preprocess.
#### context
Type: `Object`
Default: `process.env`
The context that contains the variables that are used in the source. For `@extend` variants and `@include` the additional
context property `src` is available inside of files to be included that contains the current file name. This property is also
available in the context of the source file if one of the `preprocessFile*()` API variants are used.
#### options
Type: `Object`
The options object allows to pass additional options to `preprocess`. Available options are:
##### options.fileNotFoundSilentFail
Type: `Boolean`
Default: `false`
When using `@include` variants and `@extend`, `preprocess` will by default throw an exception in case an included
file can't be found. Set this option to `true` to instruct `preprocess` to fail silently and instead of throwing
to write a message inside of the preprocessed file that an included file could not be found.
##### options.srcDir
Type: `String`
Default: `process.cwd()`
The directory where to look for files included via `@include` variants and `@extend`.
##### options.srcEol
Type: `String`
Default: EOL of source string or `os.EOL` if source string contains multiple different or no EOLs.
The end of line (EOL) character to use for the preprocessed result. May be one of:
- `\r\n` - Windows
- `\n` - Linux/OSX/Unix
- `\r` - legacy Mac
##### options.type
Type: `String`
Default: `html`
The syntax type of source string to preprocess. There are 3 main syntax variants:
- `html`, aliases: `xml`
- `js`, aliases: `javascript`, `jsx`, `c`, `cc`, `cpp`, `cs`, `csharp`, `java`, `less`, `sass`, `scss`, `css`, `php`,
`ts`, `tsx`, `peg`, `pegjs`, `jade`, `styl`
- `coffee`, aliases: `bash`, `shell`, `sh`
### preprocessFile(srcFile, destFile[, context[, callback[, options]]])
Preprocesses a `sourceFile` and saves the result to `destFile`. Simple wrapper around `fs.readFile()` and `fs.writeFile()`.
#### srcFile
Type: `String` (mandatory)
The path to the source file to preprocess.
#### destFile
Type: `String` (mandatory)
The path to the destination file where the preprocessed result shall be saved.
#### context
See `context` [attribute description](#context) of `preprocess()` function.
#### callback
Type: `function(err)`
The callback function that is called upon error or completion. Receives an error if something goes wrong as first parameter.
#### options
See `options` [attribute description](#options) of `preprocess()` function. Differs only in that the default `srcDir` value is set
to the path of the provided source file instead of `process.cwd()` and the default `type` is derived from source file extension.
### preprocessFileSync(srcFile, destFile[, context[, options]])
Preprocesses a `sourceFile` and saves the result to `destFile`. Simple wrapper around `fs.readFileSync()` and `fs.writeFileSync()`.
#### srcFile
Type: `String` (mandatory)
The path to the source file to preprocess.
#### destFile
Type: `String` (mandatory)
The path to the destination file where the preprocessed result shall be saved.
#### context
See `context` [attribute description](#context) of `preprocess()` function.
#### options
See `options` [attribute description](#options) of `preprocess()` function. Differs only in that the default `srcDir` value is set
to the path of the provided source file instead of `process.cwd()` and the default `type` is derived from source file extension.
## Usage Examples
```js
var pp = require('preprocess');
var text = 'Hi, I am <!-- @echo USERNAME -->';
pp.preprocess(text);
// -> Hi, I am jsoverson
pp.preprocess(text, {USERNAME : "Bob"});
// -> Hi, I am Bob
// specify the format to use for the directives as the third parameter
pp.preprocess(text, {USERNAME : "Bob"}, {type: 'html'});
// -> Hi, I am Bob
// Preprocess files asynchronously
pp.preprocessFile(src, dest, context, callback, options);
// Preprocess files synchronously
pp.preprocessFileSync(src, dest, context, options);
```
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or
changed functionality. Lint and test your code using jshint
## Release History
- 3.1.0
- Added `.jsx` file extension as an alias for `js` (@BendingBender, #79)
- Added `.tsx` file extension as an alias for `js` (@rosendi, #100)
- Bumped XRegExp to v3
- 3.0.1/2 Fixes for backward compatibility and regex cleanups (thanks to @anseki for suggestions, #77)
- 3.0.0
Breaking changes:
- If a file requested by `@include` or `@extend` can not be found, `preprocess` will now throw by default
with a possibility to opt in to the legacy behavior via the `fileNotFoundSilentFail` option (@BendingBender, #35).
- Fixed multiple issues with newlines (@BendingBender, #8), this may result in output that differs from earlier
versions.
- The `srcDir` option was moved to the options object and now defaults to `process.cwd` instead of throwing by
default (@BendingBender, #68)
New functionality:
- All block directives (ones that have a start and an end token, like `@if`/`@endif`) are now processed recursively (@Frizi, #61)
- Added hidden by default configuration blocks for `js` (@mallowigi, #40) and `html` (@Frizi, #66)
Fixes:
- fixed `@exec` in files included via `@include` and `@extend` (@BendingBender, #58)
- changed `@extend` and `@exclude` html regex so that directives may appear more than once in one line (@BendingBender, #36)
- fixed multiple issues with coffescript syntax (@BendingBender, #39)
- fixed `@if` and `@foreach` to not require trailing whitespace (@BendingBender, #74)
- 2.3.1 Fixed @echo and @exec directives to allow `-` and `*` characters, fixed @exec with multiple params (@BendingBender, #21, #45, #51, #54).
- 2.3.0 Added support for @include-static (@BendingBender)
- 2.2.0 Added support for @foreach and @extend (@orionstein)
- 2.1.1 Added support for .styl files via js regex (@nsonnad)
- 2.1.0 Added automatic support for numerous formats, merged @exec, hidden by default html tags, added simple directives
- 2.0.0 Added ability to echo strings, added conditional comments, removed lodash, merged 17, 13, 15, 16
- 1.2.0 Added processing for hash-style comments (@marsch). Added more file aliases.
- 1.1.0 Added deep inclusion, fixed sequential ifs
- 1.0.1 Fixed multiple inline echo statements
- 1.0.0 Pulled from grunt-preprocess to stand alone
## License
Copyright Jarrod Overson
Written by Jarrod Overson
Licensed under the Apache 2.0 license.
[npm-image]: https://nodei.co/npm/preprocess.png?downloads=true
[npm-url]: https://www.npmjs.com/package/preprocess
[linux-ci-image]: https://img.shields.io/travis/jsoverson/preprocess/master.svg?style=flat-square&label=Linux%20build
[linux-ci-url]: https://travis-ci.org/jsoverson/preprocess
[windows-ci-image]: https://img.shields.io/appveyor/ci/BendingBender/preprocess/master.svg?style=flat-square&label=Windows%20build
[windows-ci-url]: https://ci.appveyor.com/project/BendingBender/preprocess
[deps-image]: https://img.shields.io/david/jsoverson/preprocess.svg?style=flat-square
[deps-url]: https://david-dm.org/jsoverson/preprocess
[dev-deps-image]: https://img.shields.io/david/dev/jsoverson/preprocess.svg?style=flat-square
[dev-deps-url]: https://david-dm.org/jsoverson/preprocess#info=devDependencies
[coverage-image]: https://img.shields.io/coveralls/jsoverson/preprocess/master.svg?style=flat-square
[coverage-url]: https://coveralls.io/r/jsoverson/preprocess?branch=master
+439
View File
@@ -0,0 +1,439 @@
/*
* preprocess
* https://github.com/onehealth/preprocess
*
* Copyright (c) 2012 OneHealth Solutions, Inc.
* Written by Jarrod Overson - http://jarrodoverson.com/
* Licensed under the Apache 2.0 license.
*/
'use strict';
exports.preprocess = preprocess;
exports.preprocessFile = preprocessFile;
exports.preprocessFileSync = preprocessFileSync;
var path = require('path'),
fs = require('fs'),
os = require('os'),
delim = require('./regexrules'),
XRegExp = require('xregexp');
function preprocessFile(srcFile, destFile, context, callback, options) {
options = getOptionsForFile(srcFile, options);
context.src = srcFile;
fs.readFile(srcFile, function (err, data) {
if (err) return callback(err, data);
var parsed = preprocess(data, context, options);
fs.writeFile(destFile, parsed, callback);
});
}
function preprocessFileSync(srcFile, destFile, context, options) {
options = getOptionsForFile(srcFile, options);
context.src = srcFile;
var data = fs.readFileSync(srcFile);
var parsed = preprocess(data, context, options);
return fs.writeFileSync(destFile, parsed);
}
function getOptionsForFile(srcFile, options) {
options = options || {};
options.srcDir = options.srcDir || path.dirname(srcFile);
options.type = options.type || getExtension(srcFile);
return options;
}
function getExtension(filename) {
var ext = path.extname(filename||'').split('.');
return ext[ext.length - 1];
}
function preprocess(src, context, typeOrOptions) {
src = src.toString();
context = context || process.env;
// default values
var options = {
fileNotFoundSilentFail: false,
srcDir: process.cwd(),
srcEol: getEolType(src),
type: delim['html']
};
// needed for backward compatibility with 2.x.x series
if (typeof typeOrOptions === 'string') {
typeOrOptions = {
type: typeOrOptions
};
}
// needed for backward compatibility with 2.x.x series
if (typeof context.srcDir === "string") {
typeOrOptions = typeOrOptions || {};
typeOrOptions.srcDir = context.srcDir;
}
if (typeOrOptions && typeof typeOrOptions === 'object') {
options.srcDir = typeOrOptions.srcDir || options.srcDir;
options.fileNotFoundSilentFail = typeOrOptions.fileNotFoundSilentFail || options.fileNotFoundSilentFail;
options.srcEol = typeOrOptions.srcEol || options.srcEol;
options.type = delim[typeOrOptions.type] || options.type;
}
context = copy(context);
return preprocessor(src, context, options);
}
function preprocessor(src, context, opts, noRestoreEol) {
src = normalizeEol(src);
var rv = src;
// 不支持该语法,无需执行,大字符串时,该正则性能极低(比如包含较大base64时)(https://github.com/dcloudio/uni-app/issues/4661
// rv = replace(rv, opts.type.include, processIncludeDirective.bind(null, false, context, opts));
// if (opts.type.extend) {
// rv = replaceRecursive(rv, opts.type.extend, function(startMatches, endMatches, include, recurse) {
// var file = (startMatches[1] || '').trim();
// var extendedContext = copy(context);
// var extendedOpts = copy(opts);
// extendedContext.src = path.join(opts.srcDir, file);
// extendedOpts.srcDir = path.dirname(extendedContext.src);
// var fileContents = getFileContents(extendedContext.src, opts.fileNotFoundSilentFail, context.src);
// if (fileContents.error) {
// return fileContents.contents;
// }
// var extendedSource = preprocessor(fileContents.contents, extendedContext, extendedOpts, true).trim();
// if (extendedSource) {
// include = include.replace(/^\n?|\n?$/g, '');
// return replace(extendedSource, opts.type.extendable, recurse(include));
// } else {
// return '';
// }
// });
// }
// if (opts.type.foreach) {
// rv = replaceRecursive(rv, opts.type.foreach, function(startMatches, endMatches, include, recurse) {
// var variable = (startMatches[1] || '').trim();
// var forParams = variable.split(' ');
// if (forParams.length === 3) {
// var contextVar = forParams[2];
// var arrString = getDeepPropFromObj(context, contextVar);
// var eachArr;
// if (arrString.match(/\{(.*)\}/)) {
// eachArr = JSON.parse(arrString);
// } else if (arrString.match(/\[(.*)\]/)) {
// eachArr = arrString.slice(1, -1);
// eachArr = eachArr.split(',');
// eachArr = eachArr.map(function(arrEntry){
// return arrEntry.replace(/\s*(['"])(.*)\1\s*/, '$2');
// });
// } else {
// eachArr = arrString.split(',');
// }
// var replaceToken = new RegExp(XRegExp.escape(forParams[0]), 'g');
// var recursedInclude = recurse(include);
// return Object.keys(eachArr).reduce(function(stringBuilder, arrKey){
// var arrEntry = eachArr[arrKey];
// return stringBuilder + recursedInclude.replace(replaceToken, arrEntry);
// }, '');
// } else {
// return '';
// }
// });
// }
// if (opts.type.exclude) {
// rv = replaceRecursive(rv, opts.type.exclude, function(startMatches, endMatches, include, recurse){
// var test = (startMatches[1] || '').trim();
// return testPasses(test,context) ? '' : recurse(include);
// });
// }
if (opts.type.if) {
rv = replaceRecursive(rv, opts.type.if, function (startMatches, endMatches, include, recurse) {
// I need to recurse first, so I don't catch "inner" else-directives
var recursed = recurse(include);
// look for the first else-directive
var matches = opts.type.else && recursed.match(new RegExp(opts.type.else));
var match = (matches || [""])[0];
var index = match ? recursed.indexOf(match) : recursed.length;
var ifBlock = recursed.substring(0, index);
var elseBlock = recursed.substring(index + match.length); // empty string if no else-directive
var variant = startMatches[1];
var test = (startMatches[2] || '').trim();
// fixed by xxxxxx
var startLine = padContent(startMatches.input)
var endLine = padContent(endMatches.input)
switch(variant) {
case 'if':
case 'ifdef': // fixed by xxxxxx
return testPasses(test, context) ? (startLine + ifBlock + endLine) : (startLine + padContent(ifBlock) + padContent(match || '') + elseBlock + endLine);
case 'ifndef':
return !testPasses(test, context) ? (startLine + ifBlock + endLine) : (startLine + padContent(ifBlock) + padContent(match || '') + elseBlock + endLine);
// case 'ifdef':
// return typeof getDeepPropFromObj(context, test) !== 'undefined' ? ifBlock : elseBlock;
// case 'ifndef':
// return typeof getDeepPropFromObj(context, test) === 'undefined' ? ifBlock : elseBlock;
default:
throw new Error('Unknown if variant ' + variant + '.');
}
});
}
// rv = replace(rv, opts.type.echo, function (match, variable) {
// variable = (variable || '').trim();
// // if we are surrounded by quotes, echo as a string
// var stringMatch = variable.match(/^(['"])(.*)\1$/);
// if (stringMatch) return stringMatch[2];
// var arrString = getDeepPropFromObj(context, variable);
// return typeof arrString !== 'undefined' ? arrString : '';
// });
// rv = replace(rv, opts.type.exec, function (match, name, value) {
// name = (name || '').trim();
// value = value || '';
// var params = value.split(',');
// var stringRegex = /^['"](.*)['"]$/;
// params = params.map(function(param){
// param = param.trim();
// if (stringRegex.test(param)) { // handle string parameter
// return param.replace(stringRegex, '$1');
// } else { // handle variable parameter
// return getDeepPropFromObj(context, param);
// }
// });
// var fn = getDeepPropFromObj(context, name);
// if (!fn || typeof fn !== 'function') return '';
// return fn.apply(context, params);
// });
// rv = replace(rv, opts.type['include-static'], processIncludeDirective.bind(null, true, context, opts));
if (!noRestoreEol) {
rv = restoreEol(rv, opts.srcEol);
}
return rv;
}
function getEolType(source) {
var eol;
var foundEolTypeCnt = 0;
if (source.indexOf('\r\n') >= 0) {
eol = '\r\n';
foundEolTypeCnt++;
}
if (/\r[^\n]/.test(source)) {
eol = '\r';
foundEolTypeCnt++;
}
if (/[^\r]\n/.test(source)) {
eol = '\n';
foundEolTypeCnt++;
}
if (eol == null || foundEolTypeCnt > 1) {
eol = os.EOL;
}
return eol;
}
function normalizeEol(source, indent) {
// only process any kind of EOL if indentation has to be added, otherwise replace only non \n EOLs
if (indent) {
source = source.replace(/(?:\r?\n)|\r/g, '\n' + indent);
} else {
source = source.replace(/(?:\r\n)|\r/g, '\n');
}
return source;
}
function restoreEol(normalizedSource, originalEol) {
if (originalEol !== '\n') {
normalizedSource = normalizedSource.replace(/\n/g, originalEol);
}
return normalizedSource;
}
function replace(rv, rule, processor) {
var isRegex = typeof rule === 'string' || rule instanceof RegExp;
var isArray = Array.isArray(rule);
if (isRegex) {
rule = [new RegExp(rule,'gmi')];
} else if (isArray) {
rule = rule.map(function(subRule){
return new RegExp(subRule,'gmi');
});
} else {
throw new Error('Rule must be a String, a RegExp, or an Array.');
}
return rule.reduce(function(rv, rule){
return rv.replace(rule, processor);
}, rv);
}
function replaceRecursive(rv, rule, processor) {
if(!rule.start || !rule.end) {
throw new Error('Recursive rule must have start and end.');
}
var startRegex = new RegExp(rule.start, 'mi');
var endRegex = new RegExp(rule.end, 'mi');
function matchReplacePass(content) {
var matches = XRegExp.matchRecursive(content, rule.start, rule.end, 'gmi', {
valueNames: ['between', 'left', 'match', 'right']
});
var matchGroup = {
left: null,
match: null,
right: null
};
return matches.reduce(function (builder, match) {
switch(match.name) {
case 'between':
builder += match.value;
break;
case 'left':
matchGroup.left = startRegex.exec(match.value);
break;
case 'match':
matchGroup.match = match.value;
break;
case 'right':
matchGroup.right = endRegex.exec(match.value);
builder += processor(matchGroup.left, matchGroup.right, matchGroup.match, matchReplacePass);
break;
}
return builder;
}, '');
}
return matchReplacePass(rv);
}
function processIncludeDirective(isStatic, context, opts, match, linePrefix, file) {
file = (file || '').trim();
var indent = linePrefix.replace(/\S/g, ' ');
var includedContext = copy(context);
var includedOpts = copy(opts);
includedContext.src = path.join(opts.srcDir,file);
includedOpts.srcDir = path.dirname(includedContext.src);
var fileContents = getFileContents(includedContext.src, opts.fileNotFoundSilentFail, context.src);
if (fileContents.error) {
return linePrefix + fileContents.contents;
}
var includedSource = fileContents.contents;
if (isStatic) {
includedSource = fileContents.contents;
} else {
includedSource = preprocessor(fileContents.contents, includedContext, includedOpts, true);
}
includedSource = normalizeEol(includedSource, indent);
if (includedSource) {
return linePrefix + includedSource;
} else {
return linePrefix;
}
}
function getTestTemplate(test) {
/*jshint evil:true*/
test = test || 'true';
test = test.trim();
// force single equals replacement
// fixed by xxxxxx 不替换,会影响 >= 等判断
// test = test.replace(/([^=!])=([^=])/g, '$1==$2');
// fixed by xxxxxx
test = test.replace(/-/g, '_')
return new Function("context", "with (context||{}){ return ( " + test + " ); }");
}
// fixed by xxxxxx
function testPasses(test, context) {
var testFn = getTestTemplate(test)
try {
return testFn(context, getDeepPropFromObj)
} catch (e) {}
return false
}
function getFileContents(path, failSilent, requesterPath) {
try {
fs.statSync(path);
} catch (e) {
if (failSilent) {
return {error: true, contents: path + ' not found!'};
} else {
var errMsg = path;
errMsg = requesterPath ? errMsg + ' requested from ' + requesterPath : errMsg;
errMsg += ' not found!';
throw new Error(errMsg);
}
}
return {error: false, contents: fs.readFileSync(path).toString()};
}
function copy(obj) {
return Object.keys(obj).reduce(function (copyObj, objKey) {
copyObj[objKey] = obj[objKey];
return copyObj;
}, {});
}
function getDeepPropFromObj(obj, propPath) {
propPath.replace(/\[([^\]+?])\]/g, '.$1');
propPath = propPath.split('.');
// fast path, no need to loop if structurePath contains only a single segment
if (propPath.length === 1) {
return obj[propPath[0]];
}
// loop only as long as possible (no exceptions for null/undefined property access)
propPath.some(function (pathSegment) {
obj = obj[pathSegment];
return (obj == null);
});
return obj;
}
// fixed by xxxxxx
const splitRE = /\r?\n/g
function padContent(content) {
return Array(content.split(splitRE).length).join('\n')
}
+121
View File
@@ -0,0 +1,121 @@
module.exports = {
simple : {
echo : "^#echo[ \t]+(.*?)[ \t]*$",
exec : "^#exec[ \t]+(\\S+)[ \t]*\\((.*)\\)[ \t]*$",
include : "^(.*)#include(?!-)[ \t]+(.*?)[ \t]*$", // allow prefix characters to specify the indent level of included file
'include-static' : "^(.*)#include-static[ \t]+(.*?)[ \t]*$"
},
html : {
echo : "<!--[ \t]*#echo[ \t]+(.*?)[ \t]*(?:-->|!>)",
exec : "<!--[ \t]*#exec[ \t]+(\\S+)[ \t]*\\((.*)\\)[ \t]*(?:-->|!>)",
include : "(.*)<!--[ \t]*#include(?!-)[ \t]+(.*?)[ \t]*(?:-->|!>)",
'include-static' : "(.*)<!--[ \t]*#include-static[ \t]+(.*?)[ \t]*(?:-->|!>)",
exclude : {
start : "[ \t]*<!--[ \t]*#exclude(?:[ \t]+(.*?))?[ \t]*(?:-->|!>)(?:[ \t]*\n+)?",
end : "[ \t]*<!--[ \t]*#endexclude[ \t]*(?:-->|!>)(?:[ \t]*\n)?"
},
extend : {
start : "[ \t]*<!--[ \t]*#extend(?!able)[ \t]+(.*?)[ \t]*(?:-->|!>)(?:[ \t]*\n+)?",
end : "[ \t]*<!--[ \t]*#endextend[ \t]*(?:-->|!>)(?:[ \t]*\n)?"
},
extendable : "<!--[ \t]*#extendable[ \t]*(?:-->|!>)",
if : {
start : "[ \t]*<!--[ \t]*#(ifndef|ifdef|if)[ \t]+(.*?)[ \t]*(?:-->|!>)(?:[ \t]*\n+)?",
end : "[ \t]*<!(?:--)?[ \t]*#endif[ \t]*(?:-->|!>)(?:[ \t]*\n)?"
},
else : "[ \t]*<!(?:--)?[ \t]*#else[ \t]*(?:-->|!>)(?:[ \t]*\n)?",
foreach : {
start : "[ \t]*<!--[ \t]*#foreach[ \t]+(.*?)[ \t]*(?:-->|!>)(?:[ \t]*\n+)?",
end : "[ \t]*<!(?:--)?[ \t]*#endfor[ \t]*(?:-->|!>)(?:[ \t]*\n)?"
}
},
js : {
echo : [
"/\\*[ \t]*#echo[ \t]+(.*?)[ \t]*\\*(?:\\*|/)",
"//[ \t]*#echo[ \t]+(.*?)[ \t]*$"
],
exec : "(?://|/\\*)[ \t]*#exec[ \t]+(\\S+?)[ \t]*\\((.*)\\)[ \t]*(?:\\*(?:\\*|/))?",
include : [
"^(.*)/\\*[ \t]*#include(?!-)[ \t]+(.*?)[ \t]*\\*(?:\\*|/)",
"^(.*)//[ \t]*#include(?!-)[ \t]+(.*?)[ \t]*$"
],
'include-static': [
"^(.*)/\\*[ \t]*#include-static[ \t]+(.*?)[ \t]*\\*(?:\\*|/)",
"^(.*)//[ \t]*#include-static[ \t]+(.*?)[ \t]*$"
],
exclude : {
start : "[ \t]*(?://|/\\*)[ \t]*#exclude(?:[ \t]+([^\n*]*))?[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n+)?",
end : "[ \t]*(?://|/\\*)[ \t]*#endexclude[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n)?"
},
extend : {
start : "[ \t]*(?://|/\\*)[ \t]*#extend(?!able)[ \t]+([^\n*]*)(?:\\*(?:\\*|/))?(?:[ \t]*\n+)?",
end : "[ \t]*(?://|/\\*)[ \t]*#endextend[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n)?"
},
extendable : "[ \t]*(?://|/\\*)[ \t]*#extendable[ \t]*(?:\\*/)?",
if : {
start : "[ \t]*(?://|/\\*)[ \t]*#(ifndef|ifdef|if)[ \t]+([^\n*]*)(?:\\*(?:\\*|/))?(?:[ \t]*\n+)?",
end : "[ \t]*(?://|/\\*)[ \t]*#endif[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n)?"
},
else : "[ \t]*(?://|/\\*)[ \t]*#else[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n)?",
foreach : {
start : "[ \t]*(?://|/\\*)[ \t]*#foreach[ \t]+([^\n*]*)(?:\\*(?:\\*|/))?(?:[ \t]*\n+)?",
end : "[ \t]*(?://|/\\*)[ \t]*#endfor[ \t]*(?:\\*(?:\\*|/))?(?:[ \t]*\n)?"
}
},
coffee : {
echo : [
"###+[ \t]*#echo[ \t]+(.*?)[ \t]###",
"#+[ \t]*#echo[ \t]+(.*?)[ \t]*$"
],
exec : "#+[ \t]*#exec[ \t]+(\\S+)[ \t]*\\((.*)\\)[ \t]*$",
include : "^(.*?)#+[ \t]*#include(?!-)[ \t]+(.*?)[ \t]*$",
'include-static' : "^(.*?)#+[ \t]*#include-static[ \t]+(.*?)[ \t]*$",
exclude : {
start : "^[ \t]*#+[ \t]*#exclude(?:[ \t]+(.*?))?[ \t]*\n+",
end : "^[ \t]*#+[ \t]*#endexclude[ \t]*\n?"
},
extend : {
start : "^[ \t]*#+[ \t]*#extend(?!able)[ \t]+(.*?)\n+",
end : "^[ \t]*#+[ \t]*#endextend[ \t]*\n?"
},
extendable : "^[ \t]*#+[ \t]*#extendable[ \t]*$",
if : {
start : "^[ \t]*#+[ \t]*#(ifndef|ifdef|if)[ \t]+(.*?)[ \t]*\n+",
end : "^[ \t]*#+[ \t]*#endif[ \t]*\n?"
},
else : "^[ \t]*#+[ \t]*#else[ \t]*\n?",
foreach : {
start : "^[ \t]*#+[ \t]*#foreach[ \t]+(.*?)[ \t]*\n+",
end : "^[ \t]*#+[ \t]*#endfor[ \t]*\n?"
}
}
};
module.exports.xml = module.exports.html;
module.exports.javascript = module.exports.js;
module.exports.jsx = module.exports.js;
module.exports.json = module.exports.js;
module.exports.c = module.exports.js;
module.exports.cc = module.exports.js;
module.exports.cpp = module.exports.js;
module.exports.cs = module.exports.js;
module.exports.csharp = module.exports.js;
module.exports.java = module.exports.js;
module.exports.less = module.exports.js;
module.exports.sass = module.exports.js;
module.exports.scss = module.exports.js;
module.exports.css = module.exports.js;
module.exports.php = module.exports.js;
module.exports.ts = module.exports.js;
module.exports.tsx = module.exports.js;
module.exports.peg = module.exports.js;
module.exports.pegjs = module.exports.js;
module.exports.jade = module.exports.js;
module.exports.styl = module.exports.js;
module.exports.go = module.exports.js;
module.exports.bash = module.exports.coffee;
module.exports.shell = module.exports.coffee;
module.exports.sh = module.exports.coffee;
+68
View File
@@ -0,0 +1,68 @@
{
"name": "preprocess",
"description": "Preprocess directives in HTML, JavaScript, etc directives based off variable context",
"version": "3.2.0",
"homepage": "https://github.com/jsoverson/preprocess",
"author": {
"name": "Jarrod Overson",
"email": "jsoverson@gmail.com",
"url": "http://jarrodoverson.com/"
},
"repository": {
"type": "git",
"url": "git://github.com/jsoverson/preprocess.git"
},
"bugs": {
"url": "https://github.com/jsoverson/preprocess/issues"
},
"licenses": [
{
"type": "Apache 2.0",
"url": "https://github.com/jsoverson/preprocess/blob/master/LICENSE"
}
],
"main": "lib/preprocess.js",
"engines": {
"node": ">= 0.10.0"
},
"scripts": {
"test": "grunt test",
"ci": "grunt ci"
},
"dependencies": {
"xregexp": "3.1.0"
},
"devDependencies": {
"chai": "^3.5.0",
"chai-spies": "^0.7.0",
"grunt": "^0.4.5",
"grunt-benchmark": "^0.3.0",
"grunt-cli": "^0.1.13",
"grunt-contrib-clean": "^1.0.0",
"grunt-contrib-copy": "^0.8.0",
"grunt-contrib-jshint": "^1.0.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-coveralls": "^1.0.0",
"grunt-deps-ok": "^0.9.0",
"grunt-mocha-istanbul": "^3.0.1",
"grunt-mocha-test": "^0.12.7",
"istanbul": "^0.4.2",
"load-grunt-tasks": "^3.4.0",
"mocha": "^2.4.5",
"time-grunt": "^1.3.0",
"travis-cov": "^0.2.5"
},
"keywords": [
"directive",
"ENV",
"environment",
"ifdef",
"ifndef",
"echo",
"include",
"exclude",
"process",
"preprocess",
"pragma"
]
}
File diff suppressed because it is too large Load Diff