diff --git a/.github/gitgraph/patternlab-flow.js b/.github/gitgraph/patternlab-flow.js index 79872b09a..a68910cee 100644 --- a/.github/gitgraph/patternlab-flow.js +++ b/.github/gitgraph/patternlab-flow.js @@ -1,58 +1,65 @@ var graphConfig = new GitGraph.Template({ - colors: [ "#9993FF", "#47E8D4", "#6BDB52", "#F85BB5", "#FFA657", "#FFCCAA", "#F85BB5" ], + colors: [ + '#9993FF', + '#47E8D4', + '#6BDB52', + '#F85BB5', + '#FFA657', + '#FFCCAA', + '#F85BB5', + ], branch: { lineWidth: 3, spacingX: 60, - mergeStyle: "straight", + mergeStyle: 'straight', showLabel: true, // display branch names on graph - labelFont: "normal 10pt Arial", + labelFont: 'normal 10pt Arial', labelRotation: 0, - color: "black" + color: 'black', }, commit: { spacingY: -30, dot: { size: 8, - strokeColor: "#000000", - strokeWidth: 4 + strokeColor: '#000000', + strokeWidth: 4, }, tag: { - font: "normal 10pt Arial", - color: "yellow" + font: 'normal 10pt Arial', + color: 'yellow', }, message: { - color: "black", - font: "normal 12pt Arial", + color: 'black', + font: 'normal 12pt Arial', displayAuthor: false, displayBranch: false, displayHash: false, - } + }, }, arrow: { size: 8, offset: 3, - - } + }, }); var config = { template: graphConfig, - mode: "extended", - orientation: "horizontal" + mode: 'extended', + orientation: 'horizontal', }; var bugFixCommit = { messageAuthorDisplay: false, messageBranchDisplay: false, messageHashDisplay: false, - message: "Bug fix commit(s)" + message: 'Bug fix commit(s)', }; var stabilizationCommit = { messageAuthorDisplay: false, messageBranchDisplay: false, messageHashDisplay: false, - message: "Release stabilization commit(s)" + message: 'Release stabilization commit(s)', }; // You can manually fix columns to control the display. @@ -68,109 +75,104 @@ var masterCol = i++; var gitgraph = new GitGraph(config); var master = gitgraph.branch({ - name: "master", - column: masterCol + name: 'master', + column: masterCol, }); -master.commit("Initial commit"); +master.commit('Initial commit'); var develop = gitgraph.branch({ parentBranch: master, - name: "dev", - column: developCol + name: 'dev', + column: developCol, }); var developV3 = gitgraph.branch({ parentBranch: master, - name: "dev-3.0", - column: developV3Col + name: 'dev-3.0', + column: developV3Col, }); - var longRunning = gitgraph.branch({ parentBranch: master, - name: "long-running-improvement", - column: longRunningCol + name: 'long-running-improvement', + column: longRunningCol, }); develop.commit({ - messageDisplay: false + messageDisplay: false, }); developV3.commit({ - messageDisplay: false + messageDisplay: false, }); longRunning.commit({ - messageDisplay: false + messageDisplay: false, }); longRunning.merge(developV3); var feature1 = gitgraph.branch({ parentBranch: develop, - name: "feature/1-description", - column: featureCol + name: 'feature/1-description', + column: featureCol, }); -feature1.commit("#1 A feature to go into v2.8.0").commit({ - messageDisplay: false +feature1.commit('#1 A feature to go into v2.8.0').commit({ + messageDisplay: false, }); develop.merge(feature1); -feature1.commit("Small Bugfix").commit({ - messageDisplay: false +feature1.commit('Small Bugfix').commit({ + messageDisplay: false, }); feature1.merge(develop); - var feature3X = gitgraph.branch({ parentBranch: developV3, - name: "feature/42-feature-for-3-x-only", - column: featureV3Col + name: 'feature/42-feature-for-3-x-only', + column: featureV3Col, }); -feature3X.commit("#42 A feature to go into v3.X").commit({ - messageDisplay: false +feature3X.commit('#42 A feature to go into v3.X').commit({ + messageDisplay: false, }); feature3X.merge(developV3); - var feature2 = gitgraph.branch({ parentBranch: develop, - name: "feature/2-description", - column: featureCol + name: 'feature/2-description', + column: featureCol, }); -feature2.commit("#2 Another feature to go into v2.8.0").commit({ - messageDisplay: false +feature2.commit('#2 Another feature to go into v2.8.0').commit({ + messageDisplay: false, }); feature2.merge(develop); feature2.merge(developV3); -develop.merge(master,{ +develop.merge(master, { dotStrokeWidth: 10, - message: "Release v2.8.1 tagged", - tag: "v2.8.1" + message: 'Release v2.8.1 tagged', + tag: 'v2.8.1', }); - develop.commit({ - messageDisplay: false + messageDisplay: false, }); - longRunning.commit({ - messageDisplay: false + messageDisplay: false, }); developV3.merge(longRunning); longRunning.commit({ - messageDisplay: false + messageDisplay: false, }); var feature3 = gitgraph.branch({ parentBranch: develop, - name: "bugfix/3-description", - column: featureCol + name: 'bugfix/3-description', + column: featureCol, }); -feature3.commit("A feature to go into v2.8.0").commit({ - messageDisplay: false +feature3.commit('A feature to go into v2.8.0').commit({ + messageDisplay: false, }); feature3.merge(develop); @@ -178,27 +180,26 @@ longRunning.merge(developV3); developV3.commit({ messageDisplay: false, - dotStrokeWidth: 10 + dotStrokeWidth: 10, }); - develop.commit({ - messageDisplay: false + messageDisplay: false, }); develop.commit({ - messageDisplay: false + messageDisplay: false, }); develop.merge(master, { dotStrokeWidth: 10, - message: "Release v2.9.0 tagged", - tag: "v2.9.0" + message: 'Release v2.9.0 tagged', + tag: 'v2.9.0', }); develop.commit({ messageDisplay: false, - dotStrokeWidth: 10 + dotStrokeWidth: 10, }); developV3.checkout(); diff --git a/.prettierignore b/.prettierignore index d65bda2a4..b0a54c78d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,9 @@ **/*.json **/README.md +**/node_modules/ +**/bower_components/ +**/dist/ +**/public/ +**/*.min.js ./packages/core/scripts/api.handlebars ./packages/core/scripts/events.handlebars diff --git a/packages/core/package.json b/packages/core/package.json index 228261dd9..e554cd09b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -60,9 +60,7 @@ "scripts": { "docs": "node ./scripts/docs.js", "lint": "eslint src/**/*.js", - "precommit": "pretty-quick --staged", "pretest": "npm run lint", - "prettier": "prettier --config .prettierrc --write ./src/**/*.js", "release": "standard-version", "test": "tap test/*_tests.js --reporter spec --coverage" }, diff --git a/packages/core/test/files/annotations.js b/packages/core/test/files/annotations.js index f1077ed02..557b04676 100644 --- a/packages/core/test/files/annotations.js +++ b/packages/core/test/files/annotations.js @@ -1,14 +1,16 @@ var comments = { - "comments" : [ + comments: [ { - "el": "header[role=banner]", - "title" : "Masthead", - "comment": "The main header of the site doesn't take up too much screen real estate in order to keep the focus on the core content. It's using a linear CSS gradient instead of a background image to give greater design flexibility and reduce HTTP requests." + el: 'header[role=banner]', + title: 'Masthead', + comment: + "The main header of the site doesn't take up too much screen real estate in order to keep the focus on the core content. It's using a linear CSS gradient instead of a background image to give greater design flexibility and reduce HTTP requests.", }, { - "el": ".logo", - "title" : "Logo", - "comment": "The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don't support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

" - } - ] + el: '.logo', + title: 'Logo', + comment: + 'The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don\'t support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

', + }, + ], }; diff --git a/packages/core/test/help_tests.js b/packages/core/test/help_tests.js index d62db006c..847c77a52 100644 --- a/packages/core/test/help_tests.js +++ b/packages/core/test/help_tests.js @@ -3,9 +3,7 @@ const tap = require('tap'); const help = require('../src/lib/help'); -tap.test('help - includes passed in version number', function( - test -) { +tap.test('help - includes passed in version number', function(test) { //arrange const version = '⚡'; diff --git a/packages/engine-handlebars/lib/engine_handlebars.js b/packages/engine-handlebars/lib/engine_handlebars.js index 1a5e5a7d3..dbeb88312 100644 --- a/packages/engine-handlebars/lib/engine_handlebars.js +++ b/packages/engine-handlebars/lib/engine_handlebars.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict'; /* * handlebars pattern engine for patternlab-node @@ -32,7 +32,10 @@ const findListItemsRE = /({{#( )?)(list(I|i)tems.)(one|two|three|four|five|six|s const findAtPartialBlockRE = /{{#?>\s*@partial-block\s*}}/g; function escapeAtPartialBlock(partialString) { - var partial = partialString.replace(findAtPartialBlockRE, '{{> @partial-block }}'); + var partial = partialString.replace( + findAtPartialBlockRE, + '{{> @partial-block }}' + ); return partial; } @@ -51,14 +54,12 @@ var engine_handlebars = { Handlebars.registerPartial(partials); } - var compiled = Handlebars.compile( - escapeAtPartialBlock(pattern.template) - ); + var compiled = Handlebars.compile(escapeAtPartialBlock(pattern.template)); return Promise.resolve(compiled(data)); }, - registerPartial: function (pattern) { + registerPartial: function(pattern) { // register exact partial name Handlebars.registerPartial(pattern.patternPartial, pattern.template); @@ -70,7 +71,7 @@ var engine_handlebars = { var matches = pattern.template.match(findPartialsRE); return matches; }, - findPartialsWithStyleModifiers: function () { + findPartialsWithStyleModifiers: function() { // TODO: make the call to this from oPattern objects conditional on their // being implemented here. return []; @@ -78,47 +79,49 @@ var engine_handlebars = { // returns any patterns that match {{> value(foo:"bar") }} or {{> // value:mod(foo:"bar") }} within the pattern - findPartialsWithPatternParameters: function () { + findPartialsWithPatternParameters: function() { // TODO: make the call to this from oPattern objects conditional on their // being implemented here. return []; }, - findListItems: function (pattern) { + findListItems: function(pattern) { var matches = pattern.template.match(findListItemsRE); return matches; }, // given a pattern, and a partial string, tease out the "pattern key" and // return it. - findPartial: function (partialString) { + findPartial: function(partialString) { var partial = partialString.replace(findPartialsRE, '$1'); return partial; }, - spawnFile: function (config, fileName) { + spawnFile: function(config, fileName) { const paths = config.paths; const metaFilePath = path.resolve(paths.source.meta, fileName); try { fs.statSync(metaFilePath); } catch (err) { - //not a file, so spawn it from the included file - const metaFileContent = fs.readFileSync(path.resolve(__dirname, '..', '_meta/', fileName), 'utf8'); + const metaFileContent = fs.readFileSync( + path.resolve(__dirname, '..', '_meta/', fileName), + 'utf8' + ); fs.outputFileSync(metaFilePath, metaFileContent); } }, /** - * Checks to see if the _meta directory has engine-specific head and foot files, - * spawning them if not found. - * - * @param {object} config - the global config object from core, since we won't - * assume it's already present - */ - spawnMeta: function (config) { + * Checks to see if the _meta directory has engine-specific head and foot files, + * spawning them if not found. + * + * @param {object} config - the global config object from core, since we won't + * assume it's already present + */ + spawnMeta: function(config) { this.spawnFile(config, '_00-head.hbs'); this.spawnFile(config, '_01-foot.hbs'); - } + }, }; module.exports = engine_handlebars; diff --git a/packages/engine-liquid/lib/engine_liquid.js b/packages/engine-liquid/lib/engine_liquid.js index 9c97e35b1..0f61aff59 100644 --- a/packages/engine-liquid/lib/engine_liquid.js +++ b/packages/engine-liquid/lib/engine_liquid.js @@ -7,22 +7,25 @@ * */ -"use strict"; +'use strict'; const fs = require('fs-extra'); const path = require('path'); const isDirectory = source => fs.lstatSync(source).isDirectory(); const getDirectories = source => - fs.readdirSync(source).map(name => path.join(source, name)).filter(isDirectory); + fs + .readdirSync(source) + .map(name => path.join(source, name)) + .filter(isDirectory); -const { lstatSync, readdirSync } = require('fs') -const { join } = require('path') +const { lstatSync, readdirSync } = require('fs'); +const { join } = require('path'); var utils = require('./util_liquid'); var Liquid = require('liquidjs'); let engine = Liquid({ - dynamicPartials: false + dynamicPartials: false, }); // This holds the config from from core. The core has to call @@ -48,11 +51,13 @@ module.exports = { // render it renderPattern: function renderPattern(pattern, data, partials) { - return engine.parseAndRender(pattern.template, data) - .then(function(html){ + return engine + .parseAndRender(pattern.template, data) + .then(function(html) { return html; - }).catch(function(ex){ - console.log(40, ex) + }) + .catch(function(ex) { + console.log(40, ex); }); }, @@ -67,7 +72,10 @@ module.exports = { var matches; if (typeof pattern === 'string') { matches = pattern.match(regex); - } else if (typeof pattern === 'object' && typeof pattern.template === 'string') { + } else if ( + typeof pattern === 'object' && + typeof pattern.template === 'string' + ) { matches = pattern.template.match(regex); } return matches; @@ -78,38 +86,51 @@ module.exports = { var matches = this.patternMatcher(pattern, this.findPartialsRE); return matches; }, - findPartialsWithStyleModifiers: function (pattern) { - var matches = this.patternMatcher(pattern, this.findPartialsWithStyleModifiersRE); + findPartialsWithStyleModifiers: function(pattern) { + var matches = this.patternMatcher( + pattern, + this.findPartialsWithStyleModifiersRE + ); return matches; }, // returns any patterns that match {{> value(foo:"bar") }} or {{> // value:mod(foo:"bar") }} within the pattern - findPartialsWithPatternParameters: function (pattern) { - var matches = this.patternMatcher(pattern, this.findPartialsWithPatternParametersRE); + findPartialsWithPatternParameters: function(pattern) { + var matches = this.patternMatcher( + pattern, + this.findPartialsWithPatternParametersRE + ); return matches; }, - findListItems: function (pattern) { + findListItems: function(pattern) { var matches = this.patternMatcher(pattern, this.findListItemsRE); return matches; }, // given a pattern, and a partial string, tease out the "pattern key" and // return it. - findPartial_new: function (partialString) { + findPartial_new: function(partialString) { var partial = partialString.replace(this.findPartialRE, '$1'); return partial; }, // GTP: the old implementation works better. We might not need // this.findPartialRE anymore if it works in all cases! - findPartial: function (partialString) { + findPartial: function(partialString) { //strip out the template cruft - var foundPatternPartial = partialString.replace("{{> ", "").replace(" }}", "").replace("{{>", "").replace("}}", ""); + var foundPatternPartial = partialString + .replace('{{> ', '') + .replace(' }}', '') + .replace('{{>', '') + .replace('}}', ''); // remove any potential pattern parameters. this and the above are rather brutish but I didn't want to do a regex at the time if (foundPatternPartial.indexOf('(') > 0) { - foundPatternPartial = foundPatternPartial.substring(0, foundPatternPartial.indexOf('(')); + foundPatternPartial = foundPatternPartial.substring( + 0, + foundPatternPartial.indexOf('(') + ); } //remove any potential stylemodifiers. @@ -124,7 +145,7 @@ module.exports = { * * @param {object} config - the global config object from core */ - usePatternLabConfig: function (config) { + usePatternLabConfig: function(config) { patternLabConfig = config; let patternsPath = patternLabConfig.paths.source.patterns; @@ -138,34 +159,36 @@ module.exports = { engine = Liquid({ dynamicPartials: false, - root: allPaths + root: allPaths, }); }, - spawnFile: function (config, fileName) { + spawnFile: function(config, fileName) { const paths = config.paths; const metaFilePath = path.resolve(paths.source.meta, fileName); try { fs.statSync(metaFilePath); } catch (err) { - //not a file, so spawn it from the included file const localMetaFilePath = path.resolve(__dirname, '_meta/', fileName); - const metaFileContent = fs.readFileSync(path.resolve(__dirname, '..', '_meta/', fileName), 'utf8'); + const metaFileContent = fs.readFileSync( + path.resolve(__dirname, '..', '_meta/', fileName), + 'utf8' + ); fs.outputFileSync(metaFilePath, metaFileContent); } }, /** - * Checks to see if the _meta directory has engine-specific head and foot files, - * spawning them if not found. - * - * @param {object} config - the global config object from core, since we won't - * assume it's already present - */ - spawnMeta: function (config) { + * Checks to see if the _meta directory has engine-specific head and foot files, + * spawning them if not found. + * + * @param {object} config - the global config object from core, since we won't + * assume it's already present + */ + spawnMeta: function(config) { this.spawnFile(config, '_00-head.liquid'); this.spawnFile(config, '_01-foot.liquid'); - } + }, }; diff --git a/packages/engine-liquid/lib/util_liquid.js b/packages/engine-liquid/lib/util_liquid.js index 7508bc74a..3bc200d78 100644 --- a/packages/engine-liquid/lib/util_liquid.js +++ b/packages/engine-liquid/lib/util_liquid.js @@ -11,7 +11,9 @@ // the term "alphanumeric" includes underscores. // todo: document this exact regex long form. -var partialsRE = new RegExp(/{%\\include\\\s*?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-_|]+)?(?:(?:| )\(.*)?(?:\s*)?%}/g); +var partialsRE = new RegExp( + /{%\\include\\\s*?([\w\-\.\/~]+)(?:\:[A-Za-z0-9-_|]+)?(?:(?:| )\(.*)?(?:\s*)?%}/g +); // look for an opening mustache include tag, followed by >=0 whitespaces var partialsWithStyleModifiersStr = '{{>\\s*'; @@ -34,7 +36,10 @@ partialsWithStyleModifiersStr += '(\\s*\\([^\\)]*\\))?'; // look for >=0 whitespaces, followed by closing mustache tag partialsWithStyleModifiersStr += '\\s*}}'; -var partialsWithStyleModifiersRE = new RegExp(partialsWithStyleModifiersStr, 'g'); +var partialsWithStyleModifiersRE = new RegExp( + partialsWithStyleModifiersStr, + 'g' +); // look for an opening mustache include tag, followed by >=0 whitespaces var partialsWithPatternParametersStr = '{{>\\s*'; @@ -55,7 +60,10 @@ partialsWithPatternParametersStr += '(\\s*\\([^\\)]*\\))'; // look for >=0 whitespaces, followed by closing mustache tag partialsWithPatternParametersStr += '\\s*}}'; -var partialsWithPatternParametersRE = new RegExp(partialsWithPatternParametersStr, 'g'); +var partialsWithPatternParametersRE = new RegExp( + partialsWithPatternParametersStr, + 'g' +); // look for an opening mustache loop tag, followed by >=0 whitespaces var listItemsStr = '{{#\\s*'; @@ -64,7 +72,8 @@ var listItemsStr = '{{#\\s*'; listItemsStr += '(list(I|i)tems\\.)'; // look for a number 1 - 20, spelled out -listItemsStr += '(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)'; +listItemsStr += + '(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)'; // look for >=0 whitespaces, followed by closing mustache tag listItemsStr += '\\s*}}'; @@ -95,7 +104,7 @@ var utilLiquid = { partialsWithStyleModifiersRE: partialsWithStyleModifiersRE, partialsWithPatternParametersRE: partialsWithPatternParametersRE, listItemsRE: listItemsRE, - partialKeyRE: partialKeyRE + partialKeyRE: partialKeyRE, }; module.exports = utilLiquid; diff --git a/packages/engine-nunjucks/lib/engine_nunjucks.js b/packages/engine-nunjucks/lib/engine_nunjucks.js index d5d0a93d7..5c149d3f9 100644 --- a/packages/engine-nunjucks/lib/engine_nunjucks.js +++ b/packages/engine-nunjucks/lib/engine_nunjucks.js @@ -18,7 +18,7 @@ * */ -"use strict"; +'use strict'; var fs = require('fs-extra'), path = require('path'), @@ -28,17 +28,18 @@ var fs = require('fs-extra'), env = nunjucks.configure(plConfig.paths.source.patterns), partialRegistry = []; - //////////////////////////// // LOAD ANY USER NUNJUCKS CONFIGURATIONS //////////////////////////// try { - var nunjucksConfig = require(path.join(plPath, 'patternlab-nunjucks-config.js')); + var nunjucksConfig = require(path.join( + plPath, + 'patternlab-nunjucks-config.js' + )); if (typeof nunjucksConfig == 'function') { nunjucksConfig(nunjucks, env); } -} catch (err) { } - +} catch (err) {} //////////////////////////// // HELPER FUNCTIONS @@ -46,12 +47,17 @@ try { // Might do some research on the solution. //////////////////////////// if (!String.prototype.replaceAll) { - String.prototype.replaceAll = function (str1, str2, ignore) { - return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g, "\\$&"), (ignore ? "gi" : "g")), (typeof (str2) == "string") ? str2.replace(/\$/g, "$$$$") : str2); - } + String.prototype.replaceAll = function(str1, str2, ignore) { + return this.replace( + new RegExp( + str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g, '\\$&'), + ignore ? 'gi' : 'g' + ), + typeof str2 == 'string' ? str2.replace(/\$/g, '$$$$') : str2 + ); + }; } - //////////////////////////// // NUNJUCKS ENGINE //////////////////////////// @@ -75,8 +81,7 @@ var engine_nunjucks = { pattern.extendedTemplate = this.replacePartials(pattern); var result = nunjucks.renderString(pattern.extendedTemplate, data); return Promise.resolve(result); - } - catch (err) { + } catch (err) { console.error('Failed to render pattern: ' + pattern.name); } }, @@ -88,69 +93,86 @@ var engine_nunjucks = { }, // given a pattern, and a partial string, tease out the "pattern key" and return it. - findPartial: function (partialString) { + findPartial: function(partialString) { try { var partial = partialString.match(this.findPartialKeyRE)[1]; partial = partial.replace(/["']/g, ''); return partial; - } - catch (err) { - console.error('Error occured when trying to find partial name in: ' + partialString); + } catch (err) { + console.error( + 'Error occured when trying to find partial name in: ' + partialString + ); } }, // keep track of partials and their paths so we can replace the name with the path - registerPartial: function (pattern) { + registerPartial: function(pattern) { // only register each partial once. Otherwise we'll eat up a ton of memory. if (partialRegistry.indexOf(pattern.patternPartial) === -1) { - partialRegistry[pattern.patternPartial] = pattern.relPath.replace(/\\/g, '/'); + partialRegistry[pattern.patternPartial] = pattern.relPath.replace( + /\\/g, + '/' + ); } }, - replacePartials: function (pattern) { + replacePartials: function(pattern) { try { var partials = this.findPartials(pattern); if (partials !== null) { - for (var i = 0; i < partials.length; i++) { // e.g. {% include "atoms-parent" %} + for (var i = 0; i < partials.length; i++) { + // e.g. {% include "atoms-parent" %} var partialName = this.findPartial(partials[i]); // e.g. atoms-parent var partialFullPath = partialRegistry[partialName]; // e.g. 00-atoms/01-parent.njk - var newPartial = partials[i].replaceAll(partialName, partialFullPath, true); // e.g. {% include "00-atoms/01-parent.njk" %} - pattern.extendedTemplate = pattern.extendedTemplate.replaceAll(partials[i], newPartial, true); + var newPartial = partials[i].replaceAll( + partialName, + partialFullPath, + true + ); // e.g. {% include "00-atoms/01-parent.njk" %} + pattern.extendedTemplate = pattern.extendedTemplate.replaceAll( + partials[i], + newPartial, + true + ); } } return pattern.extendedTemplate; - } - catch (err) { - console.error('Error occurred in replacing partial names with paths for patern: ' + pattern.name); + } catch (err) { + console.error( + 'Error occurred in replacing partial names with paths for patern: ' + + pattern.name + ); } }, // still requires the mustache syntax because of the way PL handles lists - findListItems: function (pattern) { + findListItems: function(pattern) { var matches = pattern.template.match(this.findListItemsRE); return matches; }, // handled by nunjucks. This is here to keep PL from erroring - findPartialsWithStyleModifiers: function () { + findPartialsWithStyleModifiers: function() { return null; }, // handled by nunjucks. This is here to keep PL from erroring - findPartialsWithPatternParameters: function () { + findPartialsWithPatternParameters: function() { return null; }, - spawnFile: function (config, fileName) { + spawnFile: function(config, fileName) { const paths = config.paths; const metaFilePath = path.resolve(paths.source.meta, fileName); try { fs.statSync(metaFilePath); } catch (err) { - //not a file, so spawn it from the included file const localMetaFilePath = path.resolve(__dirname, '_meta/', fileName); - const metaFileContent = fs.readFileSync(path.resolve(__dirname, '..', '_meta/', fileName), 'utf8'); + const metaFileContent = fs.readFileSync( + path.resolve(__dirname, '..', '_meta/', fileName), + 'utf8' + ); fs.outputFileSync(metaFilePath, metaFileContent); } }, @@ -162,10 +184,10 @@ var engine_nunjucks = { * @param {object} config - the global config object from core, since we won't * assume it's already present */ - spawnMeta: function (config) { + spawnMeta: function(config) { this.spawnFile(config, '_00-head.njk'); this.spawnFile(config, '_01-foot.njk'); - } + }, }; module.exports = engine_nunjucks; diff --git a/packages/engine-nunjucks/package.json b/packages/engine-nunjucks/package.json index 3c2ad19e4..34b03b63e 100644 --- a/packages/engine-nunjucks/package.json +++ b/packages/engine-nunjucks/package.json @@ -29,5 +29,8 @@ "scripts": { "test": "grunt travis --verbose" }, - "version": "0.1.3" + "version": "0.1.4-alpha.0", + "publishConfig": { + "access": "public" + } } diff --git a/packages/live-server/index.js b/packages/live-server/index.js index 7e80e3ff0..4da8f2db4 100644 --- a/packages/live-server/index.js +++ b/packages/live-server/index.js @@ -1,101 +1,120 @@ #!/usr/bin/env node var fs = require('fs'), - connect = require('connect'), - serveIndex = require('serve-index'), - logger = require('morgan'), - WebSocket = require('faye-websocket'), - path = require('path'), - url = require('url'), - http = require('http'), - send = require('send'), - open = require('opn'), - es = require("event-stream"), - os = require('os'), - chokidar = require('chokidar'); + connect = require('connect'), + serveIndex = require('serve-index'), + logger = require('morgan'), + WebSocket = require('faye-websocket'), + path = require('path'), + url = require('url'), + http = require('http'), + send = require('send'), + open = require('opn'), + es = require('event-stream'), + os = require('os'), + chokidar = require('chokidar'); require('colors'); -var INJECTED_CODE = fs.readFileSync(path.join(__dirname, "injected.html"), "utf8"); +var INJECTED_CODE = fs.readFileSync( + path.join(__dirname, 'injected.html'), + 'utf8' +); var LiveServer = { - server: null, - watcher: null, - logLevel: 2 + server: null, + watcher: null, + logLevel: 2, }; -function escape(html){ - return String(html) - .replace(/&(?!\w+;)/g, '&') - .replace(//g, '>') - .replace(/"/g, '"'); +function escape(html) { + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); } // Based on connect.static(), but streamlined and with added code injecter function staticServer(root) { - var isFile = false; - try { // For supporting mounting files instead of just directories - isFile = fs.statSync(root).isFile(); - } catch (e) { - if (e.code !== "ENOENT") throw e; - } - return function(req, res, next) { - if (req.method !== "GET" && req.method !== "HEAD") return next(); - var reqpath = isFile ? "" : url.parse(req.url).pathname; - var hasNoOrigin = !req.headers.origin; - var injectCandidates = [ new RegExp("", "i"), new RegExp(""), new RegExp("", "i")]; - var injectTag = null; - - function directory() { - var pathname = url.parse(req.originalUrl).pathname; - res.statusCode = 301; - res.setHeader('Location', pathname + '/'); - res.end('Redirecting to ' + escape(pathname) + '/'); - } - - function file(filepath /*, stat*/) { - var x = path.extname(filepath).toLocaleLowerCase(), match, - possibleExtensions = [ "", ".html", ".htm", ".xhtml", ".php", ".svg" ]; - if (hasNoOrigin && (possibleExtensions.indexOf(x) > -1)) { - // TODO: Sync file read here is not nice, but we need to determine if the html should be injected or not - var contents = fs.readFileSync(filepath, "utf8"); - for (var i = 0; i < injectCandidates.length; ++i) { - match = injectCandidates[i].exec(contents); - if (match) { - injectTag = match[0]; - break; - } - } - if (injectTag === null && LiveServer.logLevel >= 3) { - console.warn("Failed to inject refresh script!".yellow, - "Couldn't find any of the tags ", injectCandidates, "from", filepath); - } - } - } - - function error(err) { - if (err.status === 404) return next(); - next(err); - } - - function inject(stream) { - if (injectTag) { - // We need to modify the length given to browser - var len = INJECTED_CODE.length + res.getHeader('Content-Length'); - res.setHeader('Content-Length', len); - var originalPipe = stream.pipe; - stream.pipe = function(resp) { - originalPipe.call(stream, es.replace(new RegExp(injectTag, "i"), INJECTED_CODE + injectTag)).pipe(resp); - }; - } - } - - send(req, reqpath, { root: root }) - .on('error', error) - .on('directory', directory) - .on('file', file) - .on('stream', inject) - .pipe(res); - }; + var isFile = false; + try { + // For supporting mounting files instead of just directories + isFile = fs.statSync(root).isFile(); + } catch (e) { + if (e.code !== 'ENOENT') throw e; + } + return function(req, res, next) { + if (req.method !== 'GET' && req.method !== 'HEAD') return next(); + var reqpath = isFile ? '' : url.parse(req.url).pathname; + var hasNoOrigin = !req.headers.origin; + var injectCandidates = [ + new RegExp('', 'i'), + new RegExp(''), + new RegExp('', 'i'), + ]; + var injectTag = null; + + function directory() { + var pathname = url.parse(req.originalUrl).pathname; + res.statusCode = 301; + res.setHeader('Location', pathname + '/'); + res.end('Redirecting to ' + escape(pathname) + '/'); + } + + function file(filepath /*, stat*/) { + var x = path.extname(filepath).toLocaleLowerCase(), + match, + possibleExtensions = ['', '.html', '.htm', '.xhtml', '.php', '.svg']; + if (hasNoOrigin && possibleExtensions.indexOf(x) > -1) { + // TODO: Sync file read here is not nice, but we need to determine if the html should be injected or not + var contents = fs.readFileSync(filepath, 'utf8'); + for (var i = 0; i < injectCandidates.length; ++i) { + match = injectCandidates[i].exec(contents); + if (match) { + injectTag = match[0]; + break; + } + } + if (injectTag === null && LiveServer.logLevel >= 3) { + console.warn( + 'Failed to inject refresh script!'.yellow, + "Couldn't find any of the tags ", + injectCandidates, + 'from', + filepath + ); + } + } + } + + function error(err) { + if (err.status === 404) return next(); + next(err); + } + + function inject(stream) { + if (injectTag) { + // We need to modify the length given to browser + var len = INJECTED_CODE.length + res.getHeader('Content-Length'); + res.setHeader('Content-Length', len); + var originalPipe = stream.pipe; + stream.pipe = function(resp) { + originalPipe + .call( + stream, + es.replace(new RegExp(injectTag, 'i'), INJECTED_CODE + injectTag) + ) + .pipe(resp); + }; + } + } + + send(req, reqpath, { root: root }) + .on('error', error) + .on('directory', directory) + .on('file', file) + .on('stream', inject) + .pipe(res); + }; } /** @@ -104,12 +123,15 @@ function staticServer(root) { * @param file {string} Path to the entry point file */ function entryPoint(staticHandler, file) { - if (!file) return function(req, res, next) { next(); }; - - return function(req, res, next) { - req.url = "/" + file; - staticHandler(req, res, next); - }; + if (!file) + return function(req, res, next) { + next(); + }; + + return function(req, res, next) { + req.url = '/' + file; + staticHandler(req, res, next); + }; } /** @@ -130,290 +152,314 @@ function entryPoint(staticHandler, file) { * @param middleware {array} Append middleware to stack, e.g. [function(req, res, next) { next(); }]. */ LiveServer.start = function(options) { - options = options || {}; - var host = options.host || '0.0.0.0'; - var port = options.port !== undefined ? options.port : 8080; // 0 means random - var root = options.root || process.cwd(); - var mount = options.mount || []; - var watchPaths = options.watch || [root]; - LiveServer.logLevel = options.logLevel === undefined ? 2 : options.logLevel; - var openPath = (options.open === undefined || options.open === true) ? - "" : ((options.open === null || options.open === false) ? null : options.open); - if (options.noBrowser) openPath = null; // Backwards compatibility with 0.7.0 - var file = options.file; - var staticServerHandler = staticServer(root); - var wait = options.wait === undefined ? 100 : options.wait; - var browser = options.browser || null; - var htpasswd = options.htpasswd || null; - var cors = options.cors || false; - var https = options.https || null; - var proxy = options.proxy || []; - var middleware = options.middleware || []; - var noCssInject = options.noCssInject; - var httpsModule = options.httpsModule; - - if (httpsModule) { - try { - require.resolve(httpsModule); - } catch (e) { - console.error(("HTTPS module \"" + httpsModule + "\" you've provided was not found.").red); - console.error("Did you do", "\"npm install " + httpsModule + "\"?"); - return; - } - } else { - httpsModule = "https"; - } - - // Setup a web server - var app = connect(); - - // Add logger. Level 2 logs only errors - if (LiveServer.logLevel === 2) { - app.use(logger('dev', { - skip: function (req, res) { return res.statusCode < 400; } - })); - // Level 2 or above logs all requests - } else if (LiveServer.logLevel > 2) { - app.use(logger('dev')); - } - if (options.spa) { - middleware.push("spa"); - } - // Add middleware - middleware.map(function(mw) { - if (typeof mw === "string") { - var ext = path.extname(mw).toLocaleLowerCase(); - if (ext !== ".js") { - mw = require(path.join(__dirname, "middleware", mw + ".js")); - } else { - mw = require(mw); - } - } - app.use(mw); - }); - - // Use http-auth if configured - if (htpasswd !== null) { - var auth = require('http-auth'); - var basic = auth.basic({ - realm: "Please authorize", - file: htpasswd - }); - app.use(auth.connect(basic)); - } - if (cors) { - app.use(require("cors")({ - origin: true, // reflecting request origin - credentials: true // allowing requests with credentials - })); - } - mount.forEach(function(mountRule) { - var mountPath = path.resolve(process.cwd(), mountRule[1]); - if (!options.watch) // Auto add mount paths to wathing but only if exclusive path option is not given - watchPaths.push(mountPath); - app.use(mountRule[0], staticServer(mountPath)); - if (LiveServer.logLevel >= 1) - console.log('Mapping %s to "%s"', mountRule[0], mountPath); - }); - proxy.forEach(function(proxyRule) { - var proxyOpts = url.parse(proxyRule[1]); - proxyOpts.via = true; - proxyOpts.preserveHost = true; - app.use(proxyRule[0], require('proxy-middleware')(proxyOpts)); - if (LiveServer.logLevel >= 1) - console.log('Mapping %s to "%s"', proxyRule[0], proxyRule[1]); - }); - app.use(staticServerHandler) // Custom static server - .use(entryPoint(staticServerHandler, file)) - .use(serveIndex(root, { icons: true })); - - var server, protocol; - if (https !== null) { - var httpsConfig = https; - if (typeof https === "string") { - httpsConfig = require(path.resolve(process.cwd(), https)); - } - server = require(httpsModule).createServer(httpsConfig, app); - protocol = "https"; - } else { - server = http.createServer(app); - protocol = "http"; - } - - // Handle server startup errors - server.addListener('error', function(e) { - if (e.code === 'EADDRINUSE') { - var serveURL = protocol + '://' + host + ':' + port; - console.log('%s is already in use. Trying another port.'.yellow, serveURL); - setTimeout(function() { - server.listen(0, host); - }, 1000); - } else { - console.error(e.toString().red); - LiveServer.shutdown(); - } - }); - - // Handle successful server - server.addListener('listening', function(/*e*/) { - LiveServer.server = server; - - var address = server.address(); - var serveHost = address.address === "0.0.0.0" ? "127.0.0.1" : address.address; - var openHost = host === "0.0.0.0" ? "127.0.0.1" : host; - - var serveURL = protocol + '://' + serveHost + ':' + address.port; - var openURL = protocol + '://' + openHost + ':' + address.port; - - var serveURLs = [ serveURL ]; - if (LiveServer.logLevel > 2 && address.address === "0.0.0.0") { - var ifaces = os.networkInterfaces(); - serveURLs = Object.keys(ifaces) - .map(function(iface) { - return ifaces[iface]; - }) - // flatten address data, use only IPv4 - .reduce(function(data, addresses) { - addresses.filter(function(addr) { - return addr.family === "IPv4"; - }).forEach(function(addr) { - data.push(addr); - }); - return data; - }, []) - .map(function(addr) { - return protocol + "://" + addr.address + ":" + address.port; - }); - } - - // Output - if (LiveServer.logLevel >= 1) { - if (serveURL === openURL) - if (serveURLs.length === 1) { - console.log(("Serving \"%s\" at %s").green, root, serveURLs[0]); - } else { - console.log(("Serving \"%s\" at\n\t%s").green, root, serveURLs.join("\n\t")); - } - else - console.log(("Serving \"%s\" at %s (%s)").green, root, openURL, serveURL); - } - - // Launch browser - if (openPath !== null) - if (typeof openPath === "object") { - openPath.forEach(function(p) { - open(openURL + p, {app: browser}); - }); - } else { - open(openURL + openPath, {app: browser}); - } - }); - - // Setup server to listen at port - server.listen(port, host); - - // WebSocket - var clients = []; - server.addListener('upgrade', function(request, socket, head) { - var ws = new WebSocket(request, socket, head); - ws.onopen = function() { ws.send('connected'); }; - - if (wait > 0) { - (function() { - var wssend = ws.send; - var waitTimeout; - ws.send = function() { - var args = arguments; - if (waitTimeout) clearTimeout(waitTimeout); - waitTimeout = setTimeout(function(){ - wssend.apply(ws, args); - }, wait); - }; - })(); - } - - ws.onclose = function() { - clients = clients.filter(function (x) { - return x !== ws; - }); - }; - - clients.push(ws); - }); - - var ignored = [ - function(testPath) { // Always ignore dotfiles (important e.g. because editor hidden temp files) - return testPath !== "." && /(^[.#]|(?:__|~)$)/.test(path.basename(testPath)); - } - ]; - if (options.ignore) { - ignored = ignored.concat(options.ignore); - } - if (options.ignorePattern) { - ignored.push(options.ignorePattern); - } - // Setup file watcher - LiveServer.watcher = chokidar.watch(watchPaths, { - ignored: ignored, - ignoreInitial: true - }); - function handleChange(changePath) { - var cssChange = path.extname(changePath) === ".css" && !noCssInject; - if (LiveServer.logLevel >= 1) { - if (cssChange) - console.log("CSS change detected".magenta, changePath); - else console.log("Change detected".cyan, changePath); - } - clients.forEach(function(ws) { - if (ws) - ws.send(cssChange ? 'refreshcss' : 'reload'); - }); - } - LiveServer.watcher - .on("change", handleChange) - .on("add", handleChange) - .on("unlink", handleChange) - .on("addDir", handleChange) - .on("unlinkDir", handleChange) - .on("ready", function () { - if (LiveServer.logLevel >= 1) - console.log("Ready for changes".cyan); - }) - .on("error", function (err) { - console.log("ERROR:".red, err); - }); - - LiveServer.refreshCSS = function () { - if (clients.length) { - clients.forEach(function(ws) { - if (ws) { - ws.send('refreshcss'); - } - }); - } - }; - - LiveServer.reload = function () { - if (clients.length) { - clients.forEach(function (ws) { - if (ws) { - ws.send('reload'); - } - }); - } - }; - - return server; + options = options || {}; + var host = options.host || '0.0.0.0'; + var port = options.port !== undefined ? options.port : 8080; // 0 means random + var root = options.root || process.cwd(); + var mount = options.mount || []; + var watchPaths = options.watch || [root]; + LiveServer.logLevel = options.logLevel === undefined ? 2 : options.logLevel; + var openPath = + options.open === undefined || options.open === true + ? '' + : options.open === null || options.open === false ? null : options.open; + if (options.noBrowser) openPath = null; // Backwards compatibility with 0.7.0 + var file = options.file; + var staticServerHandler = staticServer(root); + var wait = options.wait === undefined ? 100 : options.wait; + var browser = options.browser || null; + var htpasswd = options.htpasswd || null; + var cors = options.cors || false; + var https = options.https || null; + var proxy = options.proxy || []; + var middleware = options.middleware || []; + var noCssInject = options.noCssInject; + var httpsModule = options.httpsModule; + + if (httpsModule) { + try { + require.resolve(httpsModule); + } catch (e) { + console.error( + ('HTTPS module "' + httpsModule + '" you\'ve provided was not found.') + .red + ); + console.error('Did you do', '"npm install ' + httpsModule + '"?'); + return; + } + } else { + httpsModule = 'https'; + } + + // Setup a web server + var app = connect(); + + // Add logger. Level 2 logs only errors + if (LiveServer.logLevel === 2) { + app.use( + logger('dev', { + skip: function(req, res) { + return res.statusCode < 400; + }, + }) + ); + // Level 2 or above logs all requests + } else if (LiveServer.logLevel > 2) { + app.use(logger('dev')); + } + if (options.spa) { + middleware.push('spa'); + } + // Add middleware + middleware.map(function(mw) { + if (typeof mw === 'string') { + var ext = path.extname(mw).toLocaleLowerCase(); + if (ext !== '.js') { + mw = require(path.join(__dirname, 'middleware', mw + '.js')); + } else { + mw = require(mw); + } + } + app.use(mw); + }); + + // Use http-auth if configured + if (htpasswd !== null) { + var auth = require('http-auth'); + var basic = auth.basic({ + realm: 'Please authorize', + file: htpasswd, + }); + app.use(auth.connect(basic)); + } + if (cors) { + app.use( + require('cors')({ + origin: true, // reflecting request origin + credentials: true, // allowing requests with credentials + }) + ); + } + mount.forEach(function(mountRule) { + var mountPath = path.resolve(process.cwd(), mountRule[1]); + if (!options.watch) + // Auto add mount paths to wathing but only if exclusive path option is not given + watchPaths.push(mountPath); + app.use(mountRule[0], staticServer(mountPath)); + if (LiveServer.logLevel >= 1) + console.log('Mapping %s to "%s"', mountRule[0], mountPath); + }); + proxy.forEach(function(proxyRule) { + var proxyOpts = url.parse(proxyRule[1]); + proxyOpts.via = true; + proxyOpts.preserveHost = true; + app.use(proxyRule[0], require('proxy-middleware')(proxyOpts)); + if (LiveServer.logLevel >= 1) + console.log('Mapping %s to "%s"', proxyRule[0], proxyRule[1]); + }); + app + .use(staticServerHandler) // Custom static server + .use(entryPoint(staticServerHandler, file)) + .use(serveIndex(root, { icons: true })); + + var server, protocol; + if (https !== null) { + var httpsConfig = https; + if (typeof https === 'string') { + httpsConfig = require(path.resolve(process.cwd(), https)); + } + server = require(httpsModule).createServer(httpsConfig, app); + protocol = 'https'; + } else { + server = http.createServer(app); + protocol = 'http'; + } + + // Handle server startup errors + server.addListener('error', function(e) { + if (e.code === 'EADDRINUSE') { + var serveURL = protocol + '://' + host + ':' + port; + console.log( + '%s is already in use. Trying another port.'.yellow, + serveURL + ); + setTimeout(function() { + server.listen(0, host); + }, 1000); + } else { + console.error(e.toString().red); + LiveServer.shutdown(); + } + }); + + // Handle successful server + server.addListener('listening', function(/*e*/) { + LiveServer.server = server; + + var address = server.address(); + var serveHost = + address.address === '0.0.0.0' ? '127.0.0.1' : address.address; + var openHost = host === '0.0.0.0' ? '127.0.0.1' : host; + + var serveURL = protocol + '://' + serveHost + ':' + address.port; + var openURL = protocol + '://' + openHost + ':' + address.port; + + var serveURLs = [serveURL]; + if (LiveServer.logLevel > 2 && address.address === '0.0.0.0') { + var ifaces = os.networkInterfaces(); + serveURLs = Object.keys(ifaces) + .map(function(iface) { + return ifaces[iface]; + }) + // flatten address data, use only IPv4 + .reduce(function(data, addresses) { + addresses + .filter(function(addr) { + return addr.family === 'IPv4'; + }) + .forEach(function(addr) { + data.push(addr); + }); + return data; + }, []) + .map(function(addr) { + return protocol + '://' + addr.address + ':' + address.port; + }); + } + + // Output + if (LiveServer.logLevel >= 1) { + if (serveURL === openURL) + if (serveURLs.length === 1) { + console.log('Serving "%s" at %s'.green, root, serveURLs[0]); + } else { + console.log( + 'Serving "%s" at\n\t%s'.green, + root, + serveURLs.join('\n\t') + ); + } + else + console.log('Serving "%s" at %s (%s)'.green, root, openURL, serveURL); + } + + // Launch browser + if (openPath !== null) + if (typeof openPath === 'object') { + openPath.forEach(function(p) { + open(openURL + p, { app: browser }); + }); + } else { + open(openURL + openPath, { app: browser }); + } + }); + + // Setup server to listen at port + server.listen(port, host); + + // WebSocket + var clients = []; + server.addListener('upgrade', function(request, socket, head) { + var ws = new WebSocket(request, socket, head); + ws.onopen = function() { + ws.send('connected'); + }; + + if (wait > 0) { + (function() { + var wssend = ws.send; + var waitTimeout; + ws.send = function() { + var args = arguments; + if (waitTimeout) clearTimeout(waitTimeout); + waitTimeout = setTimeout(function() { + wssend.apply(ws, args); + }, wait); + }; + })(); + } + + ws.onclose = function() { + clients = clients.filter(function(x) { + return x !== ws; + }); + }; + + clients.push(ws); + }); + + var ignored = [ + function(testPath) { + // Always ignore dotfiles (important e.g. because editor hidden temp files) + return ( + testPath !== '.' && /(^[.#]|(?:__|~)$)/.test(path.basename(testPath)) + ); + }, + ]; + if (options.ignore) { + ignored = ignored.concat(options.ignore); + } + if (options.ignorePattern) { + ignored.push(options.ignorePattern); + } + // Setup file watcher + LiveServer.watcher = chokidar.watch(watchPaths, { + ignored: ignored, + ignoreInitial: true, + }); + function handleChange(changePath) { + var cssChange = path.extname(changePath) === '.css' && !noCssInject; + if (LiveServer.logLevel >= 1) { + if (cssChange) console.log('CSS change detected'.magenta, changePath); + else console.log('Change detected'.cyan, changePath); + } + clients.forEach(function(ws) { + if (ws) ws.send(cssChange ? 'refreshcss' : 'reload'); + }); + } + LiveServer.watcher + .on('change', handleChange) + .on('add', handleChange) + .on('unlink', handleChange) + .on('addDir', handleChange) + .on('unlinkDir', handleChange) + .on('ready', function() { + if (LiveServer.logLevel >= 1) console.log('Ready for changes'.cyan); + }) + .on('error', function(err) { + console.log('ERROR:'.red, err); + }); + + LiveServer.refreshCSS = function() { + if (clients.length) { + clients.forEach(function(ws) { + if (ws) { + ws.send('refreshcss'); + } + }); + } + }; + + LiveServer.reload = function() { + if (clients.length) { + clients.forEach(function(ws) { + if (ws) { + ws.send('reload'); + } + }); + } + }; + + return server; }; LiveServer.shutdown = function() { - var watcher = LiveServer.watcher; - if (watcher) { - watcher.close(); - } - var server = LiveServer.server; - if (server) - server.close(); + var watcher = LiveServer.watcher; + if (watcher) { + watcher.close(); + } + var server = LiveServer.server; + if (server) server.close(); }; module.exports = LiveServer; diff --git a/packages/live-server/live-server.js b/packages/live-server/live-server.js index 9eac8f125..a4efff0dd 100755 --- a/packages/live-server/live-server.js +++ b/packages/live-server/live-server.js @@ -2,173 +2,153 @@ var path = require('path'); var fs = require('fs'); var assign = require('object-assign'); -var liveServer = require("./index"); +var liveServer = require('./index'); var opts = { - host: process.env.IP, - port: process.env.PORT, - open: true, - mount: [], - proxy: [], - middleware: [], - logLevel: 2, + host: process.env.IP, + port: process.env.PORT, + open: true, + mount: [], + proxy: [], + middleware: [], + logLevel: 2, }; -var homeDir = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; +var homeDir = + process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME']; var configPath = path.join(homeDir, '.live-server.json'); if (fs.existsSync(configPath)) { - var userConfig = fs.readFileSync(configPath, 'utf8'); - assign(opts, JSON.parse(userConfig)); - if (opts.ignorePattern) opts.ignorePattern = new RegExp(opts.ignorePattern); + var userConfig = fs.readFileSync(configPath, 'utf8'); + assign(opts, JSON.parse(userConfig)); + if (opts.ignorePattern) opts.ignorePattern = new RegExp(opts.ignorePattern); } for (var i = process.argv.length - 1; i >= 2; --i) { - var arg = process.argv[i]; - if (arg.indexOf("--port=") > -1) { - var portString = arg.substring(7); - var portNumber = parseInt(portString, 10); - if (portNumber === +portString) { - opts.port = portNumber; - process.argv.splice(i, 1); - } - } - else if (arg.indexOf("--host=") > -1) { - opts.host = arg.substring(7); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--open=") > -1) { - var open = arg.substring(7); - if (open.indexOf('/') !== 0) { - open = '/' + open; - } - switch (typeof opts.open) { - case "boolean": - opts.open = open; - break; - case "string": - opts.open = [opts.open, open]; - break; - case "object": - opts.open.push(open); - break; - } - process.argv.splice(i, 1); - } - else if (arg.indexOf("--watch=") > -1) { - // Will be modified later when cwd is known - opts.watch = arg.substring(8).split(","); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--ignore=") > -1) { - // Will be modified later when cwd is known - opts.ignore = arg.substring(9).split(","); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--ignorePattern=") > -1) { - opts.ignorePattern = new RegExp(arg.substring(16)); - process.argv.splice(i, 1); - } - else if (arg === "--no-css-inject") { - opts.noCssInject = true; - process.argv.splice(i, 1); - } - else if (arg === "--no-browser") { - opts.open = false; - process.argv.splice(i, 1); - } - else if (arg.indexOf("--browser=") > -1) { - opts.browser = arg.substring(10).split(","); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--entry-file=") > -1) { - var file = arg.substring(13); - if (file.length) { - opts.file = file; - process.argv.splice(i, 1); - } - } - else if (arg === "--spa") { - opts.middleware.push("spa"); - process.argv.splice(i, 1); - } - else if (arg === "--quiet" || arg === "-q") { - opts.logLevel = 0; - process.argv.splice(i, 1); - } - else if (arg === "--verbose" || arg === "-V") { - opts.logLevel = 3; - process.argv.splice(i, 1); - } - else if (arg.indexOf("--mount=") > -1) { - // e.g. "--mount=/components:./node_modules" will be ['/components', '/node_modules'] - // split only on the first ":", as the path may contain ":" as well (e.g. C:\file.txt) - var match = arg.substring(8).match(/([^:]+):(.+)$/); - match[2] = path.resolve(process.cwd(), match[2]); - opts.mount.push([ match[1], match[2] ]); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--wait=") > -1) { - var waitString = arg.substring(7); - var waitNumber = parseInt(waitString, 10); - if (waitNumber === +waitString) { - opts.wait = waitNumber; - process.argv.splice(i, 1); - } - } - else if (arg === "--version" || arg === "-v") { - var packageJson = require('./package.json'); - console.log(packageJson.name, packageJson.version); - process.exit(); - } - else if (arg.indexOf("--htpasswd=") > -1) { - opts.htpasswd = arg.substring(11); - process.argv.splice(i, 1); - } - else if (arg === "--cors") { - opts.cors = true; - process.argv.splice(i, 1); - } - else if (arg.indexOf("--https=") > -1) { - opts.https = arg.substring(8); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--https-module=") > -1) { - opts.httpsModule = arg.substring(15); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--proxy=") > -1) { - // split only on the first ":", as the URL will contain ":" as well - var match = arg.substring(8).match(/([^:]+):(.+)$/); - opts.proxy.push([ match[1], match[2] ]); - process.argv.splice(i, 1); - } - else if (arg.indexOf("--middleware=") > -1) { - opts.middleware.push(arg.substring(13)); - process.argv.splice(i, 1); - } - else if (arg === "--help" || arg === "-h") { - console.log('Usage: live-server [-v|--version] [-h|--help] [-q|--quiet] [--port=PORT] [--host=HOST] [--open=PATH] [--no-browser] [--browser=BROWSER] [--ignore=PATH] [--ignorePattern=RGXP] [--no-css-inject] [--entry-file=PATH] [--spa] [--mount=ROUTE:PATH] [--wait=MILLISECONDS] [--htpasswd=PATH] [--cors] [--https=PATH] [--https-module=MODULE_NAME] [--proxy=PATH] [PATH]'); - process.exit(); - } - else if (arg === "--test") { - // Hidden param for tests to exit automatically - setTimeout(liveServer.shutdown, 500); - process.argv.splice(i, 1); - } + var arg = process.argv[i]; + if (arg.indexOf('--port=') > -1) { + var portString = arg.substring(7); + var portNumber = parseInt(portString, 10); + if (portNumber === +portString) { + opts.port = portNumber; + process.argv.splice(i, 1); + } + } else if (arg.indexOf('--host=') > -1) { + opts.host = arg.substring(7); + process.argv.splice(i, 1); + } else if (arg.indexOf('--open=') > -1) { + var open = arg.substring(7); + if (open.indexOf('/') !== 0) { + open = '/' + open; + } + switch (typeof opts.open) { + case 'boolean': + opts.open = open; + break; + case 'string': + opts.open = [opts.open, open]; + break; + case 'object': + opts.open.push(open); + break; + } + process.argv.splice(i, 1); + } else if (arg.indexOf('--watch=') > -1) { + // Will be modified later when cwd is known + opts.watch = arg.substring(8).split(','); + process.argv.splice(i, 1); + } else if (arg.indexOf('--ignore=') > -1) { + // Will be modified later when cwd is known + opts.ignore = arg.substring(9).split(','); + process.argv.splice(i, 1); + } else if (arg.indexOf('--ignorePattern=') > -1) { + opts.ignorePattern = new RegExp(arg.substring(16)); + process.argv.splice(i, 1); + } else if (arg === '--no-css-inject') { + opts.noCssInject = true; + process.argv.splice(i, 1); + } else if (arg === '--no-browser') { + opts.open = false; + process.argv.splice(i, 1); + } else if (arg.indexOf('--browser=') > -1) { + opts.browser = arg.substring(10).split(','); + process.argv.splice(i, 1); + } else if (arg.indexOf('--entry-file=') > -1) { + var file = arg.substring(13); + if (file.length) { + opts.file = file; + process.argv.splice(i, 1); + } + } else if (arg === '--spa') { + opts.middleware.push('spa'); + process.argv.splice(i, 1); + } else if (arg === '--quiet' || arg === '-q') { + opts.logLevel = 0; + process.argv.splice(i, 1); + } else if (arg === '--verbose' || arg === '-V') { + opts.logLevel = 3; + process.argv.splice(i, 1); + } else if (arg.indexOf('--mount=') > -1) { + // e.g. "--mount=/components:./node_modules" will be ['/components', '/node_modules'] + // split only on the first ":", as the path may contain ":" as well (e.g. C:\file.txt) + var match = arg.substring(8).match(/([^:]+):(.+)$/); + match[2] = path.resolve(process.cwd(), match[2]); + opts.mount.push([match[1], match[2]]); + process.argv.splice(i, 1); + } else if (arg.indexOf('--wait=') > -1) { + var waitString = arg.substring(7); + var waitNumber = parseInt(waitString, 10); + if (waitNumber === +waitString) { + opts.wait = waitNumber; + process.argv.splice(i, 1); + } + } else if (arg === '--version' || arg === '-v') { + var packageJson = require('./package.json'); + console.log(packageJson.name, packageJson.version); + process.exit(); + } else if (arg.indexOf('--htpasswd=') > -1) { + opts.htpasswd = arg.substring(11); + process.argv.splice(i, 1); + } else if (arg === '--cors') { + opts.cors = true; + process.argv.splice(i, 1); + } else if (arg.indexOf('--https=') > -1) { + opts.https = arg.substring(8); + process.argv.splice(i, 1); + } else if (arg.indexOf('--https-module=') > -1) { + opts.httpsModule = arg.substring(15); + process.argv.splice(i, 1); + } else if (arg.indexOf('--proxy=') > -1) { + // split only on the first ":", as the URL will contain ":" as well + var match = arg.substring(8).match(/([^:]+):(.+)$/); + opts.proxy.push([match[1], match[2]]); + process.argv.splice(i, 1); + } else if (arg.indexOf('--middleware=') > -1) { + opts.middleware.push(arg.substring(13)); + process.argv.splice(i, 1); + } else if (arg === '--help' || arg === '-h') { + console.log( + 'Usage: live-server [-v|--version] [-h|--help] [-q|--quiet] [--port=PORT] [--host=HOST] [--open=PATH] [--no-browser] [--browser=BROWSER] [--ignore=PATH] [--ignorePattern=RGXP] [--no-css-inject] [--entry-file=PATH] [--spa] [--mount=ROUTE:PATH] [--wait=MILLISECONDS] [--htpasswd=PATH] [--cors] [--https=PATH] [--https-module=MODULE_NAME] [--proxy=PATH] [PATH]' + ); + process.exit(); + } else if (arg === '--test') { + // Hidden param for tests to exit automatically + setTimeout(liveServer.shutdown, 500); + process.argv.splice(i, 1); + } } // Patch paths -var dir = opts.root = process.argv[2] || ""; +var dir = (opts.root = process.argv[2] || ''); if (opts.watch) { - opts.watch = opts.watch.map(function(relativePath) { - return path.join(dir, relativePath); - }); + opts.watch = opts.watch.map(function(relativePath) { + return path.join(dir, relativePath); + }); } if (opts.ignore) { - opts.ignore = opts.ignore.map(function(relativePath) { - return path.join(dir, relativePath); - }); + opts.ignore = opts.ignore.map(function(relativePath) { + return path.join(dir, relativePath); + }); } liveServer.start(opts); diff --git a/packages/live-server/middleware/example.js b/packages/live-server/middleware/example.js index cd5fd7ac5..e35dc139d 100644 --- a/packages/live-server/middleware/example.js +++ b/packages/live-server/middleware/example.js @@ -1,5 +1,4 @@ module.exports = function(req, res, next) { - res.statusCode = 202; - next(); -} - + res.statusCode = 202; + next(); +}; diff --git a/packages/live-server/middleware/spa-ignore-assets.js b/packages/live-server/middleware/spa-ignore-assets.js index ead9e9c64..42a596a8f 100644 --- a/packages/live-server/middleware/spa-ignore-assets.js +++ b/packages/live-server/middleware/spa-ignore-assets.js @@ -1,14 +1,12 @@ // Single Page Apps - redirect to /#/ except when a file extension is given var path = require('path'); module.exports = function(req, res, next) { - if (req.method !== "GET" && req.method !== "HEAD") - next(); - if (req.url !== '/' && path.extname(req.url) === '') { - var route = req.url; - req.url = '/'; - res.statusCode = 302; - res.setHeader('Location', req.url + '#' + route); - res.end(); - } - else next(); -} + if (req.method !== 'GET' && req.method !== 'HEAD') next(); + if (req.url !== '/' && path.extname(req.url) === '') { + var route = req.url; + req.url = '/'; + res.statusCode = 302; + res.setHeader('Location', req.url + '#' + route); + res.end(); + } else next(); +}; diff --git a/packages/live-server/middleware/spa.js b/packages/live-server/middleware/spa.js index 6326e4b2e..7bd5ce44d 100644 --- a/packages/live-server/middleware/spa.js +++ b/packages/live-server/middleware/spa.js @@ -1,13 +1,11 @@ // Single Page Apps - redirect to /#/ module.exports = function(req, res, next) { - if (req.method !== "GET" && req.method !== "HEAD") - next(); - if (req.url !== '/') { - var route = req.url; - req.url = '/'; - res.statusCode = 302; - res.setHeader('Location', req.url + '#' + route); - res.end(); - } - else next(); -} + if (req.method !== 'GET' && req.method !== 'HEAD') next(); + if (req.url !== '/') { + var route = req.url; + req.url = '/'; + res.statusCode = 302; + res.setHeader('Location', req.url + '#' + route); + res.end(); + } else next(); +}; diff --git a/packages/live-server/test/acceptance.js b/packages/live-server/test/acceptance.js index e4eabbb51..01603ed68 100644 --- a/packages/live-server/test/acceptance.js +++ b/packages/live-server/test/acceptance.js @@ -1,67 +1,67 @@ var request = require('supertest'); var path = require('path'); var liveServer = require('..').start({ - root: path.join(__dirname, "data"), - port: 0, - open: false + root: path.join(__dirname, 'data'), + port: 0, + open: false, }); -describe('basic functional tests', function(){ - it('should respond with index.html', function(done){ - request(liveServer) - .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') - .expect(/hello world/i) - .expect(200, done); - }); - it('should have injected script', function(done){ - request(liveServer) - .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') - .expect(/