Skip to content

Commit b048e70

Browse files
Merge pull request #480 from pattern-lab/dev
Pattern Lab Node 2.6.0-alpha
2 parents f8d70c5 + aefb32a commit b048e70

15 files changed

+276
-48
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"no-with": 2,
6868
"quotes": [0, "single"],
6969
"radix": 2,
70-
"semi": [0, "never"],
70+
"semi": [1, "always"],
7171
"strict": 0,
7272
"space-before-blocks": 1,
7373
"space-before-function-paren": [1, {

core/lib/annotation_exporter.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ var annotations_exporter = function (pl) {
5959
//take the annotation snippets and split them on our custom delimiter
6060
var annotationsYAML = annotationsMD.split('~*~');
6161
for (var i = 0; i < annotationsYAML.length; i++) {
62-
var annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser)
62+
var annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser);
6363
annotations.push(annotation);
6464
}
6565
return false;
66-
}
66+
};
6767
}
6868

6969
/*
@@ -72,7 +72,7 @@ var annotations_exporter = function (pl) {
7272
function parseAnnotationsMD() {
7373
var markdown_parser = new mp();
7474
var annotations = [];
75-
var mdFiles = glob.sync(paths.source.annotations + '/*.md')
75+
var mdFiles = glob.sync(paths.source.annotations + '/*.md');
7676

7777
mdFiles.forEach(parseMDFile(annotations, markdown_parser));
7878
return annotations;

core/lib/object_factory.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,19 @@ Pattern.prototype = {
8787
// calculated path from the root of the public directory to the generated html
8888
// file for this pattern.
8989
// Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html'
90-
getPatternLink: function (patternlab, suffixType) {
90+
getPatternLink: function (patternlab, suffixType, customfileExtension) {
9191
// if no suffixType is provided, we default to rendered
9292
var suffixConfig = patternlab.config.outputFileSuffixes;
9393
var suffix = suffixType ? suffixConfig[suffixType] : suffixConfig.rendered;
9494

9595
if (suffixType === 'rawTemplate') {
9696
return this.name + path.sep + this.name + suffix + this.fileExtension;
9797
}
98+
99+
if (suffixType === 'custom') {
100+
return this.name + path.sep + this.name + customfileExtension;
101+
}
102+
98103
return this.name + path.sep + this.name + suffix + '.html';
99104
},
100105

core/lib/pattern_assembler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ var pattern_assembler = function () {
551551
parseDataLinks(patternlab);
552552
},
553553
parse_data_links_specific: function (patternlab, data, label) {
554-
return parseDataLinksHelper(patternlab, data, label)
554+
return parseDataLinksHelper(patternlab, data, label);
555555
},
556556
parse_pattern_markdown: function (pattern, patternlab) {
557557
parsePatternMarkdown(pattern, patternlab);

core/lib/patternlab.js

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* patternlab-node - v2.5.1 - 2016
2+
* patternlab-node - v2.6.0-alpha - 2016
33
*
44
* Brian Muenzenmeyer, Geoff Pursell, and the web community.
55
* Licensed under the MIT license.
@@ -14,8 +14,13 @@ var diveSync = require('diveSync'),
1414
glob = require('glob'),
1515
_ = require('lodash'),
1616
path = require('path'),
17+
cleanHtml = require('js-beautify').html,
18+
inherits = require('util').inherits,
19+
pm = require('./plugin_manager'),
1720
plutils = require('./utilities');
1821

22+
var EventEmitter = require('events').EventEmitter;
23+
1924
function buildPatternData(dataFilesPath, fs) {
2025
var dataFiles = glob.sync(dataFilesPath + '*.json', {"ignore" : [dataFilesPath + 'listitems.json']});
2126
var mergeObject = {};
@@ -73,6 +78,28 @@ function checkConfiguration(patternlab) {
7378
patternlab.config.outputFileSuffixes = _.extend(outputFileSuffixes, patternlab.config.outputFileSuffixes);
7479
}
7580

81+
/**
82+
* Finds and calls the main method of any found plugins.
83+
* @param patternlab - global data store
84+
*/
85+
function initializePlugins(patternlab) {
86+
var plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json'));
87+
var foundPlugins = plugin_manager.detect_plugins();
88+
89+
if (foundPlugins && foundPlugins.length > 0) {
90+
91+
for (var i = 0; i < foundPlugins.length; i++) {
92+
var plugin = plugin_manager.load_plugin(foundPlugins[i]);
93+
plugin(patternlab);
94+
}
95+
}
96+
}
97+
98+
function PatternLabEventEmitter() {
99+
EventEmitter.call(this);
100+
}
101+
inherits(PatternLabEventEmitter, EventEmitter);
102+
76103
var patternlab_engine = function (config) {
77104
'use strict';
78105

@@ -92,9 +119,13 @@ var patternlab_engine = function (config) {
92119

93120
patternlab.package = fs.readJSONSync(path.resolve(__dirname, '../../package.json'));
94121
patternlab.config = config || fs.readJSONSync(path.resolve(__dirname, '../../patternlab-config.json'));
122+
patternlab.events = new PatternLabEventEmitter();
95123

96124
checkConfiguration(patternlab);
97125

126+
//todo: determine if this is the best place to wire up plugins
127+
initializePlugins(patternlab);
128+
98129
var paths = patternlab.config.paths;
99130

100131
function getVersion() {
@@ -236,6 +267,9 @@ var patternlab_engine = function (config) {
236267
}
237268

238269
function buildPatterns(deletePatternDir) {
270+
271+
patternlab.events.emit('patternlab-build-pattern-start', patternlab);
272+
239273
try {
240274
patternlab.data = buildPatternData(paths.source.data, fs);
241275
} catch (ex) {
@@ -245,7 +279,7 @@ var patternlab_engine = function (config) {
245279
try {
246280
patternlab.listitems = fs.readJSONSync(path.resolve(paths.source.data, 'listitems.json'));
247281
} catch (ex) {
248-
plutils.logRed('missing or malformed' + paths.source.data + 'listitems.json Pattern Lab may not work without this file.');
282+
plutils.logOrange('WARNING: missing or malformed ' + paths.source.data + 'listitems.json file. Pattern Lab may not work without this file.');
249283
patternlab.listitems = {};
250284
}
251285
try {
@@ -268,9 +302,13 @@ var patternlab_engine = function (config) {
268302

269303
pattern_assembler.combine_listItems(patternlab);
270304

305+
patternlab.events.emit('patternlab-build-global-data-end', patternlab);
306+
271307
// diveSync once to perform iterative populating of patternlab object
272308
processAllPatternsIterative(pattern_assembler, paths.source.patterns, patternlab);
273309

310+
patternlab.events.emit('patternlab-pattern-iteration-end', patternlab);
311+
274312
//diveSync again to recursively include partials, filling out the
275313
//extendedTemplate property of the patternlab.patterns elements
276314
processAllPatternsRecursive(pattern_assembler, paths.source.patterns, patternlab);
@@ -384,15 +422,26 @@ var patternlab_engine = function (config) {
384422

385423
var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData);
386424

425+
patternlab.events.emit('patternlab-pattern-write-begin', patternlab, pattern);
426+
387427
//write the compiled template to the public patterns directory
388428
var patternPage = headHTML + pattern.patternPartialCode + footerHTML;
389-
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'rendered'), patternPage);
429+
430+
//beautify the output if configured to do so
431+
var cleanedPatternPage = config.cleanOutputHtml ? cleanHtml(patternPage, {indent_size: 2}) : patternPage;
432+
var cleanedPatternPartialCode = config.cleanOutputHtml ? cleanHtml(pattern.patternPartialCode, {indent_size: 2}) : pattern.patternPartialCode;
433+
var cleanedPatternTemplateCode = config.cleanOutputHtml ? cleanHtml(pattern.template, {indent_size: 2}) : pattern.template;
434+
435+
//write the compiled template to the public patterns directory
436+
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'rendered'), cleanedPatternPage);
390437

391438
//write the mustache file too
392-
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'rawTemplate'), pattern.template);
439+
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'rawTemplate'), cleanedPatternTemplateCode);
393440

