diff --git a/bedrock.config.js b/bedrock.config.js index 828bd1f6..49ffd2e8 100644 --- a/bedrock.config.js +++ b/bedrock.config.js @@ -17,6 +17,7 @@ module.exports = { purge: false }, styleguide: { + url: '/styleguide', search: true, colors: './content/scss/_colors.scss', categoryOrder: [ diff --git a/content/templates/_components/aov-icons/02-icon-font.pug b/content/templates/_components/aov-icons/02-icon-font.pug index 3ce37a3c..661982a0 100755 --- a/content/templates/_components/aov-icons/02-icon-font.pug +++ b/content/templates/_components/aov-icons/02-icon-font.pug @@ -1,6 +1,6 @@ -include ../../../../core/templates/mixins/icon-overview +include /core/templates/mixins/icon-overview if config.icons.generateIconFont +iconsOverview('icon-font', 'Icon font') else - p You don't seem to have icon fonts activated in bedrock.config.js. You can safely delete these documentation templates if you are not using an icon font, or document your icon font in your own manner. \ No newline at end of file + p You don't seem to have icon fonts activated in bedrock.config.js. You can safely delete these documentation templates if you are not using an icon font, or document your icon font in your own manner. diff --git a/content/templates/_layouts/master.pug b/content/templates/_layouts/master.pug index 0186dd24..6ef356e6 100644 --- a/content/templates/_layouts/master.pug +++ b/content/templates/_layouts/master.pug @@ -1,8 +1,8 @@ //- Globally expose mixins without output, needed for Bedrock to work -include ../../../core/templates/mixins/icon -include ../../../core/templates/mixins/render-page-tree -include ../../../core/templates/mixins/sample -include ../../../core/templates/mixins/styleguide-settings +include /core/templates/mixins/icon +include /core/templates/mixins/render-page-tree +include /core/templates/mixins/sample +include /core/templates/mixins/styleguide-settings //- Use this include to add your own mixins include ../_mixins/all @@ -51,14 +51,14 @@ html(dir="ltr" lang="en" class=htmlClass ? htmlClass : '') if config.pageTree && config.pageTree.layoutStyle == 'sidebar' .br-prototype-wrapper - include ../../../core/templates/includes/prototype-nav + include /core/templates/includes/prototype-nav .br-prototype-content block body else block body if config.pageTree && config.pageTree.layoutStyle == 'fixed' .br-pagetree-fixed-wrapper - include ../../../core/templates/includes/prototype-nav + include /core/templates/includes/prototype-nav = "\n" diff --git a/content/templates/page-index.pug b/content/templates/page-index.pug index 0ed8d134..7f4de524 100644 --- a/content/templates/page-index.pug +++ b/content/templates/page-index.pug @@ -1,6 +1,6 @@ extends /templates/_layouts/master -include ../../core/templates/mixins/render-page-tree +include /core/templates/mixins/render-page-tree block append headerStyles style. diff --git a/core/discovery/default-config.js b/core/discovery/default-config.js index 85c08245..4b0d96f0 100644 --- a/core/discovery/default-config.js +++ b/core/discovery/default-config.js @@ -27,6 +27,7 @@ const defaultConfig = { * determines whether the styleguide gets generated */ styleguide: { + url: '/styleguide', /** * search [boolean] * Feature flag for search feature @@ -86,4 +87,4 @@ const defaultConfig = { }, }; -module.exports = defaultConfig; \ No newline at end of file +module.exports = defaultConfig; diff --git a/core/discovery/docs.js b/core/discovery/docs.js index 07aee6e0..36b978d1 100644 --- a/core/discovery/docs.js +++ b/core/discovery/docs.js @@ -13,6 +13,8 @@ const config = require('./config'); const locals = require('../templates/locals'); const paths = require('../paths'); +const MultipleBaseDirs = require('../templates/multi-basedirs'); + module.exports = { discover: function () { const docFiles = glob.sync(paths.content.docs) @@ -30,10 +32,11 @@ module.exports = { parsedFile.body = marked(parsedFile.body); } else if (extension === '.pug') { const indentedPugMarkup = parsedFile.body.split('\n').map(line => ` ${line}`).join('\n'); - const markupWithLayout = `extends /../core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; + const markupWithLayout = `extends /core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; const compiler = pug.compile(markupWithLayout, Object.assign({}, config.pug, { - filename: docPath + filename: docPath, + plugins: [MultipleBaseDirs()] })); parsedFile.body = compiler(Object.assign({}, locals.getDefaultLocals(), { pathname: `styleguide/docs/${filename}` diff --git a/core/paths.js b/core/paths.js index 0eb61527..af8ae7cd 100644 --- a/core/paths.js +++ b/core/paths.js @@ -83,8 +83,8 @@ module.exports = { modules: path.join(compiledPath, 'modules/'), js: path.join(compiledPath, 'js/'), css: path.join(compiledPath, 'css/'), - styleguide: path.join(compiledPath, 'styleguide/'), - docs: path.join(compiledPath, 'styleguide/docs/'), + styleguide: path.join(compiledPath, config.styleguide.url), + docs: path.join(compiledPath, config.styleguide.url+'/docs/'), assets: { images: path.join(compiledPath, 'images/'), fonts: path.join(compiledPath, 'fonts/'), @@ -100,8 +100,8 @@ module.exports = { mainPath: path.join(distPath, 'css/'), allFiles: path.join(distPath, 'css/**/*.css'), }, - styleguide: path.join(distPath, 'styleguide/'), - docs: path.join(distPath, 'styleguide/docs/'), + styleguide: path.join(distPath, config.styleguide.url), + docs: path.join(distPath, config.styleguide.url+'/docs/'), assets: { images: path.join(distPath, 'images/'), fonts: path.join(distPath, 'fonts/'), diff --git a/core/tasks/server.js b/core/tasks/server.js index d8b78082..fcfee9dc 100644 --- a/core/tasks/server.js +++ b/core/tasks/server.js @@ -45,13 +45,13 @@ function renderView(req, res, viewName, customLocals) { } module.exports = function (done) { - app.get('/styleguide', function (req, res) { + app.get(config.styleguide.url, function (req, res) { renderView(req, res, 'styleguide/index', { pathname: 'styleguide/index' }); }); - app.get('/styleguide/docs/:doc', function (req, res) { + app.get(config.styleguide.url+'/docs/:doc', function (req, res) { const docFilename = req.params.doc.replace('.html', ''); const doc = _.find(docs.discover().allDocs, doc => doc.attributes.filename === docFilename); @@ -61,7 +61,7 @@ module.exports = function (done) { }); }); - app.get('/styleguide/:group', function (req, res) { + app.get(config.styleguide.url+'/:group', function (req, res) { const componentGroups = components.discover(); const componentGroup = req.params.group.replace('.html', ''); diff --git a/core/tasks/templates.js b/core/tasks/templates.js index 4f2f1074..80aedc84 100644 --- a/core/tasks/templates.js +++ b/core/tasks/templates.js @@ -20,6 +20,12 @@ const paths = require('../paths'); const locals = require('../templates/locals'); const docs = require('../discovery/docs'); +const MultipleBaseDirs = require('../templates/multi-basedirs'); + +config.pug.plugins = [MultipleBaseDirs()]; + +const bedrockDir = path.join(__dirname, '../../'); + function getDefaultLocals() { const defaultLocals = locals.getDefaultLocals(); defaultLocals.docs = docs.discover(); @@ -28,9 +34,10 @@ function getDefaultLocals() { module.exports = { clean(done) { - del(['./dist/**.html', './dist/modules', './dist/styleguide']).then(function () { - done(); - }); + del(['./dist/**.html', './dist/modules', './dist'+config.styleguide.url]) + .then(function () { + done(); + }); }, compile: { styleguide(done) { @@ -38,7 +45,7 @@ module.exports = { const tasks = Object.keys(defaultLocals.components.byGroup).map(componentGroup => { return gulp.src([ - paths.core.templates.styleguide.componentGroup + path.join(bedrockDir, paths.core.templates.styleguide.componentGroup) ]) .pipe(data(function (file) { return Object.assign({}, getDefaultLocals(), { @@ -56,7 +63,7 @@ module.exports = { tasks.push( gulp.src([ - paths.core.templates.styleguide.index + path.join(bedrockDir, paths.core.templates.styleguide.index) ]) .pipe(data(function (file) { return Object.assign({}, getDefaultLocals(), { @@ -78,7 +85,9 @@ module.exports = { const defaultLocals = getDefaultLocals(); const tasks = defaultLocals.docs.allDocs.map(doc => { - return gulp.src(paths.core.templates.styleguide.doc) + return gulp.src( + path.join(bedrockDir, paths.core.templates.styleguide.doc) + ) .pipe(data(function (file) { return Object.assign({}, getDefaultLocals(), { doc, diff --git a/core/templates/includes/styleguide-nav.pug b/core/templates/includes/styleguide-nav.pug index c90fb019..35b767ef 100644 --- a/core/templates/includes/styleguide-nav.pug +++ b/core/templates/includes/styleguide-nav.pug @@ -7,8 +7,8 @@ .br-docs-category-list-wrapper(class=styleguideNavListWrapperClass) ul(class=styleguideNavListClass) each doc in docs.byCategory[docsCategoryName] - li(class=styleguideNavListItemClass+' '+`${ "styleguide/docs/" + doc.attributes.filename == pathname ? styleguideNavListItemActiveClass : "" }`) - a(href=`/styleguide/docs/${doc.attributes.filename}.html` class=styleguideNavListItemLinkClass+' '+`${ "styleguide/docs/" + doc.attributes.filename == pathname ? styleguideNavListItemLinkActiveClass : "" }`) + li(class=styleguideNavListItemClass+' '+`${ config.styleguide.url+'/docs/' + doc.attributes.filename == pathname ? styleguideNavListItemActiveClass : "" }`) + a(href=config.styleguide.url+`/docs/${doc.attributes.filename}.html` class=styleguideNavListItemLinkClass+' '+`${ config.styleguide.url+'/docs/' + doc.attributes.filename == pathname ? styleguideNavListItemLinkActiveClass : "" }`) | #{doc.attributes.title} if docsCategoryName === 'Components' && Object.keys(components.byCategory).length > 0 each category, categoryName in components.byCategory @@ -21,8 +21,8 @@ ul(class=styleguideNavListClass) each group in category - var groupName = group.docs ? group.docs.attributes.title || group.group.id : group.group.id - li(class=styleguideNavListItemClass+' '+`${ "styleguide/" + group.group.id == pathname ? styleguideNavListItemActiveClass : "" }`) - a(href=`/styleguide/${group.group.id}.html` class=styleguideNavListItemLinkClass+' '+`${ ("styleguide/" + group.group.id) == pathname ? styleguideNavListItemLinkActiveClass : "" }`) + li(class=styleguideNavListItemClass+' '+`${ config.styleguide.url + '/' + group.group.id == pathname ? styleguideNavListItemActiveClass : "" }`) + a(href=config.styleguide.url+`/${group.group.id}.html` class=styleguideNavListItemLinkClass+' '+`${ (config.styleguide.url + '/' + group.group.id) == pathname ? styleguideNavListItemLinkActiveClass : "" }`) | #{groupName} if group.docs.attributes.containsCustom .br-docs-category-marker-custom diff --git a/core/templates/layouts/sample.pug b/core/templates/layouts/sample.pug index 911487f1..953e2348 100644 --- a/core/templates/layouts/sample.pug +++ b/core/templates/layouts/sample.pug @@ -1,4 +1,4 @@ -include ../../../content/templates/_mixins/all +include /templates/_mixins/all include ../mixins/icon diff --git a/core/templates/locals.js b/core/templates/locals.js index 09f55a9e..6d0654e6 100644 --- a/core/templates/locals.js +++ b/core/templates/locals.js @@ -9,6 +9,8 @@ const config = require('../discovery/config'); const paths = require('../paths'); const beautifyHTML = require('js-beautify').html; +const MultipleBaseDirs = require('../templates/multi-basedirs'); + function indentCode(code) { return code.split('\n').map(line => ` ${line}`).join('\n'); } @@ -27,6 +29,7 @@ function getDefaultLocals() { const locals = { basedir: './content/', + plugins: [MultipleBaseDirs()], contentData: contentData.discover(), components: components.discover(), pages: pages.discover(), @@ -52,13 +55,14 @@ function getDefaultLocals() { } else if (language === 'html') { const indentedPugMarkup = indentCode(pugMarkup); - const markupWithLayout = `extends /../core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; + const markupWithLayout = `extends /core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; // First compile Pug var a = pug.compile(markupWithLayout, { pretty: true, basedir: 'content', - filename: componentFileLocation + filename: componentFileLocation, + plugins: [MultipleBaseDirs()] })(locals); // Then beautify with JS beautify settings @@ -70,13 +74,14 @@ function getDefaultLocals() { // I know we are repeating 8 lines of code from above, could be made more DRY const indentedPugMarkup = pugMarkup.split('\n').map(line => ` ${line}`).join('\n'); - const markupWithLayout = `extends /../core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; + const markupWithLayout = `extends /core/templates/layouts/sample\n\nblock content\n${indentedPugMarkup}`; // First compile Pug var compiledPug = pug.compile(markupWithLayout, { pretty: true, basedir: 'content', - filename: componentFileLocation + filename: componentFileLocation, + plugins: [MultipleBaseDirs()] })(locals); const reactFunctionBegin = `{/* Note that this is merely a starting point for a real React component */} diff --git a/core/templates/mixins/render-page-tree.pug b/core/templates/mixins/render-page-tree.pug index 030a5ba4..bd3fab0f 100644 --- a/core/templates/mixins/render-page-tree.pug +++ b/core/templates/mixins/render-page-tree.pug @@ -24,7 +24,7 @@ mixin renderDirectory(entry) mixin renderPageTree ul.br-bordered-list if config.styleguide - li: a(href="/styleguide") Styleguide + li: a(href=config.styleguide.url) Styleguide each entry in pages if entry.type === 'directory' +renderDirectory(entry) diff --git a/core/templates/multi-basedirs.js b/core/templates/multi-basedirs.js new file mode 100644 index 00000000..9704780d --- /dev/null +++ b/core/templates/multi-basedirs.js @@ -0,0 +1,53 @@ +/* + * This is a Pug plugin to allow multiple basedirs. This is used to have Pug + * templates in both Bedrock core and in a project that uses Bedrock. + * + * From https://github.com/pugjs/pug/issues/2499 and + * https://github.com/gryphonmyers/pug-multiple-basedirs-plugin + */ + +const { accessSync, constants: {R_OK} } = require('fs'); +const path = require('path'); + +const config = require('../discovery/config'); + +// The multiple basedirs are the user-defined basedir plus Bedrock's. Adding +// bedrockDir allows to refer to Bedrock's core templates with the /core +// prefix. Adding it at the end allows users to override core templates. +const bedrockDir = path.join(__dirname, '../../'); +const basedirs = [config.pug.basedir, bedrockDir]; + +const exists = filename => { + try { + accessSync(filename, R_OK); + return true; + } catch (err) { + return false; + } +}; + +function MultipleBaseDirs() { + return { + name: 'multipleBasedirs', + resolve(filename, source) { + let out; + + if (filename[0] === '/') { + filename = filename.substr(1); + if (!basedirs.some(basedir => exists(out = path.resolve(basedir, filename)))) { + throw new Error(`${filename} cannot be found in any basedir`); + } + } else { + if (!source) { + throw new Error('the "filename" option is required to use includes and extends with "relative" paths'); + } + + out = path.resolve(path.dirname(source), filename); + } + + return out; + } + }; +} + +module.exports = MultipleBaseDirs; diff --git a/core/templates/styleguide/index.pug b/core/templates/styleguide/index.pug index 03b70185..a414f0c9 100644 --- a/core/templates/styleguide/index.pug +++ b/core/templates/styleguide/index.pug @@ -11,7 +11,7 @@ block body .br-styleguide-header if styleguideBrandCustomTemplate - include ../../../content/docs/templates/styleguide-custom-brand-template + include /docs/templates/styleguide-custom-brand-template else if styleguideLogoAsImage a(href=styleguideBrandLink?styleguideBrandLink:"") @@ -23,7 +23,7 @@ block body if config.styleguide.search .br-styleguide-search if styleguideSearchCustomTemplate - include ../../../content/docs/templates/styleguide-custom-search-template + include /docs/templates/styleguide-custom-search-template else input#styleguideSearch(type="search" placeholder=styleguideSearchPlaceholderString class=styleguideInputClass)