Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] auto-discovery of freestyle components #178

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
{
files: [
'index.js',
'lib/freestyle-discovery.js',
'testem.js',
'ember-cli-build.js',
'config/**/*.js',
Expand Down
10 changes: 10 additions & 0 deletions addon/components/freestyle-auto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Component from '@ember/component';
import layout from '../templates/components/freestyle-auto';
import { inject as service } from '@ember/service';
import { readOnly } from '@ember/object/computed';

export default Component.extend({
layout,
emberFreestyle: service(),
components: readOnly('emberFreestyle.discoveredComponents')
});
3 changes: 3 additions & 0 deletions addon/templates/components/freestyle-auto.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{#each components as |c|}}
{{component c}}
{{/each}}
1 change: 1 addition & 0 deletions app/components/freestyle-auto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-freestyle/components/freestyle-auto';
7 changes: 6 additions & 1 deletion app/services/ember-freestyle.js
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export { default } from 'ember-freestyle/services/ember-freestyle';
import Service from 'ember-freestyle/services/ember-freestyle';
import discoveredComponents from '../-freestyle/discovered-components';

export default Service.extend({
discoveredComponents
});
6 changes: 5 additions & 1 deletion ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ module.exports = function(defaults) {
},
freestyle: {
snippetSearchPaths: ["tests/dummy/app", "addon/styles"]
}
},
"ember-cli-babel": {
includePolyfill: true
},
es3Safe: false,
});