394441
//write the encoded version too
395-
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'markupOnly'), pattern.patternPartialCode);
442+
fs.outputFileSync(paths.public.patterns + pattern.getPatternLink(patternlab, 'markupOnly'), cleanedPatternPartialCode);
443+
444+
patternlab.events.emit('patternlab-pattern-write-end', patternlab, pattern);
396445

397446
return true;
398447
});

core/lib/plugin_manager.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"use strict";
2+
3+
var plugin_manager = function (config, configPath) {
4+
var path = require('path'),
5+
fs = require('fs-extra'),
6+
util = require('./utilities');
7+
8+
function loadPlugin(pluginName) {
9+
return require(path.join(process.cwd(), 'node_modules', pluginName));
10+
}
11+
12+
function installPlugin(pluginName) {
13+
try {
14+
var pluginPath = path.resolve(
15+
path.join(process.cwd(), 'node_modules', pluginName)
16+
);
17+
console.log('Attempting to load plugin from', pluginPath);
18+
try {
19+
var pluginDirStats = fs.statSync(pluginPath);
20+
} catch (ex) {
21+
util.logRed(pluginName + ' not found, please use npm to install it first.');
22+
util.logRed(pluginName + ' not loaded.');
23+
return;
24+
}
25+
var pluginPathDirExists = pluginDirStats.isDirectory();
26+
if (pluginPathDirExists) {
27+
28+
//write config entry back
29+
var diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8');
30+
diskConfig[pluginName] = false;
31+
fs.outputFileSync(path.resolve(configPath), JSON.stringify(diskConfig, null, 2));
32+
33+
util.logGreen('Plugin ' + pluginName + ' installed.');
34+
35+
//todo, tell them how to uninstall or disable
36+
37+
}
38+
} catch (ex) {
39+
console.log(ex);
40+
}
41+
}
42+
43+
function detectPlugins() {
44+
var node_modules_path = path.join(process.cwd(), 'node_modules');
45+
return fs.readdirSync(node_modules_path).filter(function (dir) {
46+
var module_path = path.join(process.cwd(), 'node_modules', dir);
47+
return fs.statSync(module_path).isDirectory() && dir.indexOf('plugin-node-') === 0;
48+
});
49+
}
50+
51+
function disablePlugin(pluginName) {
52+
console.log('disablePlugin not implemented yet. No change made to state of plugin', pluginName);
53+
}
54+
55+
function enablePlugin(pluginName) {
56+
console.log('enablePlugin not implemented yet. No change made to state of plugin', pluginName);
57+
}
58+
59+
return {
60+
install_plugin: function (pluginName) {
61+
installPlugin(pluginName);
62+
},
63+
load_plugin: function (pluginName) {
64+
return loadPlugin(pluginName);
65+
},
66+
detect_plugins: function () {
67+
return detectPlugins();
68+
},
69+
disable_plugin: function (pluginName) {
70+
disablePlugin(pluginName);
71+
},
72+
enable_plugin: function (pluginName) {
73+
enablePlugin(pluginName);
74+
}
75+
};
76+
77+
};
78+
79+
module.exports = plugin_manager;

