Если необходима портативная версия Node.js, то достаточно просто скачать файл
http://nodejs.org/dist/latest/node.exe
и поместить его в папку с вашими серверными JavaScript-файлами.
После этого в командной строке перейдите в папку вашего проекта и запустите ваш скрипт стандартным образом:
\path\to\saved\node.exe scriptname.js
При желании вы можете прописать ссылку на файл node.exe в системную переменную PATH, чтобы запускать ваши скрипты из любого места так:
node scriptname.js
Если вам нужен NPM, то скачайте его архив ZIP по ссылке
https://github.com/npm/npm
и распакуйте его в папку, в которую поместили файл node.exe.
Переименуйте папку с файлами NPM в "npm", убрав из названия номер версии версию, если он есть.
Создайте рядом с файлом node.exe папку "node_modules" и перенесите в неё папку "npm".
Скопируйте в папку с файлом node.exe файл npm.cmd из папки "node_modules/npm/bin/"
После этого NPM автоматически заработает из командной строки стандартным образом:
npm -h
Когда вам потребуется обновить Node.js, то просто замените файл node.exe на новую версию.
А для обновления NPM выполните команду:
npm update npm -g
или удалите старую папку node_modules и распакуйте в проект архив ZIP с новой версией NPM.
У меня стартовая структура проекта выглядит в итоге так:
C:\test\server.js - мой сценарий JavaScript
C:\test\node.exe - файл новой версии Node.js
C:\test\node_modules\npm - папка из архива ZIP с новой версией NPM
C:\test\npm.cmd - файл из архива ZIP с новой версией NPM
Если NPM не может скачать пакеты в Node.js для версии выше 0.12, то необходимо в командной строке выполнить команду:
npm config set strict-ssl=false
После этого пакеты начнут скачиваться.
понедельник, 8 февраля 2016 г.
вторник, 2 февраля 2016 г.
Настройка TypeScript + Grunt
1. В папку с проектом установить модули
npm install grunt
npm install grunt-contrib-watch
npm install grunt-typescript
npm install grunt-ts
npm install grunt-tslint
npm install grunt-jsbeautifier
npm install grunt-newer
2. Создать файл Gruntfile.js с кодом
module.exports = function (grunt) {
var tsFiles = ['./js/**/*.ts'];
grunt.initConfig({
// Скомпилироать файлы TypeScript в JavaScript
typescript: {
base: {
src: tsFiles
, dest: '' // '' - компиляция в разные файлы или './js/single.js' - компиляция в единый файл
, options: {
module: 'amd' // 'amd' или 'commonjs'
, target: 'es3' // 'es6', 'es5' или 'es3' (по умолчанию)
, sourceMap: false // true, false - создавать ли файл '.map'
, module: 'amd' // генерация кода модулей в стиле: 'commonjs' (по умолчанию), 'amd', 'system' или 'umd'
, noImplicitAny: false // true // true, false - предупреждать ли о наличи в коде переменных и фунций с типом ':any'
, removeComments: false // true, false - удалять ли комментарии из итогового файла
, preserveConstEnums: false // true, false - не стирать определение const enum в генерируемом коде
, suppressImplicitAnyIndexErrors: true // true, false - подавлять ли сообщения об ошибках типа noImplicitAny для индексируемых объектов
, noEmitOnError: true // true (по умолчанию), false - не компилировать файл, если во время его проверки найдена ошибка
, declaration: false // true, false - создавать ли соотвествующий файл .d.ts
, nolib: true // true, false - не включать по умолчанию файл lib.d.ts в global declarations
, noResolve: false // true, false - не добавлять сслыку описание (///reference) или module import в список компилируемых файлов
, experimentalDecorators: true // true, false - включить экспермментальную поддержку декораторов из ES7
, emitDecoratorMetadata: true // true, false - сгенерировать метаданные для декораторов
, newLine: 'CRLF' // 'CRLF' (windows), 'LF' (unix) - тип переноса строк в компилируемых файлах
, inlineSourceMap: false // true, false - сгенерировать один файл source map вместо нескольких отдельных файлов
, inlineSources: false // true, false - сгенирировать инлайновый source map внутри единого файла (требует, чтобы был inlineSourceMap: true)
, noEmitHelpers: true // true, false - не генерировать вспомогательные функции в компилируемых файлах подобных '__extends'
, keepDirectoryHierarchy: true // true, false
/*
, references: [ // set auto reference libraries
'core' // lib.core.d.ts
, 'dom' // lib.dom.d.ts
, 'scriptHost' // lib.scriptHost.d.ts
, 'webworker' // lib.webworker.d.ts
//, 'path/to/reference/files/** /*.d.ts'
]
, watch: { //{} или false
path: 'path/to/typescript/files' // или ['path/to/typescript/file1', 'path/to/typescript/file2']
, before: ['beforetask'] // ['clean']
, after: ['aftertask'] // ['minify']
, atBegin: true // true, false (по умолчания) - запустить ли задачи вместе с вотчером
}
*/
}
}
}
// Другой компилятор TypeScript в JavaScript
, ts: {
default : {
src: ['js/test/module1.ts', 'js/test/module2.ts', 'js/test/module3.ts'] // ['js/**/*.ts']
// , out: 'js/test/main.js'
, options: {
declaration: false // true | false (default) - Generates a .d.ts definitions file for compiled TypeScript files
, emitDecoratorMetadata: false // true | false (default) - Emit metadata for type/parameter decorators.
, experimentalDecorators: false // true | false (default) - Enables experimental support for ES7 decorators
, inlineSourceMap: false // true | false (default) - Emit a single file that includes source maps instead of emitting a separate .js.map file.
, inlineSources: false // true | false (default) - Emit the TypeScript source alongside the sourcemaps within a single file. Requires inlineSourceMap to be set.
, isolatedModules: false // true | false (default) - Ensures that the output is safe to only emit single files by making cases that break single-file transpilation an error
, mapRoot: '' // '/maps' - Specifies the location where debugger should locate map files instead of generated locations.
, module: 'amd' // 'amd' (default) | 'commonjs' | 'system' | 'umd' | '' - Specify module style for code generation
, newLine: 'CRLF' // 'CRLF' | 'LF' | '' (default) - Explicitly specify newline character (CRLF or LF); if omitted, uses OS default.
, noEmit: false // true | false (default) - Check, but do not emit JS, even in the absence of errors.
, noEmitHelpers: true // true | false (default) - Do not generate custom helper functions like __extends in compiled output.
, noImplicitAny: false // true | false (default) - Warn on expressions and declarations with an implied any type.
, noResolve: true // true | false (default) - Do not add triple-slash references or module import targets to the compilation context.
, out: '' // '' - компиляция в разные файлы или './js/single.js' - компиляция в единый файл - Concatenate and emit output to a single file.
, outDir: '' // 'dist' - Redirect output structure to the directory.
, preserveConstEnums: false // true | false (default) - Const enums will be kept as enums in the emitted JS.
, removeComments: false // true (default)| false - Configures if comments should be included in the output
, sourceMap: false // true (default) | false - Generates corresponding .map file
, sourceRoot: '' // '/dev' - Specifies the location where debugger should locate TypeScript files instead of source locations.
, suppressImplicitAnyIndexErrors: false // true | false (default) - If set to true, TypeScript will allow access to properties of an object by string indexer when noImplicitAny is active, even if TypeScript doesn't know about them. This setting has no effect unless noImplicitAny is active.
, target: 'es3' // 'es3' | 'es5' (default) | 'es6' - Specify ECMAScript target version: 'es3', 'es5', or 'es6'
}
}
}
// Проверить оформление кода в TypeScript-файлах
, tslint: {
options: {
configuration: grunt.file.readJSON('tslint.json')
}
, all: {
src: tsFiles
}
}
// Форматирование кода JavaScript
, 'jsbeautifier' : {
files : ['js/**/*.js']
, options : {
js: {
braceStyle: 'collapse'
, breakChainedMethods: false
, e4x: false
, evalCode: false
, indentChar: ' '
, indentLevel: 0
, indentSize: 4
, indentWithTabs: false
, jslintHappy: true
, keepArrayIndentation: false
, keepFunctionIndentation: false
, maxPreserveNewlines: 10
, preserveNewlines: true
, spaceBeforeConditional: true
, spaceInParen: false
, unescapeStrings: false
, wrapLineLength: 0
, endWithNewline: false
}
}
}
// Начать отслеживание изменений кода файлов
, watch: {
scripts: {
files: tsFiles
, tasks: [
// 'newer:tslint'
//, 'typescript'
'ts'
, 'jsbeautifier'
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-ts');
grunt.loadNpmTasks('grunt-tslint');
grunt.loadNpmTasks('grunt-jsbeautifier');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('default', [
// 'newer:tslint'
//, 'typescript'
'ts'
, 'jsbeautifier'
, 'watch'
]);
};
3. Создать файл rungrunt.js с кодом
require('grunt').cli();
4. Создать файл tsling.json с кодом
{
"rules": {
"ban": false
, "class-name": true
, "comment-format": [true, "check-space"]
, "curly": true
, "eofline": false
, "forin": true
, "indent": [true, "spaces"]
, "jsdoc-format": true
, "label-position": true
, "label-undefined": true
, "max-line-length": [true, 500]
, "member-access": true
, "member-ordering": [
true
, "public-before-private"
, "static-before-instance"
, "variables-before-functions"
]
, "no-any": true
, "no-arg": true
, "no-bitwise": true
, "no-console": [
true
, "debug"
, "info"
, "time"
, "timeEnd"
, "trace"
]
, "no-consecutive-blank-lines": true
, "no-construct": true
, "no-constructor-vars": true
, "no-debugger": false
, "no-duplicate-key": true
, "no-duplicate-variable": true
, "no-empty": true
, "no-eval": true
, "no-internal-module": true
, "no-string-literal": false
, "no-trailing-comma": true
, "no-trailing-whitespace": true
, "no-unreachable": true
, "no-unused-expression": true
, "no-unused-variable": true
, "no-use-before-declare": true
, "one-line": [
true
, "check-open-brace"
, "check-catch"
, "check-else"
, "check-whitespace"
]
, "quotemark": [true, "single"]
, "radix": true
, "semicolon": true
, "switch-default": true
, "triple-equals": [true, "allow-null-check"]
, "typedef": [
true
, "call-signature"
, "parameter"
, "property"
, "variable-declaration"
, "member-variable-declarations"
]
, "typedef-whitespace": [
true
, {
"call-signature": "nospace"
, "index-signature": "nospace"
, "parameter": "nospace"
, "property-declaration": "nospace"
, "variable-declaration": "nospace"
}
]
, "variable-name": false
, "whitespace": [
true
, "check-branch"
, "check-decl"
, "check-module"
, "check-operator"
, "check-separator"
]
}
}
5. Поместить исходные TypeScript-файлы в папку js
js/module-1.ts
js/module-2.ts
6. Скомпилировать TypeScript-файлы в JavaScript-файлы командой
node rungrunt.js
npm install grunt
npm install grunt-contrib-watch
npm install grunt-typescript
npm install grunt-ts
npm install grunt-tslint
npm install grunt-jsbeautifier
npm install grunt-newer
module.exports = function (grunt) {
var tsFiles = ['./js/**/*.ts'];
grunt.initConfig({
// Скомпилироать файлы TypeScript в JavaScript
typescript: {
base: {
src: tsFiles
, dest: '' // '' - компиляция в разные файлы или './js/single.js' - компиляция в единый файл
, options: {
module: 'amd' // 'amd' или 'commonjs'
, target: 'es3' // 'es6', 'es5' или 'es3' (по умолчанию)
, sourceMap: false // true, false - создавать ли файл '.map'
, module: 'amd' // генерация кода модулей в стиле: 'commonjs' (по умолчанию), 'amd', 'system' или 'umd'
, noImplicitAny: false // true // true, false - предупреждать ли о наличи в коде переменных и фунций с типом ':any'
, removeComments: false // true, false - удалять ли комментарии из итогового файла
, preserveConstEnums: false // true, false - не стирать определение const enum в генерируемом коде
, suppressImplicitAnyIndexErrors: true // true, false - подавлять ли сообщения об ошибках типа noImplicitAny для индексируемых объектов
, noEmitOnError: true // true (по умолчанию), false - не компилировать файл, если во время его проверки найдена ошибка
, declaration: false // true, false - создавать ли соотвествующий файл .d.ts
, nolib: true // true, false - не включать по умолчанию файл lib.d.ts в global declarations
, noResolve: false // true, false - не добавлять сслыку описание (///reference) или module import в список компилируемых файлов
, experimentalDecorators: true // true, false - включить экспермментальную поддержку декораторов из ES7
, emitDecoratorMetadata: true // true, false - сгенерировать метаданные для декораторов
, newLine: 'CRLF' // 'CRLF' (windows), 'LF' (unix) - тип переноса строк в компилируемых файлах
, inlineSourceMap: false // true, false - сгенерировать один файл source map вместо нескольких отдельных файлов
, inlineSources: false // true, false - сгенирировать инлайновый source map внутри единого файла (требует, чтобы был inlineSourceMap: true)
, noEmitHelpers: true // true, false - не генерировать вспомогательные функции в компилируемых файлах подобных '__extends'
, keepDirectoryHierarchy: true // true, false
/*
, references: [ // set auto reference libraries
'core' // lib.core.d.ts
, 'dom' // lib.dom.d.ts
, 'scriptHost' // lib.scriptHost.d.ts
, 'webworker' // lib.webworker.d.ts
//, 'path/to/reference/files/** /*.d.ts'
]
, watch: { //{} или false
path: 'path/to/typescript/files' // или ['path/to/typescript/file1', 'path/to/typescript/file2']
, before: ['beforetask'] // ['clean']
, after: ['aftertask'] // ['minify']
, atBegin: true // true, false (по умолчания) - запустить ли задачи вместе с вотчером
}
*/
}
}
}
// Другой компилятор TypeScript в JavaScript
, ts: {
default : {
src: ['js/test/module1.ts', 'js/test/module2.ts', 'js/test/module3.ts'] // ['js/**/*.ts']
// , out: 'js/test/main.js'
, options: {
declaration: false // true | false (default) - Generates a .d.ts definitions file for compiled TypeScript files
, emitDecoratorMetadata: false // true | false (default) - Emit metadata for type/parameter decorators.
, experimentalDecorators: false // true | false (default) - Enables experimental support for ES7 decorators
, inlineSourceMap: false // true | false (default) - Emit a single file that includes source maps instead of emitting a separate .js.map file.
, inlineSources: false // true | false (default) - Emit the TypeScript source alongside the sourcemaps within a single file. Requires inlineSourceMap to be set.
, isolatedModules: false // true | false (default) - Ensures that the output is safe to only emit single files by making cases that break single-file transpilation an error
, mapRoot: '' // '/maps' - Specifies the location where debugger should locate map files instead of generated locations.
, module: 'amd' // 'amd' (default) | 'commonjs' | 'system' | 'umd' | '' - Specify module style for code generation
, newLine: 'CRLF' // 'CRLF' | 'LF' | '' (default) - Explicitly specify newline character (CRLF or LF); if omitted, uses OS default.
, noEmit: false // true | false (default) - Check, but do not emit JS, even in the absence of errors.
, noEmitHelpers: true // true | false (default) - Do not generate custom helper functions like __extends in compiled output.
, noImplicitAny: false // true | false (default) - Warn on expressions and declarations with an implied any type.
, noResolve: true // true | false (default) - Do not add triple-slash references or module import targets to the compilation context.
, out: '' // '' - компиляция в разные файлы или './js/single.js' - компиляция в единый файл - Concatenate and emit output to a single file.
, outDir: '' // 'dist' - Redirect output structure to the directory.
, preserveConstEnums: false // true | false (default) - Const enums will be kept as enums in the emitted JS.
, removeComments: false // true (default)| false - Configures if comments should be included in the output
, sourceMap: false // true (default) | false - Generates corresponding .map file
, sourceRoot: '' // '/dev' - Specifies the location where debugger should locate TypeScript files instead of source locations.
, suppressImplicitAnyIndexErrors: false // true | false (default) - If set to true, TypeScript will allow access to properties of an object by string indexer when noImplicitAny is active, even if TypeScript doesn't know about them. This setting has no effect unless noImplicitAny is active.
, target: 'es3' // 'es3' | 'es5' (default) | 'es6' - Specify ECMAScript target version: 'es3', 'es5', or 'es6'
}
}
}
// Проверить оформление кода в TypeScript-файлах
, tslint: {
options: {
configuration: grunt.file.readJSON('tslint.json')
}
, all: {
src: tsFiles
}
}
// Форматирование кода JavaScript
, 'jsbeautifier' : {
files : ['js/**/*.js']
, options : {
js: {
braceStyle: 'collapse'
, breakChainedMethods: false
, e4x: false
, evalCode: false
, indentChar: ' '
, indentLevel: 0
, indentSize: 4
, indentWithTabs: false
, jslintHappy: true
, keepArrayIndentation: false
, keepFunctionIndentation: false
, maxPreserveNewlines: 10
, preserveNewlines: true
, spaceBeforeConditional: true
, spaceInParen: false
, unescapeStrings: false
, wrapLineLength: 0
, endWithNewline: false
}
}
}
// Начать отслеживание изменений кода файлов
, watch: {
scripts: {
files: tsFiles
, tasks: [
// 'newer:tslint'
//, 'typescript'
'ts'
, 'jsbeautifier'
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-ts');
grunt.loadNpmTasks('grunt-tslint');
grunt.loadNpmTasks('grunt-jsbeautifier');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('default', [
// 'newer:tslint'
//, 'typescript'
'ts'
, 'jsbeautifier'
, 'watch'
]);
};
3. Создать файл rungrunt.js с кодом
require('grunt').cli();
4. Создать файл tsling.json с кодом
{
"rules": {
"ban": false
, "class-name": true
, "comment-format": [true, "check-space"]
, "curly": true
, "eofline": false
, "forin": true
, "indent": [true, "spaces"]
, "jsdoc-format": true
, "label-position": true
, "label-undefined": true
, "max-line-length": [true, 500]
, "member-access": true
, "member-ordering": [
true
, "public-before-private"
, "static-before-instance"
, "variables-before-functions"
]
, "no-any": true
, "no-arg": true
, "no-bitwise": true
, "no-console": [
true
, "debug"
, "info"
, "time"
, "timeEnd"
, "trace"
]
, "no-consecutive-blank-lines": true
, "no-construct": true
, "no-constructor-vars": true
, "no-debugger": false
, "no-duplicate-key": true
, "no-duplicate-variable": true
, "no-empty": true
, "no-eval": true
, "no-internal-module": true
, "no-string-literal": false
, "no-trailing-comma": true
, "no-trailing-whitespace": true
, "no-unreachable": true
, "no-unused-expression": true
, "no-unused-variable": true
, "no-use-before-declare": true
, "one-line": [
true
, "check-open-brace"
, "check-catch"
, "check-else"
, "check-whitespace"
]
, "quotemark": [true, "single"]
, "radix": true
, "semicolon": true
, "switch-default": true
, "triple-equals": [true, "allow-null-check"]
, "typedef": [
true
, "call-signature"
, "parameter"
, "property"
, "variable-declaration"
, "member-variable-declarations"
]
, "typedef-whitespace": [
true
, {
"call-signature": "nospace"
, "index-signature": "nospace"
, "parameter": "nospace"
, "property-declaration": "nospace"
, "variable-declaration": "nospace"
}
]
, "variable-name": false
, "whitespace": [
true
, "check-branch"
, "check-decl"
, "check-module"
, "check-operator"
, "check-separator"
]
}
}
5. Поместить исходные TypeScript-файлы в папку js
js/module-1.ts
js/module-2.ts
6. Скомпилировать TypeScript-файлы в JavaScript-файлы командой
node rungrunt.js
Настройка TypeScript + Gulp
1. В папку с проектом установить модули
npm install gulp
npm install gulp-typescript
npm install gulp-tslint
2. Создать файл Gulpfile.js с кодом
var gulp = require('gulp')
, typescript = require('gulp-typescript')
, typescriptLint = require('gulp-tslint');
// Lint all typescript files
gulp.task('typescript-lint', function () {
return gulp.src(['src/**/*.ts']).pipe(typescriptLint({configuration: 'tslint.json'}))
.pipe(typescriptLint.report('prose'));
});
// Build all typescript files
gulp.task('typescript-build', function () {
var typescriptResult = gulp.src(['src/**/*.ts']).pipe(typescript(typescript.createProject('tsconfig.json')));
return typescriptResult.js.pipe(gulp.dest('build'));
});
// Watch all typescript files for changes and rebuild everything
gulp.task('typescript-watch', function () {
gulp.watch(['src/**/*.ts'], [
'typescript-lint'
, 'typescript-build'
]);
});
// Default gulp task
gulp.task('default', [
'typescript-lint'
, 'typescript-build'
, 'typescript-watch'
]);
3. Создать файл rungulp.js с кодом
// Execute gulp task
var command = 'node ./node_modules/gulp/bin/gulp.js default'
, process = require('child_process').exec(command);
process.stdout.on('data', function(data) {console.log(data);});
process.stderr.on('data', function(data) {console.log(data);});
process.on('close', function(code) {if (code === 0) {console.log('Done');} else {console.log('Exit code: ' + code);}});
4. Создать файл tsconfig.json с кодом
{
"compilerOptions": {
"declaration": false
, "emitDecoratorMetadata": false
, "experimentalDecorators": false
, "inlineSourceMap": false
, "inlineSources": false
, "isolatedModules": false
, "mapRoot": ""
, "module": "amd"
, "newLine": "CRLF"
, "noEmit": false
, "noEmitHelpers": true
, "noImplicitAny": true
, "noResolve": true
, "outFile": "final.js"
, "preserveConstEnums": false
, "removeComments": false
, "sourceMap": false
, "sourceRoot": ""
, "suppressImplicitAnyIndexErrors": false
, "target": "es3"
}
}
5. Создать файл tsling.json с кодом
{
"rules": {
"ban": false
, "class-name": true
, "comment-format": [true, "check-space"]
, "curly": true
, "eofline": false
, "forin": true
, "indent": [true, "spaces"]
, "jsdoc-format": true
, "label-position": true
, "label-undefined": true
, "max-line-length": [true, 500]
, "member-access": true
, "member-ordering": [
true
, "public-before-private"
, "static-before-instance"
, "variables-before-functions"
]
, "no-any": true
, "no-arg": true
, "no-bitwise": true
, "no-console": [
true
, "debug"
, "info"
, "time"
, "timeEnd"
, "trace"
]
, "no-consecutive-blank-lines": true
, "no-construct": true
, "no-constructor-vars": true
, "no-debugger": false
, "no-duplicate-key": true
, "no-duplicate-variable": true
, "no-empty": true
, "no-eval": true
, "no-internal-module": true
, "no-string-literal": false
, "no-trailing-comma": true
, "no-trailing-whitespace": true
, "no-unreachable": true
, "no-unused-expression": true
, "no-unused-variable": true
, "no-use-before-declare": true
, "one-line": [
true
, "check-open-brace"
, "check-catch"
, "check-else"
, "check-whitespace"
]
, "quotemark": [true, "single"]
, "radix": true
, "semicolon": true
, "switch-default": true
, "triple-equals": [true, "allow-null-check"]
, "typedef": [
true
, "call-signature"
, "parameter"
, "property"
, "variable-declaration"
, "member-variable-declarations"
]
, "typedef-whitespace": [
true
, {
"call-signature": "nospace"
, "index-signature": "nospace"
, "parameter": "nospace"
, "property-declaration": "nospace"
, "variable-declaration": "nospace"
}
]
, "variable-name": false
, "whitespace": [
true
, "check-branch"
, "check-decl"
, "check-module"
, "check-operator"
, "check-separator"
]
}
}
npm install gulp
npm install gulp-typescript
npm install gulp-tslint
2. Создать файл Gulpfile.js с кодом
var gulp = require('gulp')
, typescript = require('gulp-typescript')
, typescriptLint = require('gulp-tslint');
// Lint all typescript files
gulp.task('typescript-lint', function () {
return gulp.src(['src/**/*.ts']).pipe(typescriptLint({configuration: 'tslint.json'}))
.pipe(typescriptLint.report('prose'));
});
// Build all typescript files
gulp.task('typescript-build', function () {
var typescriptResult = gulp.src(['src/**/*.ts']).pipe(typescript(typescript.createProject('tsconfig.json')));
return typescriptResult.js.pipe(gulp.dest('build'));
});
// Watch all typescript files for changes and rebuild everything
gulp.task('typescript-watch', function () {
gulp.watch(['src/**/*.ts'], [
'typescript-lint'
, 'typescript-build'
]);
});
// Default gulp task
gulp.task('default', [
'typescript-lint'
, 'typescript-build'
, 'typescript-watch'
]);
3. Создать файл rungulp.js с кодом
// Execute gulp task
var command = 'node ./node_modules/gulp/bin/gulp.js default'
, process = require('child_process').exec(command);
process.stdout.on('data', function(data) {console.log(data);});
process.stderr.on('data', function(data) {console.log(data);});
process.on('close', function(code) {if (code === 0) {console.log('Done');} else {console.log('Exit code: ' + code);}});
4. Создать файл tsconfig.json с кодом
{
"compilerOptions": {
"declaration": false
, "emitDecoratorMetadata": false
, "experimentalDecorators": false
, "inlineSourceMap": false
, "inlineSources": false
, "isolatedModules": false
, "mapRoot": ""
, "module": "amd"
, "newLine": "CRLF"
, "noEmit": false
, "noEmitHelpers": true
, "noImplicitAny": true
, "noResolve": true
, "outFile": "final.js"
, "preserveConstEnums": false
, "removeComments": false
, "sourceMap": false
, "sourceRoot": ""
, "suppressImplicitAnyIndexErrors": false
, "target": "es3"
}
}
5. Создать файл tsling.json с кодом
{
"rules": {
"ban": false
, "class-name": true
, "comment-format": [true, "check-space"]
, "curly": true
, "eofline": false
, "forin": true
, "indent": [true, "spaces"]
, "jsdoc-format": true
, "label-position": true
, "label-undefined": true
, "max-line-length": [true, 500]
, "member-access": true
, "member-ordering": [
true
, "public-before-private"
, "static-before-instance"
, "variables-before-functions"
]
, "no-any": true
, "no-arg": true
, "no-bitwise": true
, "no-console": [
true
, "debug"
, "info"
, "time"
, "timeEnd"
, "trace"
]
, "no-consecutive-blank-lines": true
, "no-construct": true
, "no-constructor-vars": true
, "no-debugger": false
, "no-duplicate-key": true
, "no-duplicate-variable": true
, "no-empty": true
, "no-eval": true
, "no-internal-module": true
, "no-string-literal": false
, "no-trailing-comma": true
, "no-trailing-whitespace": true
, "no-unreachable": true
, "no-unused-expression": true
, "no-unused-variable": true
, "no-use-before-declare": true
, "one-line": [
true
, "check-open-brace"
, "check-catch"
, "check-else"
, "check-whitespace"
]
, "quotemark": [true, "single"]
, "radix": true
, "semicolon": true
, "switch-default": true
, "triple-equals": [true, "allow-null-check"]
, "typedef": [
true
, "call-signature"
, "parameter"
, "property"
, "variable-declaration"
, "member-variable-declarations"
]
, "typedef-whitespace": [
true
, {
"call-signature": "nospace"
, "index-signature": "nospace"
, "parameter": "nospace"
, "property-declaration": "nospace"
, "variable-declaration": "nospace"
}
]
, "variable-name": false
, "whitespace": [
true
, "check-branch"
, "check-decl"
, "check-module"
, "check-operator"
, "check-separator"
]
}
}
6. Поместить исходные TypeScript-файлы в папку src
src/module-1.ts
src/module-2.ts
7. Скомпилировать TypeScript-файлы в JavaScript-файлы командой
node rungulp.js
понедельник, 25 января 2016 г.
Как запустить Gulp локально
Устанавливаем локально Gulp в папку с проектом:
cd C:\Work\My\Folder
npm install gulp
Создаем файл gulpfile.js с кодом
var gulp = require('gulp');
gulp.task('build', function () {
console.log('Building...');
});
gulp.task('default', function () {
console.log('Hello, world!');
});
4 способа запустить задания из файла gulpfile.js.
1) Запустить из файла rungulp.js
Создать файл rungulp.js:
var exec = require('child_process').exec;
exec('node ./node_modules/gulp/bin/gulp.js build', function(error, stdout, stderr) {
console.log('stdout: ', stdout);
console.log('stderr: ', stderr);
if (error !== null) {
console.log('exec error: ', error);
}
});
// или
/*
var child = exec('node ./node_modules/gulp/bin/gulp.js build');
child.stdout.on('data', function(data) {console.log('stdout: ' + data);});
child.stderr.on('data', function(data) {console.log('stderr: ' + data);});
child.on('close', function(code) {console.log('closing code: ' + code);});
*/
Запустить его из командной строки:
node rungulp.js
2) Запустить из командной строки файл gulp
C:\Work\My\Folder\node_modules\.bin\gulp
3) Создать файл package.json с кодом
{
// ...
"scripts": {
"gulp": "gulp"
}
// ...
}
Выполнить в командной строке команду
npm run gulp
4) Установить Gulp глобально
npm install -g gulp
Выполнить в командной строке команду
gulp
cd C:\Work\My\Folder
npm install gulp
Создаем файл gulpfile.js с кодом
var gulp = require('gulp');
gulp.task('build', function () {
console.log('Building...');
});
gulp.task('default', function () {
console.log('Hello, world!');
});
4 способа запустить задания из файла gulpfile.js.
1) Запустить из файла rungulp.js
Создать файл rungulp.js:
var exec = require('child_process').exec;
exec('node ./node_modules/gulp/bin/gulp.js build', function(error, stdout, stderr) {
console.log('stdout: ', stdout);
console.log('stderr: ', stderr);
if (error !== null) {
console.log('exec error: ', error);
}
});
// или
/*
var child = exec('node ./node_modules/gulp/bin/gulp.js build');
child.stdout.on('data', function(data) {console.log('stdout: ' + data);});
child.stderr.on('data', function(data) {console.log('stderr: ' + data);});
child.on('close', function(code) {console.log('closing code: ' + code);});
*/
Запустить его из командной строки:
node rungulp.js
2) Запустить из командной строки файл gulp
C:\Work\My\Folder\node_modules\.bin\gulp
3) Создать файл package.json с кодом
{
// ...
"scripts": {
"gulp": "gulp"
}
// ...
}
Выполнить в командной строке команду
npm run gulp
4) Установить Gulp глобально
npm install -g gulp
Выполнить в командной строке команду
gulp
понедельник, 16 ноября 2015 г.
Node.js EJS Partial include
Файл server.js
var fs = require('fs')
, ejs = require('ejs')
, inputFilePath = __dirname + '/sample.html'
, outputFilePath = __dirname + '/index.html';
fs.readFile(inputFilePath, 'utf-8', function (error, content) {
if (error) {throw error;}
var result = ejs.render(content, {users: [{name: 'tj' }, {name: 'mape'}, {name: 'guillermo'}]}, {filename: 'sample.html'});
fs.writeFile(outputFilePath, result, 'utf-8', function (error) {
if (error) {throw error;}
console.log(result);
})
});
Файл sample.html
<%- include('partial', {user: 1}); %>
<% include partial2 %>
<p><%= users[0].name %></p>
<p><%= users[1].name %></p>
<p><%= users[2].name %></p>
Файл partial.ejs
<ul>
<li><%= user %></li>
</ul>
<% include partial2 %>
<h1><%= users[0].name %></h1>
Файл partial2.ejs
<b><%= users[1].name %></b>
Итоговый файл index.html
<ul>
<li>1</li>
</ul>
<b>mape</b>
<h1>tj</h1>
<b>mape</b>
<p>tj</p>
<p>mape</p>
<p>guillermo</p>
var fs = require('fs')
, ejs = require('ejs')
, inputFilePath = __dirname + '/sample.html'
, outputFilePath = __dirname + '/index.html';
fs.readFile(inputFilePath, 'utf-8', function (error, content) {
if (error) {throw error;}
var result = ejs.render(content, {users: [{name: 'tj' }, {name: 'mape'}, {name: 'guillermo'}]}, {filename: 'sample.html'});
fs.writeFile(outputFilePath, result, 'utf-8', function (error) {
if (error) {throw error;}
console.log(result);
})
});
Файл sample.html
<%- include('partial', {user: 1}); %>
<% include partial2 %>
<p><%= users[0].name %></p>
<p><%= users[1].name %></p>
<p><%= users[2].name %></p>
Файл partial.ejs
<ul>
<li><%= user %></li>
</ul>
<% include partial2 %>
<h1><%= users[0].name %></h1>
Файл partial2.ejs
<b><%= users[1].name %></b>
Итоговый файл index.html
<ul>
<li>1</li>
</ul>
<b>mape</b>
<h1>tj</h1>
<b>mape</b>
<p>tj</p>
<p>mape</p>
<p>guillermo</p>
Шаблоны и SSI инклюды в статичные файлы на Node.js
Файл templater.js
// Для правильной работы необходимо установить библиотеку "glob": npm install glob
//
// Данный сценарий будет искать все HTML-файлы в корневой папке, в которой он находится, или в папке, которую вы зададите,
// и обрабатывать статичные инклюды обернутые в HTML-комментарии следующим образом:
// <!-- #include "example/foo.html" -->
// Вы также можете добавить переменные, подлежащие замене, используя синтакиси mustache
// (пока поддерживается только самый простой способ замены):
// <!-- #include "inc/header.html" title="Example Title" foo="bar" -->
// значения внутри {{title}} и {{foo}} будут заменены на соотвестующий значения, прописанные в комментарии.
// После обработки шаблонов будут сформированы итоговые файлы, которые будут помещены в указанную вами папку.
//
// Пример кода шаблона
//
// Файл /index.html
// <!DOCTYPE html>
// <!-- #include "tpl/header.html" title="Example" header="Sample Title" -->
// <div role="main">
// content goes here
// </div>
// <!-- #include "tpl/footer.html" msg="yeah" -->
// </body>
// </html>
//
// Файл /tpl/header.html
// <html>
// <head>
// <meta charset="utf-8">
// <title>{{ title }}</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>{{header}}</h1>
//
// Файл /tpl/footer.html
// <footer>{{msg}}</footer>
//
// Итоговый файл /result/index.html
// <!DOCTYPE html>
// <html>
// <head>
// <meta charset="utf-8">
// <title>Example</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>Sample Title</h1>
// <div role="main">
// content goes here
// </div>
// <footer>yeah</footer>
// </body>
// </html>
// Конфигурационные настройки
var config = {
inputDirectoryPath: './'
, outputDirectoryPath: './result/'
, fileEncoding: 'utf-8'
};
// Загрузка модулей
var glob = require('glob')
, fs = require('fs');
// Регулярное выражения для поиска комментария инклюда
// ($1) = file name - путь к файлу и его имя "folder/file.html"
// ($2) = variables - переменные title="Example Title" foo="bar"
// | <!-- #include "file.html" variable="value" --> |
var regExpForInclude = /^\s*<!--\s*\#include\s*["']([^"']+)["']\s*(.+)?\s*-->\s*$/gm;
// Регулярное выражения для поиска объявленных переменных
// ($1) = variable name - имя переменной
// ($2) = variable value - значение переменной
// | some-variable_name = "value" |
var regExpForVariables = /([-_\w]+)\s*=\s*["']([^"']+)["']/g;
// Регулярное выражения для поиска мест, куда должно быть вставлено значение переменной
// | {{ some-variable_name }} |
var regExpForMustache = /\{\{\s*([-_\w]+)\s*\}\}/g;
// Обработать все файлы в исходной директории и поместить результаты обработки в виде файлов в заданную папку
glob(config.inputDirectoryPath + '*.html', function (error, files) {
if (error) {throw error;}
files.forEach(function (filePath) {
fs.readFile(filePath, config.fileEncoding, function (error, fileData) {
if (error) {throw error;}
fileData = fileData.replace(regExpForInclude, function (match, fileName, variablesString) {
var content = fs.readFileSync(fileName, config.fileEncoding);
content = replaceVariables(content, parseVariables(variablesString));
content = renderTemplate(content, parseVariables(variablesString) /* или {value: 1}*/).replace(/(\s+<)/g, '\n$1'); // ДОБАВЛЕНО МНОЙ
return content;
});
fs.writeFile(config.outputDirectoryPath + filePath, fileData, config.fileEncoding, function (error) {
if (error) {throw error;}
console.log('complete: '+ filePath);
});
});
});
});
// Функция преобразования строки с набором переменных в объект, состоящий из комбинаций "имя переменной: значение переменной"
function parseVariables (variablesString) {
var obj = {}
, match;
while (match = regExpForVariables.exec(variablesString)) {
obj[match[1]] = match[2]; // obj[some-variable_name] = variable_value;
}
return obj;
}
// Функция для замены имен переменных внутри шаблона на значения этих переменных
function replaceVariables (template, variablesObject, regexp) {
function replaceFunction (match, variableName) {
return (variableName in variablesObject) ? variablesObject[variableName] : '';
}
return template.replace(regexp || regExpForMustache, replaceFunction);
}
// Функция для выполнения кода внутри шаблона
function renderTemplate (templateString, dataObject) {
// <% for (var i = 0; i < 3; i++) { %><p><%= i %> <%= someArray[i] %></p><% } %>
var functionArgument ="dataObject"
, functionBody = "var code = [];"
+ "with (dataObject) {"
+ "code.push('" + templateString
.replace(/[\r\t\n]/g, "")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("code.push('")
.split("\r").join("\\'")
+ "');"
+ "}"
+ "return code.join('');";
return new Function(functionArgument, functionBody).call(null, dataObject);
}
// Взять шаблон, подставить в него значения переменных, вернуть новый обработанный шаблон в виде строки
// Для правильной работы необходимо установить библиотеку "glob": npm install glob
//
// Данный сценарий будет искать все HTML-файлы в корневой папке, в которой он находится, или в папке, которую вы зададите,
// и обрабатывать статичные инклюды обернутые в HTML-комментарии следующим образом:
// <!-- #include "example/foo.html" -->
// Вы также можете добавить переменные, подлежащие замене, используя синтакиси mustache
// (пока поддерживается только самый простой способ замены):
// <!-- #include "inc/header.html" title="Example Title" foo="bar" -->
// значения внутри {{title}} и {{foo}} будут заменены на соотвестующий значения, прописанные в комментарии.
// После обработки шаблонов будут сформированы итоговые файлы, которые будут помещены в указанную вами папку.
//
// Пример кода шаблона
//
// Файл /index.html
// <!DOCTYPE html>
// <!-- #include "tpl/header.html" title="Example" header="Sample Title" -->
// <div role="main">
// content goes here
// </div>
// <!-- #include "tpl/footer.html" msg="yeah" -->
// </body>
// </html>
//
// Файл /tpl/header.html
// <html>
// <head>
// <meta charset="utf-8">
// <title>{{ title }}</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>{{header}}</h1>
//
// Файл /tpl/footer.html
// <footer>{{msg}}</footer>
//
// Итоговый файл /result/index.html
// <!DOCTYPE html>
// <html>
// <head>
// <meta charset="utf-8">
// <title>Example</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>Sample Title</h1>
// <div role="main">
// content goes here
// </div>
// <footer>yeah</footer>
// </body>
// </html>
// Конфигурационные настройки
var config = {
inputDirectoryPath: './'
, outputDirectoryPath: './result/'
, fileEncoding: 'utf-8'
};
// Загрузка модулей
var glob = require('glob')
, fs = require('fs');
// Регулярное выражения для поиска комментария инклюда
// ($1) = file name - путь к файлу и его имя "folder/file.html"
// ($2) = variables - переменные title="Example Title" foo="bar"
// | <!-- #include "file.html" variable="value" --> |
var regExpForInclude = /^\s*<!--\s*\#include\s*["']([^"']+)["']\s*(.+)?\s*-->\s*$/gm;
// Регулярное выражения для поиска объявленных переменных
// ($1) = variable name - имя переменной
// ($2) = variable value - значение переменной
// | some-variable_name = "value" |
var regExpForVariables = /([-_\w]+)\s*=\s*["']([^"']+)["']/g;
// Регулярное выражения для поиска мест, куда должно быть вставлено значение переменной
// | {{ some-variable_name }} |
var regExpForMustache = /\{\{\s*([-_\w]+)\s*\}\}/g;
// Обработать все файлы в исходной директории и поместить результаты обработки в виде файлов в заданную папку
glob(config.inputDirectoryPath + '*.html', function (error, files) {
if (error) {throw error;}
files.forEach(function (filePath) {
fs.readFile(filePath, config.fileEncoding, function (error, fileData) {
if (error) {throw error;}
fileData = fileData.replace(regExpForInclude, function (match, fileName, variablesString) {
var content = fs.readFileSync(fileName, config.fileEncoding);
content = replaceVariables(content, parseVariables(variablesString));
content = renderTemplate(content, parseVariables(variablesString) /* или {value: 1}*/).replace(/(\s+<)/g, '\n$1'); // ДОБАВЛЕНО МНОЙ
return content;
});
fs.writeFile(config.outputDirectoryPath + filePath, fileData, config.fileEncoding, function (error) {
if (error) {throw error;}
console.log('complete: '+ filePath);
});
});
});
});
// Функция преобразования строки с набором переменных в объект, состоящий из комбинаций "имя переменной: значение переменной"
function parseVariables (variablesString) {
var obj = {}
, match;
while (match = regExpForVariables.exec(variablesString)) {
obj[match[1]] = match[2]; // obj[some-variable_name] = variable_value;
}
return obj;
}
// Функция для замены имен переменных внутри шаблона на значения этих переменных
function replaceVariables (template, variablesObject, regexp) {
function replaceFunction (match, variableName) {
return (variableName in variablesObject) ? variablesObject[variableName] : '';
}
return template.replace(regexp || regExpForMustache, replaceFunction);
}
// Функция для выполнения кода внутри шаблона
function renderTemplate (templateString, dataObject) {
// <% for (var i = 0; i < 3; i++) { %><p><%= i %> <%= someArray[i] %></p><% } %>
var functionArgument ="dataObject"
, functionBody = "var code = [];"
+ "with (dataObject) {"
+ "code.push('" + templateString
.replace(/[\r\t\n]/g, "")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("code.push('")
.split("\r").join("\\'")
+ "');"
+ "}"
+ "return code.join('');";
return new Function(functionArgument, functionBody).call(null, dataObject);
}
// Взять шаблон, подставить в него значения переменных, вернуть новый обработанный шаблон в виде строки
Файл index.html
<!DOCTYPE html>
<!-- #include "tpl/header.html" title="Example" header="Sample Title" superman="['one', 'two', 'three']" -->
<div role="main">
content goes here
</div>
<!-- #include "tpl/footer.html" msg="yeah" -->
</body>
</html>
Файл tpl/header.html
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>{{header}}</h1>
<h2><%= header %></h2>
<% for (var i = 0; i < 3; i++) { %><p><%= i %> <%= superman[i] %></p><% } %>
Файл tpl.footer.html
<footer>{{msg}}</footer>
Итоговый файл result/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>Sample Title</h1>
<h2>Sample Title</h2>
<p>0Example</p><p>1Example</p><p>2Example</p><p>3Example</p><p>4Example</p><p>5Example</p><p>6Example</p><p>7Example</p><p>8Example</p><p>9Example</p>
<div role="main">
content goes here
</div>
<footer>yeah</footer>
</body>
</html>
четверг, 12 ноября 2015 г.
Node.js static SSI - Script to inline HTML Static Includes
index.html
<!DOCTYPE html>
<!-- #include "inc_header.html" title="Example" header="Sample Title" -->
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>Sample Title</h1>
<!-- endinclude -->
<div role="main">
content goes here
</div>
<!-- #include "inc_footer.html" msg="yeah" -->
<footer>yeah</footer>
<!-- endinclude -->
</body>
</html>
inc_header.html
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>{{header}}</h1>
Если ваш проект состоит из более чем 5 статичных страниц, использующих одинаковые header и footer, то в этом случае вы можете использовать данный простой script для вставки кода из внешних файлов, основанный на использовании комментариев в качестве разметки. Таким образом вы сможете обновлять все файлы сразу, внося изменение только в одном месте. В дальнейшем данный script может быть расширен для поддержки variables/arguments, но сейчас в этом нет необходимости.
inc_footer.html
<footer>{{msg}}</footer>
templater.js
// Для правильной работы необходимо установить библиотеку "glob": npm install glob
//
// Данный сценарий будет искать все HTML-файлы в корневой папке, в которой он находится, или в папке, которую вы зададите,
// и обрабатывать статичные инклюды обернутые в HTML-комментарии следующим образом:
// <!-- #include "example/foo.html" -->
// Вы также можете добавить переменные, подлежащие замене, используя синтакиси mustache
// (пока поддерживается только самый простой способ замены):
// <!-- #include "inc/header.html" title="Example Title" foo="bar" -->
// значения внутри {{title}} и {{foo}} будут заменены на соотвестующий значения, прописанные в комментарии.
// После обработки шаблонов будут сформированы итоговые файлы, которые будут помещены в указанную вами папку.
//
// Пример кода шаблона
//
// Файл /index.html
// <!DOCTYPE html>
// <!-- #include "tpl/header.html" title="Example" header="Sample Title" -->
// <div role="main">
// content goes here
// </div>
// <!-- #include "tpl/footer.html" msg="yeah" -->
// </body>
// </html>
//
// Файл /tpl/header.html
// <html>
// <head>
// <meta charset="utf-8">
// <title>{{ title }}</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>{{header}}</h1>
//
// Файл /tpl/footer.html
// <footer>{{msg}}</footer>
//
// Итоговый файл /result/index.html
// <!DOCTYPE html>
// <html>
// <head>
// <meta charset="utf-8">
// <title>Example</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>Sample Title</h1>
// <div role="main">
// content goes here
// </div>
// <footer>yeah</footer>
// </body>
// </html>
// Конфигурационные настройки
var config = {
inputDirectoryPath: './'
, outputDirectoryPath: './result/'
, fileEncoding: 'utf-8'
};
// Загрузка модулей
var glob = require('glob')
, fs = require('fs');
// Регулярное выражения для поиска комментария инклюда
// ($1) = file name - путь к файлу и его имя "folder/file.html"
// ($2) = variables - переменные title="Example Title" foo="bar"
// | <!-- #include "file.html" variable="value" --> |
var regExpForInclude = /^\s*<!--\s*\#include\s*["']([^"']+)["']\s*(.+)?\s*-->\s*$/gm;
// Регулярное выражения для поиска объявленных переменных
// ($1) = variable name - имя переменной
// ($2) = variable value - значение переменной
// | some-variable_name = "value" |
var regExpForVariables = /([-_\w]+)\s*=\s*["']([^"']+)["']/g;
// Регулярное выражения для поиска мест, куда должно быть вставлено значение переменной
// | {{ some-variable_name }} |
var regExpForMustache = /\{\{\s*([-_\w]+)\s*\}\}/g;
// Обработать все файлы в исходной директории и поместить результаты обработки в виде файлов в заданную папку
glob(config.inputDirectoryPath + '*.html', function (error, files) {
if (error) {throw error;}
files.forEach(function (filePath) {
fs.readFile(filePath, config.fileEncoding, function (error, fileData) {
if (error) {throw error;}
fileData = fileData.replace(regExpForInclude, function (match, fileName, variablesString) {
var content = fs.readFileSync(fileName, config.fileEncoding);
content = interpolate(content, parseVariables(variablesString));
return content;
});
fs.writeFile(config.outputDirectoryPath + filePath, fileData, config.fileEncoding, function (error) {
if (error) {throw error;}
console.log('complete: '+ filePath);
});
});
});
});
// Функция преобразования строки с набором переменных в объект, состоящий из комбинаций "имя переменной: значение переменной"
function parseVariables (variablesString) {
var obj = {}
, match;
while (match = regExpForVariables.exec(variablesString)) {
obj[match[1]] = match[2]; // obj[some-variable_name] = variable_value;
}
return obj;
}
// Функция для замены имен переменных внутри шаблона на значения этих переменных
function interpolate (template, variablesObject, regexp) {
function replaceFunction (match, variableName) {
return (variableName in variablesObject) ? variablesObject[variableName] : '';
}
return template.replace(regexp || regExpForMustache, replaceFunction);
}
<!DOCTYPE html>
<!-- #include "inc_header.html" title="Example" header="Sample Title" -->
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>Sample Title</h1>
<!-- endinclude -->
<div role="main">
content goes here
</div>
<!-- #include "inc_footer.html" msg="yeah" -->
<footer>yeah</footer>
<!-- endinclude -->
</body>
</html>
inc_header.html
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>{{header}}</h1>
Если ваш проект состоит из более чем 5 статичных страниц, использующих одинаковые header и footer, то в этом случае вы можете использовать данный простой script для вставки кода из внешних файлов, основанный на использовании комментариев в качестве разметки. Таким образом вы сможете обновлять все файлы сразу, внося изменение только в одном месте. В дальнейшем данный script может быть расширен для поддержки variables/arguments, но сейчас в этом нет необходимости.
inc_footer.html
<footer>{{msg}}</footer>
templater.js
// Для правильной работы необходимо установить библиотеку "glob": npm install glob
//
// Данный сценарий будет искать все HTML-файлы в корневой папке, в которой он находится, или в папке, которую вы зададите,
// и обрабатывать статичные инклюды обернутые в HTML-комментарии следующим образом:
// <!-- #include "example/foo.html" -->
// Вы также можете добавить переменные, подлежащие замене, используя синтакиси mustache
// (пока поддерживается только самый простой способ замены):
// <!-- #include "inc/header.html" title="Example Title" foo="bar" -->
// значения внутри {{title}} и {{foo}} будут заменены на соотвестующий значения, прописанные в комментарии.
// После обработки шаблонов будут сформированы итоговые файлы, которые будут помещены в указанную вами папку.
//
// Пример кода шаблона
//
// Файл /index.html
// <!DOCTYPE html>
// <!-- #include "tpl/header.html" title="Example" header="Sample Title" -->
// <div role="main">
// content goes here
// </div>
// <!-- #include "tpl/footer.html" msg="yeah" -->
// </body>
// </html>
//
// Файл /tpl/header.html
// <html>
// <head>
// <meta charset="utf-8">
// <title>{{ title }}</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>{{header}}</h1>
//
// Файл /tpl/footer.html
// <footer>{{msg}}</footer>
//
// Итоговый файл /result/index.html
// <!DOCTYPE html>
// <html>
// <head>
// <meta charset="utf-8">
// <title>Example</title>
// <link rel="stylesheet" href="css/main.css">
// </head>
// <body>
// <h1>Sample Title</h1>
// <div role="main">
// content goes here
// </div>
// <footer>yeah</footer>
// </body>
// </html>
// Конфигурационные настройки
var config = {
inputDirectoryPath: './'
, outputDirectoryPath: './result/'
, fileEncoding: 'utf-8'
};
// Загрузка модулей
var glob = require('glob')
, fs = require('fs');
// Регулярное выражения для поиска комментария инклюда
// ($1) = file name - путь к файлу и его имя "folder/file.html"
// ($2) = variables - переменные title="Example Title" foo="bar"
// | <!-- #include "file.html" variable="value" --> |
var regExpForInclude = /^\s*<!--\s*\#include\s*["']([^"']+)["']\s*(.+)?\s*-->\s*$/gm;
// Регулярное выражения для поиска объявленных переменных
// ($1) = variable name - имя переменной
// ($2) = variable value - значение переменной
// | some-variable_name = "value" |
var regExpForVariables = /([-_\w]+)\s*=\s*["']([^"']+)["']/g;
// Регулярное выражения для поиска мест, куда должно быть вставлено значение переменной
// | {{ some-variable_name }} |
var regExpForMustache = /\{\{\s*([-_\w]+)\s*\}\}/g;
// Обработать все файлы в исходной директории и поместить результаты обработки в виде файлов в заданную папку
glob(config.inputDirectoryPath + '*.html', function (error, files) {
if (error) {throw error;}
files.forEach(function (filePath) {
fs.readFile(filePath, config.fileEncoding, function (error, fileData) {
if (error) {throw error;}
fileData = fileData.replace(regExpForInclude, function (match, fileName, variablesString) {
var content = fs.readFileSync(fileName, config.fileEncoding);
content = interpolate(content, parseVariables(variablesString));
return content;
});
fs.writeFile(config.outputDirectoryPath + filePath, fileData, config.fileEncoding, function (error) {
if (error) {throw error;}
console.log('complete: '+ filePath);
});
});
});
});
// Функция преобразования строки с набором переменных в объект, состоящий из комбинаций "имя переменной: значение переменной"
function parseVariables (variablesString) {
var obj = {}
, match;
while (match = regExpForVariables.exec(variablesString)) {
obj[match[1]] = match[2]; // obj[some-variable_name] = variable_value;
}
return obj;
}
// Функция для замены имен переменных внутри шаблона на значения этих переменных
function interpolate (template, variablesObject, regexp) {
function replaceFunction (match, variableName) {
return (variableName in variablesObject) ? variablesObject[variableName] : '';
}
return template.replace(regexp || regExpForMustache, replaceFunction);
}
Подписаться на:
Сообщения (Atom)