Skip to content

Commit

Permalink
Merge pull request #592 from pattern-lab/dev
Browse files Browse the repository at this point in the history
Pattern Lab Node Core 2.7.1
  • Loading branch information
bmuenzenmeyer authored Jan 14, 2017
2 parents ffcec17 + b7a62ec commit b918c8d
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 70 deletions.
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/
.github/
.travis.yml
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.png?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) ![current release](https://img.shields.io/github/release/pattern-lab/patternlab-node.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Join the chat at Gitter](https://badges.gitter.im/pattern-lab/node.svg)](https://gitter.im/pattern-lab/node)
[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) ![current release](https://img.shields.io/github/release/pattern-lab/patternlab-node.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Join the chat at Gitter](https://badges.gitter.im/pattern-lab/node.svg)](https://gitter.im/pattern-lab/node)

# Pattern Lab Node Core

Expand All @@ -12,14 +12,17 @@ If this looks **REALLY DIFFERENT** from what you expected, check out the [Change

* [@bmuenzenmeyer](https://github.com/bmuenzenmeyer) - Lead Maintainer
* [@geoffp](https://github.com/geoffp) - Core Contributor
* [@raphaelokon](https://github.com/raphaelokon) - CLI Contributor
* [@tburny](https://github.com/tburny) - Core Contributor

## Upgrading

If you find yourself here and are looking to upgrade, check out how to upgrade from version to version of Pattern Lab Node here: [https://github.com/pattern-lab/patternlab-node/wiki/Upgrading](https://github.com/pattern-lab/patternlab-node/wiki/Upgrading)

## Command Line Interface

The [command line interface](https://github.com/pattern-lab/patternlab-node/wiki/Command-Line-Interface) is documented in the wiki, and already implemented for you within [Node Editions](https://github.com/pattern-lab?utf8=%E2%9C%93&query=edition-node).
The rudimentary [command line interface](https://github.com/pattern-lab/patternlab-node/wiki/Command-Line-Interface) is documented in the wiki, and already implemented for you within [Node Editions](https://github.com/pattern-lab?utf8=%E2%9C%93&query=edition-node).
A [full-featured command line interface](https://github.com/pattern-lab/patternlab-node-cli) is in the works, courtesy of [@raphaelokon](https://github.com/raphaelokon).

## Contributing

Expand Down
27 changes: 23 additions & 4 deletions core/lib/changes_hunter.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,32 @@ ChangesHunter.prototype = {
let renderedTemplatePath =
patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'rendered');

//write the compiled template to the public patterns directory
let markupOnlyPath =
patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'markupOnly');

if (!pattern.compileState) {
pattern.compileState = CompileState.NEEDS_REBUILD;
}

try {
// Prevent error message if file does not exist
fs.accessSync(renderedTemplatePath, fs.F_OK);

// renderedTemplatePath required to display a single element
// Markup only is required for "View All" pages. It will get loaded later on.
// If any of these is missing, mark pattern for recompile
[renderedTemplatePath, markupOnlyPath].forEach(renderedFile =>

// Prevent error message if file does not exist
fs.accessSync(renderedFile, fs.F_OK)
);
let outputLastModified = fs.statSync(renderedTemplatePath).mtime.getTime();

if (pattern.lastModified && outputLastModified > pattern.lastModified) {
pattern.compileState = CompileState.CLEAN;
}
} catch (e) {
// Output does not exist yet, needs recompile
// Output does not exist yet, force recompile
pattern.compileState = CompileState.NEEDS_REBUILD;
}

let node = patternlab.graph.node(pattern);
Expand Down Expand Up @@ -75,7 +87,14 @@ ChangesHunter.prototype = {
// Ignore, not a regular file
}
}
},

needsRebuild: function (lastModified, p) {
if (p.compileState !== CompileState.CLEAN || ! p.lastModified) {
return true;
}
return p.lastModified >= lastModified;
}
};

module.exports = ChangesHunter;
module.exports = ChangesHunter;
48 changes: 39 additions & 9 deletions core/lib/pattern_assembler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use strict";

var path = require('path'),
_ = require('lodash'),
fs = require('fs-extra'),
Pattern = require('./object_factory').Pattern,
CompileState = require('./object_factory').CompileState,
Expand All @@ -15,8 +16,8 @@ var path = require('path'),
ch = require('./changes_hunter'),
JSON5 = require('json5');

var markdown_parser = new mp();
var changes_hunter = new ch();
const markdown_parser = new mp();
const changes_hunter = new ch();

var pattern_assembler = function () {
// HELPER FUNCTIONS
Expand Down Expand Up @@ -155,6 +156,8 @@ var pattern_assembler = function () {

try {
var markdownFileName = path.resolve(patternlab.config.paths.source.patterns, currentPattern.subdir, currentPattern.fileName + ".md");
changes_hunter.checkLastModified(currentPattern, markdownFileName);

var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8');

var markdownObject = markdown_parser.parse(markdownFileContents);
Expand Down Expand Up @@ -404,13 +407,40 @@ var pattern_assembler = function () {
decomposePattern(currentPattern, patternlab);
}

function findModifiedPatterns(lastModified, patternlab) {
return patternlab.patterns.filter(p => {
if (p.compileState !== CompileState.CLEAN || ! p.lastModified) {
return true;

/**
* Finds patterns that were modified and need to be rebuilt. For clean patterns load the already
* rendered markup.
*
* @param lastModified
* @param patternlab
*/
function markModifiedPatterns(lastModified, patternlab) {
/**
* If the given array exists, apply a function to each of its elements
* @param {Array} array
* @param {Function} func
*/
const forEachExisting = (array, func) => {
if (array) {
array.forEach(func);
}
return p.lastModified >= lastModified;
};
const modifiedOrNot = _.groupBy(
patternlab.patterns,
p => changes_hunter.needsRebuild(lastModified, p) ? 'modified' : 'notModified');

// For all unmodified patterns load their rendered template output
forEachExisting(modifiedOrNot.notModified, cleanPattern => {
const xp = path.join(patternlab.config.paths.public.patterns, cleanPattern.getPatternLink(patternlab, 'markupOnly'));

// Pattern with non-existing markupOnly files were already marked for rebuild and thus are not "CLEAN"
cleanPattern.patternPartialCode = fs.readFileSync(xp, 'utf8');
});

// For all patterns that were modified, schedule them for rebuild
forEachExisting(modifiedOrNot.modified, p => p.compileState = CompileState.NEEDS_REBUILD);
return modifiedOrNot;
}

function expandPartials(foundPatternPartials, list_item_hunter, patternlab, currentPattern) {
Expand Down Expand Up @@ -526,8 +556,8 @@ var pattern_assembler = function () {
}

return {
find_modified_patterns: function (lastModified, patternlab) {
return findModifiedPatterns(lastModified, patternlab);
mark_modified_patterns: function (lastModified, patternlab) {
return markModifiedPatterns(lastModified, patternlab);
},
find_pattern_partials: function (pattern) {
return pattern.findPartials();
Expand Down
17 changes: 16 additions & 1 deletion core/lib/pattern_graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ var nodeName =

PatternGraph.prototype = {

/**
* Synchronizes the graph nodes with the set of all known patterns.
* For instance when a pattern is deleted or moved, it might still have a node from the serialized
* JSON, but there is no source pattern.
*
* @see {@link https://github.com/pattern-lab/patternlab-node/issues/580|Issue #580}
*/
sync: function () {
// Remove any patterns that are in the graph data, but that haven't been discovered when
// walking all patterns iteratively
const nodesToRemove = this.nodes().filter(n => !this.patterns.has(n));
nodesToRemove.forEach(n => this.remove(n));
return nodesToRemove;
},

/**
* Creates an independent copy of the graph where nodes and edges can be modified without
* affecting the source.
Expand Down Expand Up @@ -362,7 +377,7 @@ PatternGraph.resolveJsonGraphFile = function (patternlab, file) {
PatternGraph.loadFromFile = function (patternlab, file) {
const jsonGraphFile = this.resolveJsonGraphFile(patternlab, file);

// File is fresh, so simply constuct an empty graph in memory
// File is fresh, so simply construct an empty graph in memory
if (!fs.existsSync(jsonGraphFile)) {
return PatternGraph.empty();
}
Expand Down
83 changes: 58 additions & 25 deletions core/lib/patternlab.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* patternlab-node - v2.7.1-alpha - 2016
* patternlab-node - v2.7.1 - 2017
*
* Brian Muenzenmeyer, Geoff Pursell, and the web community.
* Brian Muenzenmeyer, Geoff Pursell, Raphael Okon, tburny and the web community.
* Licensed under the MIT license.
*
* Many thanks to Brad Frost and Dave Olsen for inspiration, encouragement, and advice.
Expand Down Expand Up @@ -438,10 +438,50 @@ var patternlab_engine = function (config) {
return true;
}

/**
* If a graph was serialized and then {@code deletePatternDir == true}, there is a mismatch in the
* pattern metadata and not all patterns might be recompiled.
* For that reason an empty graph is returned in this case, so every pattern will be flagged as
* "needs recompile". Otherwise the pattern graph is loaded from the meta data.
*
* @param patternlab
* @param {boolean} deletePatternDir When {@code true}, an empty graph is returned
* @return {PatternGraph}
*/
function loadPatternGraph(deletePatternDir) {
// Sanity check to prevent problems when code is refactored
if (deletePatternDir) {
return PatternGraph.empty();
}
return PatternGraph.loadFromFile(patternlab);
}

function buildPatterns(deletePatternDir) {

patternlab.events.emit('patternlab-build-pattern-start', patternlab);
patternlab.graph = PatternGraph.loadFromFile(patternlab);

let graph = patternlab.graph = loadPatternGraph(deletePatternDir);

let graphNeedsUpgrade = !PatternGraph.checkVersion(graph);

if (graphNeedsUpgrade) {
plutils.log.info("Due to an upgrade, a complete rebuild is required and the public/patterns directory was deleted. " +
"Incremental build is available again on the next successful run.");

// Ensure that the freshly built graph has the latest version again.
patternlab.graph.upgradeVersion();
}

// Flags
let incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade);

if (incrementalBuildsEnabled) {
plutils.log.info("Incremental builds enabled.");
} else {
// needs to be done BEFORE processing patterns
fs.removeSync(paths.public.patterns);
fs.emptyDirSync(paths.public.patterns);
}

try {
patternlab.data = buildPatternData(paths.source.data, fs);
Expand Down Expand Up @@ -511,34 +551,27 @@ var patternlab_engine = function (config) {
cacheBuster: patternlab.cacheBuster
});

let patternsToBuild = patternlab.patterns;

let graphNeedsUpgrade = !PatternGraph.checkVersion(patternlab.graph);
// If deletePatternDir == true or graph needs to be updated
// rebuild all patterns
let patternsToBuild = null;

// Incremental builds are enabled, but we cannot use them
if (!deletePatternDir && graphNeedsUpgrade) {
plutils.log.info("Due to an upgrade, a complete rebuild is required. " +
"Incremental build is available again on the next run.");

// Ensure that the freshly built graph has the latest version again.
patternlab.graph.upgradeVersion();
}
if (incrementalBuildsEnabled) {
// When the graph was loaded from file, some patterns might have been moved/deleted between runs
// so the graph data become out of sync
patternlab.graph.sync().forEach(n => {
plutils.log.info("[Deleted/Moved] " + n);
});

//delete the contents of config.patterns.public before writing
//Also if the serialized graph must be updated
if (deletePatternDir || graphNeedsUpgrade) {
fs.removeSync(paths.public.patterns);
fs.emptyDirSync(paths.public.patterns);
} else {
// TODO Find created or deleted files
let now = new Date().getTime();
var modified = pattern_assembler.find_modified_patterns(now, patternlab);

// First mark all modified files
for (let p of modified) {
pattern_assembler.mark_modified_patterns(now, patternlab);
patternsToBuild = patternlab.graph.compileOrder();
} else {
// build all patterns, mark all to be rebuilt
patternsToBuild = patternlab.patterns;
for (let p of patternsToBuild) {
p.compileState = CompileState.NEEDS_REBUILD;
}
patternsToBuild = patternlab.graph.compileOrder();
}


Expand Down
2 changes: 1 addition & 1 deletion core/lib/ui_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ var ui_builder = function () {
output += 'var ishControls = {"ishControlsHide":' + JSON.stringify(patternlab.config.ishControlsHide) + '};' + eol;

//navItems
output += 'var navItems = {"patternTypes": ' + JSON.stringify(patternlab.patternTypes) + '};' + eol;
output += 'var navItems = {"patternTypes": ' + JSON.stringify(patternlab.patternTypes) + ', "ishControlsHide": ' + JSON.stringify(patternlab.config.ishControlsHide) + '};' + eol;

//patternPaths
output += 'var patternPaths = ' + JSON.stringify(patternlab.patternPaths) + ';' + eol;
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "patternlab-node",
"description": "Pattern Lab is a collection of tools to help you create atomic design systems. This is the node command line interface (CLI).",
"version": "2.7.1-alpha",
"version": "2.7.1",
"main": "./core/lib/patternlab.js",
"dependencies": {
"diveSync": "^0.3.0",
Expand Down Expand Up @@ -41,6 +41,12 @@
"contributors": [
{
"name": "Geoff Pursell"
},
{
"name": "Raphael Okon"
},
{
"name": "tburny"
}
],
"license": "MIT",
Expand Down
Loading

0 comments on commit b918c8d

Please sign in to comment.