core/lib/pseudopattern_hunter.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ var pseudopattern_hunter = function () {
5151
extendedTemplate: currentPattern.extendedTemplate,
5252
isPseudoPattern: true,
5353
basePattern: currentPattern,
54+
stylePartials: currentPattern.stylePartials,
55+
parameteredPartials: currentPattern.parameteredPartials,
5456

5557
// use the same template engine as the non-variant
5658
engine: currentPattern.engine

core/lib/starterkit_manager.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
var starterkit_manager = function (config) {
44
var path = require('path'),
5+
fetch = require('node-fetch'),
56
fs = require('fs-extra'),
67
util = require('./utilities'),
78
paths = config.paths;
@@ -41,8 +42,35 @@ var starterkit_manager = function (config) {
4142
}
4243
}
4344

45+
/**
46+
* @func listStarterkits
47+
* @desc Fetches starterkit repos from GH API that contain 'starterkit' in their name for the user 'pattern-lab'
48+
* @returns {Promise} Returns an Array<{name,url}> for the starterkit repos
49+
*/
4450
function listStarterkits() {
45-
console.log('https://github.com/search?utf8=%E2%9C%93&q=starterkit+in%3Aname%2C+user%3Apattern-lab&type=Repositories&ref=searchresults');
51+
return fetch('https://api.github.com/search/repositories?q=starterkit+in:name+user:pattern-lab&sort=stars&order=desc', {
52+
method: 'GET',
53+
headers: {
54+
'Accept': 'application/json'
55+
}
56+
}).then(function (res) {
57+
var contentType = res.headers.get('content-type');
58+
if (contentType && contentType.indexOf('application/json') === -1) {
59+
throw new TypeError("StarterkitManager->listStarterkits: Not valid JSON");
60+
}
61+
return res.json();
62+
}).then(function (json) {
63+
if (!json.items || !Array.isArray(json.items)) {
64+
return false;
65+
}
66+
return json.items
67+
.map(function (repo) {
68+
return {name: repo.name, url: repo.html_url};
69+
});
70+
}).catch(function (err) {
71+
console.error(err);
72+
return false;
73+
});
4674
}
4775

4876
function packStarterkit() {
@@ -63,7 +91,7 @@ var starterkit_manager = function (config) {
6391
loadStarterKit(starterkitName, clean);
6492
},
6593
list_starterkits: function () {
66-
listStarterkits();
94+
return listStarterkits();
6795
},
6896
pack_starterkit: function () {
6997
packStarterkit();

core/lib/ui_builder.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ var ui_builder = function () {
9292
if (patternlab.config.debug) {
9393
console.log('Omitting ' + pattern.patternPartial + ' from styleguide patterns because it is defined as a defaultPattern.');
9494
}
95+
patternlab.defaultPattern = pattern;
9596
return true;
9697
}
9798

@@ -245,7 +246,7 @@ var ui_builder = function () {
245246
patternState: pattern.patternState,
246247
patternSrcPath: encodeURI(pattern.subdir + '/' + pattern.fileName),
247248
patternPath: patternPath
248-
}
249+
};
249250
}
250251

251252
/**
@@ -552,8 +553,8 @@ var ui_builder = function () {
552553
//viewAllPaths
553554
output += 'var viewAllPaths = ' + JSON.stringify(patternlab.viewAllPaths) + ';' + eol;
554555

555-
//plugins someday
556-
output += 'var plugins = [];' + eol;
556+
//plugins
557+
output += 'var plugins = ' + JSON.stringify(patternlab.plugins) + ';' + eol;
557558

558559
//smaller config elements
559560
output += 'var defaultShowPatternInfo = ' + (patternlab.config.defaultShowPatternInfo ? patternlab.config.defaultShowPatternInfo : 'false') + ';' + eol;
@@ -611,6 +612,12 @@ var ui_builder = function () {
611612
//build the viewall pages
612613
var allPatterns = buildViewAllPages(headerHTML, patternlab, styleguidePatterns);
613614

615+
//add the defaultPattern if we found one
616+
if (patternlab.defaultPattern) {
617+
allPatterns.push(patternlab.defaultPattern);
618+
addToPatternPaths(patternlab, patternlab.defaultPattern);
619+
}
620+
614621
//build the main styleguide page
615622
var styleguideHtml = pattern_assembler.renderPattern(patternlab.viewAll,
616623
{
@@ -638,7 +645,7 @@ var ui_builder = function () {
638645

639646
return {
640647
buildFrontend: function (patternlab) {
641-
buildFrontend(patternlab)
648+
buildFrontend(patternlab);
642649
},
643650
isPatternExcluded: function (pattern, patternlab) {
644651
return isPatternExcluded(pattern, patternlab);

0 commit comments

Comments
 (0)