if (defaults.project.findAddonByName("ember-native-dom-event-dispatcher")) {
Expand Down
44 changes: 42 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict';
var mergeTrees = require('broccoli-merge-trees');
var fs = require('fs');
var fs = require('fs');
var flatiron = require('broccoli-flatiron');
var freestyleUsageSnippetFinder = require('./freestyle-usage-snippet-finder');
var FreestyleDiscovery = require('./lib/freestyle-discovery');
var Funnel = require('broccoli-funnel');

module.exports = {
name: 'ember-freestyle',
Expand All @@ -27,6 +29,24 @@ module.exports = {
return mergeTrees(treesToMerge);
},

preprocessTree: function(type, tree) {
if (type === 'js') {
var treesToMerge = [tree];
let discoveredComponents = FreestyleDiscovery(tree, {
appName: this.app.name,
outputFile: '/-freestyle/discovered-components.js'
});

discoveredComponents = new Funnel(discoveredComponents, {
destDir: this.app.name
});

treesToMerge.push(discoveredComponents);
tree = mergeTrees(treesToMerge);
}
return tree;
},

snippetPaths: function() {
if (this.app) {
var freestyleOptions = this.app.options.freestyle || {};
Expand All @@ -43,8 +63,28 @@ module.exports = {
return ['app'];
},

included: function(/*app, parentAddon*/) {
included: function(app, parentAddon) {
this._super.included.apply(this, arguments);

// Quick fix for add-on nesting
// https://github.com/aexmachina/ember-cli-sass/blob/v5.3.0/index.js#L73-L75
// see: https://github.com/ember-cli/ember-cli/issues/3718
while (typeof app.import !== 'function' && (app.app || app.parent)) {
app = app.app || app.parent;
}

// if app.import and parentAddon are blank, we're probably being consumed by an in-repo-addon
// or engine, for which the "bust through" technique above does not work.
if (typeof app.import !== 'function' && !parentAddon) {
if (app.registry && app.registry.app) {
app = app.registry.app;
}
}

// Per the ember-cli documentation
// http://ember-cli.com/extending/#broccoli-build-options-for-in-repo-addons
let target = (parentAddon || app);
this.options = target.options || {};
},

isDevelopingAddon: function() {
Expand Down
58 changes: 58 additions & 0 deletions lib/freestyle-discovery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';
var Writer = require('broccoli-writer');
var path = require('path');
var glob = require('glob');
var fs = require('fs');

FreestyleDiscovery.prototype = Object.create(Writer.prototype);
FreestyleDiscovery.prototype.constructor = FreestyleDiscovery;

function FreestyleDiscovery(inputTree, options) {
if (!(this instanceof FreestyleDiscovery)) {
return new FreestyleDiscovery(inputTree, options);
}

this.inputTree = inputTree;
var freestyleComponentName = options.freestyleComponentName || 'freestyle';
var defaultGlobPattern = `**/{${freestyleComponentName}/component.js,${options.appName}/components/${freestyleComponentName}/**/*.js}`;
this.options = {
outputFile: options.outputFile,
freestyleComponentName: freestyleComponentName,
componentPathGlobPattern: options.componentPathGlobPattern || defaultGlobPattern,
extractComponentName: options.extractComponentName || function extractComponentName(componentPath) {
// Extract a freestyle component name that looks like:
// x-bay/freestyle
// from a componentPath that looks like:
// /Users/xxxxx/p/xxxxx/ember-freestyle/tmp/broccoli_merge_trees-output_path-7BiiNpHw.tmp/dummy/components/x-bay/freestyle/component.js
// or
// /Users/xxxxx/p/xxxxx/ember-freestyle/tmp/broccoli_merge_trees-output_path-7BiiNpHw.tmp/dummy/components/x-bay/freestyle.js
var regexp = new RegExp(`${options.appName}/components/(.+/${freestyleComponentName})(?:/component)?.js$`);
var match = regexp.exec(componentPath);
if (!match) {
regexp = new RegExp(`${options.appName}/components/(${freestyleComponentName}/.+)(?:/component)?.js$`);
match = regexp.exec(componentPath);
}
if (match) {
return match[1].replace(/\/component$/,'');
}
}
};
}

FreestyleDiscovery.prototype.write = function(readTree, destDir) {
var _this = this;
var componentPathGlobPattern = this.options.componentPathGlobPattern;
var extractComponentName = this.options.extractComponentName;

return readTree(this.inputTree).then(function(srcDir) {
var files = glob.sync(path.join(srcDir, componentPathGlobPattern));
var components = files.map(extractComponentName).filter((name) => {
return name && !(/template$/.test(name));
});
var output = `export default ${JSON.stringify(components)};`;
fs.mkdirSync(path.join(destDir, path.dirname(_this.options.outputFile)));
fs.writeFileSync(path.join(destDir, _this.options.outputFile), output);
});
}

module.exports = FreestyleDiscovery;
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"dependencies": {
"broccoli-flatiron": "0.1.2",
"broccoli-funnel": "^2.0.1",
"broccoli-merge-trees": "^2.0.0",
"broccoli-writer": "^0.1.1",
"ember-cli-babel": "^6.6.0",
Expand All @@ -40,7 +41,7 @@
"ember-cli-github-pages": "0.2.0",
"ember-cli-htmlbars-inline-precompile": "^1.0.0",
"ember-cli-inject-live-reload": "^1.4.1",
"ember-cli-page-object": "^1.13.0-alpha.1",
"ember-cli-page-object": "^1.14.0",
"ember-cli-qunit": "^4.1.1",
"ember-cli-release": "v1.0.0-beta.2",
"ember-cli-sass-lint": "^1.0.3",
Expand All @@ -55,7 +56,8 @@
"eslint-config-ember": "0.3.0",
"eslint-plugin-ember": "^5.0.0",
"eslint-plugin-node": "^6.0.0",
"loader.js": "^4.2.3"
"loader.js": "^4.2.3",
"qunit-dom": "^0.6.3"
},
"engines": {
"node": "^4.5 || 6.* || >= 7.*"
Expand Down
19 changes: 19 additions & 0 deletions tests/acceptance/auto-discover-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { test } from 'qunit';
import moduleForAcceptance from '../../tests/helpers/module-for-acceptance';
import freestyleGuide from '../pages/freestyle-guide';
import discoveredComponents from 'dummy/-freestyle/discovered-components';

moduleForAcceptance('Acceptance | auto-discover', {
beforeEach() {
freestyleGuide.visit();
}
});

test('verifying auto discovery', async function(assert) {
assert.ok(discoveredComponents.includes('x-baz/freestyle'), 'includes discovered x-baz/freestyle component');
assert.ok(discoveredComponents.includes('freestyle/x-bay'), 'includes discovered freestyle/x-bay component');
assert.ok(discoveredComponents.includes('freestyle/x-qux'), 'includes discovered freestyle/x-qux component');
assert.dom('.x-Baz-title').hasText('Just a static x-baz title');
assert.dom('.x-Bay-title').hasText('Just a static x-bay title');
assert.dom('.x-Qux-title').hasText('Just a static x-qux title');
});
11 changes: 6 additions & 5 deletions tests/acceptance/section-navigation-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ test('verifying header', (assert) => {
});

test('verifying menu sections', (assert) => {
assert.expect(5);
assert.expect(6);
andThen(() => {
assert.equal(freestyleGuide.menu.sections.length, 4);
assert.equal(freestyleGuide.menu.sections.length, 5);
assert.equal(freestyleGuide.menu.sections.objectAt(0).text, 'All');
assert.equal(freestyleGuide.menu.sections.objectAt(1).text, 'Foo Things');
assert.equal(freestyleGuide.menu.sections.objectAt(2).text, 'Dynamic Properties');
assert.equal(freestyleGuide.menu.sections.objectAt(3).text, 'Visual Style');
assert.equal(freestyleGuide.menu.sections.objectAt(2).text, 'Auto-Discovered');
assert.equal(freestyleGuide.menu.sections.objectAt(3).text, 'Dynamic Properties');
assert.equal(freestyleGuide.menu.sections.objectAt(4).text, 'Visual Style');
});
});

Expand All @@ -35,7 +36,7 @@ test('navigating directly to a subsection', function(assert) {
assert.equal(sectionFooThings.subsections.objectAt(0).text, 'Foo Subsection A');
assert.equal(sectionFooThings.subsections.objectAt(1).text, 'Foo Subsection B');

let sectionVisualStyle = freestyleGuide.menu.sections.objectAt(3);
let sectionVisualStyle = freestyleGuide.menu.sections.objectAt(4);
assert.equal(sectionVisualStyle.subsections.length, 2);
assert.equal(sectionVisualStyle.subsections.objectAt(0).text, 'Typography');
assert.equal(sectionVisualStyle.subsections.objectAt(1).text, 'Color');
Expand Down
53 changes: 23 additions & 30 deletions tests/acceptance/section-rendering-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,36 @@ import moduleForAcceptance from '../../tests/helpers/module-for-acceptance';
import freestyleGuide from '../pages/freestyle-guide';

moduleForAcceptance('Acceptance | section rendering', {
beforeEach() {
freestyleGuide.visit();
async beforeEach() {
await freestyleGuide.visit();
}
});

test('verifying guide sections', (assert) => {
assert.expect(4);
andThen(() => {
assert.equal(freestyleGuide.content.sections.length, 3);
assert.equal(freestyleGuide.content.sections.objectAt(0).text, 'Foo Things');
assert.equal(freestyleGuide.content.sections.objectAt(1).text, 'Dynamic Properties');
assert.equal(freestyleGuide.content.sections.objectAt(2).text, 'Visual Style');
});
test('verifying guide sections', async function(assert) {
assert.expect(5);
assert.equal(freestyleGuide.content.sections.length, 4, '4 sections rendered');
assert.equal(freestyleGuide.content.sections.objectAt(0).text, 'Foo Things');
assert.equal(freestyleGuide.content.sections.objectAt(1).text, 'Auto-Discovered');
assert.equal(freestyleGuide.content.sections.objectAt(2).text, 'Dynamic Properties');
assert.equal(freestyleGuide.content.sections.objectAt(3).text, 'Visual Style');
});

test('verifying guide subsections', (assert) => {
test('verifying guide subsections', async function(assert) {
assert.expect(6);
andThen(() => {
let sectionFooThings = freestyleGuide.content.sections.objectAt(0);
assert.equal(sectionFooThings.subsections.length, 2);
assert.equal(sectionFooThings.subsections.objectAt(0).text, 'Foo Subsection A');
assert.equal(sectionFooThings.subsections.objectAt(1).text, 'Foo Subsection B');

let sectionVisualStyle = freestyleGuide.content.sections.objectAt(2);
assert.equal(sectionVisualStyle.subsections.length, 2);
assert.equal(sectionVisualStyle.subsections.objectAt(0).text, 'Typography');
assert.equal(sectionVisualStyle.subsections.objectAt(1).text, 'Color');
});
let sectionFooThings = freestyleGuide.content.sections.objectAt(0);
assert.equal(sectionFooThings.subsections.length, 2, '2 subsections in first section');
assert.equal(sectionFooThings.subsections.objectAt(0).text, 'Foo Subsection A');
assert.equal(sectionFooThings.subsections.objectAt(1).text, 'Foo Subsection B');

let sectionVisualStyle = freestyleGuide.content.sections.objectAt(3);
assert.equal(sectionVisualStyle.subsections.length, 2, '2 subsections in fourth section');
assert.equal(sectionVisualStyle.subsections.objectAt(0).text, 'Typography');
assert.equal(sectionVisualStyle.subsections.objectAt(1).text, 'Color');
});

test('freestyle notes show up', (assert) => {
test('freestyle notes show up', async function(assert) {
assert.expect(1);
andThen(() => {
let sectionFooThings = freestyleGuide.content.sections.objectAt(0);
let note = sectionFooThings.subsections.objectAt(0).collections.objectAt(0).variants.objectAt(0).noteContent[1];

assert.ok(note.includes('Another Note About Normal'));
})
})
let sectionFooThings = freestyleGuide.content.sections.objectAt(0);
let note = sectionFooThings.subsections.objectAt(0).collections.objectAt(0).variants.objectAt(0).noteContent[1];
assert.ok(note.includes('Another Note About Normal'));
});
6 changes: 6 additions & 0 deletions tests/dummy/app/components/freestyle/x-bay/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Component from '@ember/component';
import layout from './template';

export default Component.extend({
layout
});
6 changes: 6 additions & 0 deletions tests/dummy/app/components/freestyle/x-bay/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{{#freestyle-usage 'x-bay' title='x-bay'}}
{{x-bay
title='Just a static x-bay title'
size=15
}}
{{/freestyle-usage}}
3 changes: 3 additions & 0 deletions tests/dummy/app/components/freestyle/x-qux.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Component from '@ember/component';

export default Component.extend();
12 changes: 12 additions & 0 deletions tests/dummy/app/components/x-bay/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Component from '@ember/component';
import layout from './template';

export default Component.extend({
layout,
title: 'Default Title',
description: 'Default Description',
size: 'medium',
showBorder: true,
isVisible: true,
isTasteful: false,
});
13 changes: 13 additions & 0 deletions tests/dummy/app/components/x-bay/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="x-Bay
x-Bay--{{size}}
{{unless showBorder 'x-Bay--hide-border'}}
{{unless isVisible 'x-Bay--hidden'}}
{{if isTasteful 'x-Bay--tasteful'}}">
<div class="x-Bay-title">
{{title}}
</div>
<p>{{description}}</p>
<div class="x-Bay-description">
{{yield}}
</div>
</div>
12 changes: 12 additions & 0 deletions tests/dummy/app/components/x-baz/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Component from '@ember/component';
import layout from './template';

export default Component.extend({
layout,
title: 'Default Title',
description: 'Default Description',
size: 'medium',
showBorder: true,
isVisible: true,
isTasteful: false,
});
3 changes: 3 additions & 0 deletions tests/dummy/app/components/x-baz/freestyle/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Component from '@ember/component';

export default Component.extend();
11 changes: 11 additions & 0 deletions tests/dummy/app/components/x-baz/freestyle/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{#freestyle-usage 'x-baz' title='x-baz'}}
{{x-baz
title='Just a static x-baz title'
size=10
showBorder=true
rank=2
isVisible=true
isTasteful=true
innerBorderThickness=3
}}
{{/freestyle-usage}}
Loading