@penskemediacorp/larva 1.2.0-alpha.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +6 -0
- package/LICENSE +21 -0
- package/README.md +119 -4
- package/__tests__/fixtures/build/css/common.inline.css +1 -0
- package/__tests__/fixtures/build/images/test.png +0 -0
- package/__tests__/fixtures/build/js/larva-ui.js +1 -0
- package/__tests__/fixtures/build/svg/defs/sprite.svg +1 -0
- package/__tests__/fixtures/larva.config.js +43 -0
- package/__tests__/fixtures/public/some-library.js +1 -0
- package/__tests__/fixtures/src/patterns/__tests__/.gitkeep +0 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.featured.aia.js +3 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.featured.js +3 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.js +1 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.json +3 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.prototype.js +3 -0
- package/__tests__/fixtures/src/patterns/components/c-nav-link/c-nav-link.twig +3 -0
- package/__tests__/fixtures/src/patterns/components/c-tagline/c-tagline.prototype.js +3 -0
- package/__tests__/fixtures/src/patterns/modules/_also-ignored/_also-ignored.prototype.js +3 -0
- package/__tests__/fixtures/src/patterns/modules/_also-ignored/_also-ignored.twig +3 -0
- package/__tests__/fixtures/src/patterns/modules/ignore-me/ignore-me.prototype.js +0 -0
- package/__tests__/fixtures/src/patterns/modules/ignore-me/ignore-me.twig +0 -0
- package/__tests__/fixtures/src/patterns/modules/test-module/test-module.featured.js +3 -0
- package/__tests__/fixtures/src/patterns/modules/test-module/test-module.prototype.js +3 -0
- package/__tests__/fixtures/src/patterns/modules/test-module/test-module.twig +0 -0
- package/__tests__/fixtures/src/patterns/objects/_objects.scss +0 -0
- package/__tests__/fixtures/src/patterns/objects/o-crap/o-crap.json +3 -0
- package/__tests__/fixtures/src/patterns/objects/o-crap/o-crap.scss +0 -0
- package/__tests__/fixtures/src/patterns/objects/o-crap/o-crap.twig +1 -0
- package/__tests__/fixtures/src/patterns/objects/o-nav/o-nav.twig +14 -0
- package/__tests__/fixtures/src/patterns/one-offs/newswire/newswire.html +1 -0
- package/__tests__/fixtures/src/patterns/one-offs/newswire/newswire.prototype.js +3 -0
- package/__tests__/fixtures/template-parts/some-template.php +3 -0
- package/__tests__/lib/generateStatic.test.js +140 -0
- package/__tests__/lib/utils/clonePatternData.test.js +23 -0
- package/__tests__/lib/utils/getAllPatternsObj.test.js +45 -0
- package/__tests__/lib/utils/getAppConfiguration.test.js +13 -0
- package/__tests__/lib/utils/getModuleNamesFromDirectory.test.js +23 -0
- package/__tests__/lib/utils/getPatternData.test.js +55 -0
- package/__tests__/lib/utils/getPatternPathsToLoad.test.js +13 -0
- package/__tests__/lib/utils/getPatternRoutes.test.js +29 -0
- package/__tests__/lib/utils/getPatternType.test.js +16 -0
- package/__tests__/lib/utils/getPatternVariants.test.js +20 -0
- package/__tests__/lib/utils/getPatternsIndexPath.test.js +9 -0
- package/__tests__/lib/utils/getSubDirectoryNames.test.js +17 -0
- package/__tests__/lib/utils/isCoreTheme.test.js +12 -0
- package/__tests__/lib/utils/writeJsonToFile.test.js +29 -0
- package/__tests__/lib/writeJson.test.js +83 -0
- package/bin/larva.js +25 -0
- package/build/css/larva-important.css +1 -0
- package/build/css/larva-ui.css +1 -0
- package/build/css/larva.css +1 -0
- package/build/css/larva.inline-important.css +1 -0
- package/build/css/larva.inline.css +1 -0
- package/build/css/variety.compat-important.css +1 -0
- package/build/css/variety.compat.css +1 -0
- package/build/js/common.js +26 -0
- package/build/js/larva-ui.js +1 -0
- package/build/js/standalone/video-showcase.js +26 -0
- package/build/svg/brand-logo-white.svg +1 -0
- package/build/svg/brand-logo.svg +1 -0
- package/build/svg/defs/sprite.defs.html +852 -0
- package/build/svg/defs/sprite.defs.svg +1 -0
- package/build/tokens/artinamerica.custom-properties.css +546 -0
- package/build/tokens/artinamerica.json +533 -0
- package/build/tokens/artinamerica.map.scss +546 -0
- package/build/tokens/artinamerica.raw.json +4341 -0
- package/build/tokens/artnews.custom-properties.css +550 -0
- package/build/tokens/artnews.json +536 -0
- package/build/tokens/artnews.map.scss +550 -0
- package/build/tokens/artnews.raw.json +4373 -0
- package/build/tokens/bbpro.custom-properties.css +96 -0
- package/build/tokens/bbpro.json +80 -0
- package/build/tokens/bbpro.map.scss +96 -0
- package/build/tokens/bbpro.raw.json +789 -0
- package/build/tokens/billboard.custom-properties.css +96 -0
- package/build/tokens/billboard.json +80 -0
- package/build/tokens/billboard.map.scss +96 -0
- package/build/tokens/billboard.raw.json +789 -0
- package/build/tokens/deadline.custom-properties.css +533 -0
- package/build/tokens/deadline.json +517 -0
- package/build/tokens/deadline.map.scss +533 -0
- package/build/tokens/deadline.raw.json +4204 -0
- package/build/tokens/default.custom-properties.css +533 -0
- package/build/tokens/default.json +517 -0
- package/build/tokens/default.map.scss +533 -0
- package/build/tokens/default.raw.json +4204 -0
- package/build/tokens/dirt.custom-properties.css +81 -0
- package/build/tokens/dirt.json +66 -0
- package/build/tokens/dirt.map.scss +81 -0
- package/build/tokens/dirt.raw.json +690 -0
- package/build/tokens/indiewire.custom-properties.css +536 -0
- package/build/tokens/indiewire.json +520 -0
- package/build/tokens/indiewire.map.scss +536 -0
- package/build/tokens/indiewire.raw.json +4221 -0
- package/build/tokens/rivet.custom-properties.css +82 -0
- package/build/tokens/rivet.json +68 -0
- package/build/tokens/rivet.map.scss +82 -0
- package/build/tokens/rivet.raw.json +703 -0
- package/build/tokens/robbreport.custom-properties.css +536 -0
- package/build/tokens/robbreport.json +518 -0
- package/build/tokens/robbreport.map.scss +536 -0
- package/build/tokens/robbreport.raw.json +4215 -0
- package/build/tokens/rollingstone-2022.custom-properties.css +534 -0
- package/build/tokens/rollingstone-2022.json +519 -0
- package/build/tokens/rollingstone-2022.map.scss +534 -0
- package/build/tokens/rollingstone-2022.raw.json +4035 -0
- package/build/tokens/rollingstone.custom-properties.css +530 -0
- package/build/tokens/rollingstone.json +518 -0
- package/build/tokens/rollingstone.map.scss +530 -0
- package/build/tokens/rollingstone.raw.json +4207 -0
- package/build/tokens/sheknows.custom-properties.css +92 -0
- package/build/tokens/sheknows.json +76 -0
- package/build/tokens/sheknows.map.scss +92 -0
- package/build/tokens/sheknows.raw.json +761 -0
- package/build/tokens/sourcingjournal.custom-properties.css +87 -0
- package/build/tokens/sourcingjournal.json +70 -0
- package/build/tokens/sourcingjournal.map.scss +87 -0
- package/build/tokens/sourcingjournal.raw.json +720 -0
- package/build/tokens/sportico.custom-properties.css +73 -0
- package/build/tokens/sportico.json +59 -0
- package/build/tokens/sportico.map.scss +73 -0
- package/build/tokens/sportico.raw.json +640 -0
- package/build/tokens/thr.custom-properties.css +83 -0
- package/build/tokens/thr.json +67 -0
- package/build/tokens/thr.map.scss +83 -0
- package/build/tokens/thr.raw.json +698 -0
- package/build/tokens/variety-compat.custom-properties.css +36 -0
- package/build/tokens/variety-compat.json +33 -0
- package/build/tokens/variety-compat.map.scss +36 -0
- package/build/tokens/variety-compat.raw.json +224 -0
- package/build/tokens/variety-vip.custom-properties.css +532 -0
- package/build/tokens/variety-vip.json +521 -0
- package/build/tokens/variety-vip.map.scss +532 -0
- package/build/tokens/variety-vip.raw.json +4223 -0
- package/build/tokens/variety.custom-properties.css +534 -0
- package/build/tokens/variety.json +521 -0
- package/build/tokens/variety.map.scss +534 -0
- package/build/tokens/variety.raw.json +4225 -0
- package/build/tokens/vibe.custom-properties.css +77 -0
- package/build/tokens/vibe.json +63 -0
- package/build/tokens/vibe.map.scss +77 -0
- package/build/tokens/vibe.raw.json +668 -0
- package/build/tokens/wwd-2021.custom-properties.css +82 -0
- package/build/tokens/wwd-2021.json +67 -0
- package/build/tokens/wwd-2021.map.scss +82 -0
- package/build/tokens/wwd-2021.raw.json +701 -0
- package/build/tokens/wwd-beauty.custom-properties.css +86 -0
- package/build/tokens/wwd-beauty.json +70 -0
- package/build/tokens/wwd-beauty.map.scss +86 -0
- package/build/tokens/wwd-beauty.raw.json +719 -0
- package/build/tokens/wwd-dd.custom-properties.css +18 -0
- package/build/tokens/wwd-dd.json +13 -0
- package/build/tokens/wwd-dd.map.scss +18 -0
- package/build/tokens/wwd-dd.raw.json +90 -0
- package/build/tokens/wwd.custom-properties.css +70 -0
- package/build/tokens/wwd.json +60 -0
- package/build/tokens/wwd.map.scss +70 -0
- package/build/tokens/wwd.raw.json +643 -0
- package/index.js +7 -0
- package/lib/generateStatic.js +133 -0
- package/lib/server.js +284 -0
- package/lib/start.js +7 -0
- package/lib/utils/clonePatternData.js +13 -0
- package/lib/utils/copySyncHelper.js +33 -0
- package/lib/utils/getAllPatternsObj.js +48 -0
- package/lib/utils/getAppConfiguration.js +82 -0
- package/lib/utils/getArgsFromCli.js +3 -0
- package/lib/utils/getModuleNamesFromDirectory.js +11 -0
- package/lib/utils/getPatternData.js +34 -0
- package/lib/utils/getPatternPathsToLoad.js +20 -0
- package/lib/utils/getPatternRoutes.js +58 -0
- package/lib/utils/getPatternType.js +15 -0
- package/lib/utils/getPatternVariants.js +24 -0
- package/lib/utils/getPatternsIndexPath.js +11 -0
- package/lib/utils/getSubDirectoryNames.js +23 -0
- package/lib/utils/isCoreTheme.js +8 -0
- package/lib/utils/renderSass.js +20 -0
- package/lib/utils/spawnScript.js +26 -0
- package/lib/utils/writeJsonToFile.js +6 -0
- package/lib/writeJson.js +53 -0
- package/package.json +72 -5
- package/public/webfontloader.js +22 -0
- package/scripts/build-html.js +52 -0
- package/scripts/build-icons.js +80 -0
- package/scripts/build-scss.js +15 -0
- package/scripts/config/.eslintrc.json +11 -0
- package/scripts/config/gulpfile.js +191 -0
- package/scripts/config/stylelint.config.js +5 -0
- package/scripts/config/svgo-config.json +67 -0
- package/scripts/config/webpack.config.js +95 -0
- package/scripts/dev-js.js +13 -0
- package/scripts/dev-scss.js +20 -0
- package/scripts/help.js +65 -0
- package/scripts/init.js +21 -0
- package/scripts/larva/.nvmrc +1 -0
- package/scripts/larva/README.md +29 -0
- package/scripts/larva/larva.config.js +3 -0
- package/scripts/larva/src/patterns/README.md +3 -0
- package/scripts/larva/src/patterns/base.html +6 -0
- package/scripts/larva/src/patterns/components/README.md +3 -0
- package/scripts/larva/src/patterns/modules/README.md +3 -0
- package/scripts/larva/src/patterns/objects/README.md +3 -0
- package/scripts/larva/src/patterns/one-offs/README.md +3 -0
- package/scripts/link-all.js +40 -0
- package/scripts/lint-js.js +11 -0
- package/scripts/lint-scss.js +13 -0
- package/scripts/lint.js +73 -0
- package/scripts/prod-js.js +12 -0
- package/scripts/prod-scss.js +24 -0
- package/scripts/prod.js +122 -0
- package/scripts/server.js +11 -0
- package/scripts/start.js +36 -0
- package/scripts/upgrade.js +99 -0
- package/scripts/write-json.js +14 -0
- package/.DS_Store +0 -0
- package/__tests__/larva.test.js +0 -7
- package/lib/larva.js +0 -7
- package/lib/patterns.js +0 -48
- package/setup.scss +0 -1
- package/src/02-generic/breakpoint-label.scss +0 -33
- package/src/06-algorithms/a-glue/a-glue.html +0 -4
- package/src/06-algorithms/a-glue/a-glue.scss +0 -56
- package/src/06-algorithms/a-glue/index.js +0 -1
- package/src/06-algorithms/a-grid.scss +0 -29
- package/src/07-utilities/u-background.scss +0 -5
- package/src/07-utilities/u-color.scss +0 -5
- package/src/07-utilities/u-crop.scss +0 -5
- package/src/07-utilities/u-flex.scss +0 -35
- package/src/07-utilities/u-margin.scss +0 -5
- package/src/07-utilities/u-padding.scss +0 -5
- package/src/07-utilities/u-text.scss +0 -33
- package/src/07-utilities/utilities.scss +0 -5
- package/static/css/components.css +0 -4
- package/static/css/objects.css +0 -21
- package/static/css/prism.css +0 -126
- package/static/js/prism.js +0 -8
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const path = require( 'path' );
|
|
2
|
+
const mkdirp = require( 'mkdirp' );
|
|
3
|
+
const fs = require( 'fs-extra' );
|
|
4
|
+
const chalk = require( 'chalk' );
|
|
5
|
+
const axios = require( 'axios' );
|
|
6
|
+
|
|
7
|
+
const getAppConfiguration = require( './utils/getAppConfiguration' );
|
|
8
|
+
const copySyncHelper = require( './utils/copySyncHelper' );
|
|
9
|
+
|
|
10
|
+
const assetsConfig = getAppConfiguration( 'assets' );
|
|
11
|
+
const themeAssetsConfig = getAppConfiguration( 'themeAssets' );
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate Static HTML
|
|
15
|
+
*
|
|
16
|
+
* Given an array of pattern routes from the Larva server and
|
|
17
|
+
* a target build directory, use HTTP requests the get the HTML content
|
|
18
|
+
* of each route, and write the content to directory structure that
|
|
19
|
+
* mirrors the pattern routes.
|
|
20
|
+
*
|
|
21
|
+
* @param {array} routesArr An array of routes in a pattern server, excluding the pattern source (i.e. larva or project).
|
|
22
|
+
* This is the result of getPatternRoutes.
|
|
23
|
+
* @param {string} buildPath A directory where the HTML files should be written.
|
|
24
|
+
* @param {function} done A callback function to run when the site generation completes.
|
|
25
|
+
* @param {string} urlBase The base URL for the pattern library e.g. 'http://localhost:3001/larva'.
|
|
26
|
+
* Pattern routes will be appended to this. Should not end in slash.
|
|
27
|
+
*
|
|
28
|
+
* @see {@link getPatternRoutes}.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
module.exports = function generateStatic( routesArr, buildPath, done, urlBase = 'http://localhost:3000/larva' ) {
|
|
33
|
+
const errors = [];
|
|
34
|
+
|
|
35
|
+
fs.mkdirpSync( buildPath );
|
|
36
|
+
|
|
37
|
+
// Copy assets from assets/build and assets/public
|
|
38
|
+
// to the static site build directory.
|
|
39
|
+
console.log( '\nCopying assets...\n')
|
|
40
|
+
|
|
41
|
+
// assets/public dir contains fonts and non-built things.
|
|
42
|
+
const publicAssetsSrc = ( () => {
|
|
43
|
+
let pubPath = path.join( assetsConfig.path, `public` );
|
|
44
|
+
|
|
45
|
+
// Fallback to assets in Larva
|
|
46
|
+
if ( ! fs.existsSync( pubPath ) ) {
|
|
47
|
+
pubPath = path.join( assetsConfig.path, 'public' )
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return pubPath;
|
|
51
|
+
})();
|
|
52
|
+
const publicAssetsDest = path.join( buildPath, '../assets/public' );
|
|
53
|
+
|
|
54
|
+
const builtAssets = [
|
|
55
|
+
'js',
|
|
56
|
+
'css',
|
|
57
|
+
'tokens',
|
|
58
|
+
'images',
|
|
59
|
+
'svg'
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
builtAssets.forEach( item => {
|
|
63
|
+
const dest = path.join( buildPath, `../assets/build/${item}` );
|
|
64
|
+
const src = path.join( assetsConfig.path, `build/${item}` );
|
|
65
|
+
|
|
66
|
+
copySyncHelper( src, dest );
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
copySyncHelper( publicAssetsSrc, publicAssetsDest );
|
|
70
|
+
|
|
71
|
+
const themeAssetKeys = Object.keys( themeAssetsConfig );
|
|
72
|
+
|
|
73
|
+
themeAssetKeys.forEach( key => {
|
|
74
|
+
const src = themeAssetsConfig[key];
|
|
75
|
+
const dest = path.join( buildPath, `../assets/theme/${key}` );
|
|
76
|
+
|
|
77
|
+
copySyncHelper( src, dest );
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Build the site.
|
|
81
|
+
// Cycle through the list of routes and write the response
|
|
82
|
+
// to files.
|
|
83
|
+
console.log( '\nBuilding site...\n');
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
|
|
87
|
+
const promises = routesArr.map( ( route ) => {
|
|
88
|
+
|
|
89
|
+
const dir = path.join( buildPath, route );
|
|
90
|
+
const url = `${urlBase}/${route}`;
|
|
91
|
+
|
|
92
|
+
return axios.get( url ).then( ( response ) => {
|
|
93
|
+
|
|
94
|
+
if ( 200 === response.status ) {
|
|
95
|
+
mkdirp.sync( dir );
|
|
96
|
+
fs.writeFileSync( `${dir}/index.html`, response.data );
|
|
97
|
+
console.log( `Built ${route}.` );
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} ).catch( ( e ) => {
|
|
101
|
+
|
|
102
|
+
if ( 'ECONNREFUSED' === e.code ) {
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
} else {
|
|
105
|
+
mkdirp.sync( dir );
|
|
106
|
+
fs.writeFileSync( `${dir}/index.html`, e.message );
|
|
107
|
+
|
|
108
|
+
console.log( chalk.yellow( `Error writing ${route}: ${e.message}.` ) );
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
} );
|
|
114
|
+
|
|
115
|
+
axios.all( promises ).then( () => {
|
|
116
|
+
|
|
117
|
+
if ( errors.length > 0 ) {
|
|
118
|
+
console.log( errors );
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
done( chalk.green( `\nSite built to build/html/${path.basename( buildPath )}. Check output for issues.\n` ) );
|
|
122
|
+
|
|
123
|
+
} ).catch( ( e ) => {
|
|
124
|
+
|
|
125
|
+
done( chalk.bold.red( e ) );
|
|
126
|
+
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
} catch ( e ) {
|
|
130
|
+
console.error( e );
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
}
|
package/lib/server.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
const path = require( 'path' );
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const { marked } = require( 'marked' );
|
|
4
|
+
const fs = require( 'fs' );
|
|
5
|
+
const globby = require( 'globby' );
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
TwingEnvironment,
|
|
9
|
+
TwingLoaderFilesystem,
|
|
10
|
+
TwingFilter,
|
|
11
|
+
TwingFunction
|
|
12
|
+
} = require('twing');
|
|
13
|
+
|
|
14
|
+
const fontData = require( '../../larva-tokens/lib/font-data' );
|
|
15
|
+
|
|
16
|
+
const getAppConfiguration = require('./utils/getAppConfiguration' );
|
|
17
|
+
const getPatternPathsToLoad = require( './utils/getPatternPathsToLoad' );
|
|
18
|
+
const getPatternData = require( './utils/getPatternData' );
|
|
19
|
+
const getAllPatternsObj = require( './utils/getAllPatternsObj' );
|
|
20
|
+
|
|
21
|
+
const app = express();
|
|
22
|
+
|
|
23
|
+
const patternConfig = getAppConfiguration( 'patterns' );
|
|
24
|
+
const brandConfig = getAppConfiguration( 'brand' );
|
|
25
|
+
const assetsConfig = getAppConfiguration( 'assets' );
|
|
26
|
+
const themeAssetsConfig = getAppConfiguration( 'themeAssets' );
|
|
27
|
+
const twigPaths = getPatternPathsToLoad( patternConfig );
|
|
28
|
+
|
|
29
|
+
let loader = new TwingLoaderFilesystem( twigPaths );
|
|
30
|
+
|
|
31
|
+
// Add markdown filter
|
|
32
|
+
const markdownFilter = new TwingFilter( 'markdown', ( string ) => {
|
|
33
|
+
if ( string ) {
|
|
34
|
+
return Promise.resolve( marked( string ) );
|
|
35
|
+
} else {
|
|
36
|
+
const noDocsMessage = '**This needs docs!** <br>Create a README.md in the pattern\'s directory and add details about using this pattern in markdown.';
|
|
37
|
+
|
|
38
|
+
return Promise.resolve( marked( noDocsMessage ) );
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Support `{{ item|markup }}` syntax for outputting escaped content within loops.
|
|
43
|
+
const markupFilter = new TwingFilter(
|
|
44
|
+
'markup',
|
|
45
|
+
( string ) => Promise.resolve( string ),
|
|
46
|
+
{},
|
|
47
|
+
{ is_safe: ['html'] }
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const kebabify = ( name ) => {
|
|
51
|
+
let kebabCase = [];
|
|
52
|
+
|
|
53
|
+
// TODO: find a more concise way of turning a string into an iterable
|
|
54
|
+
for (let i = 0; i < name.length; i++) {
|
|
55
|
+
let letter = name[i];
|
|
56
|
+
kebabCase[i] = letter;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return kebabCase.reduce( ( a, b ) => {
|
|
60
|
+
if ( '_' === b ) {
|
|
61
|
+
return a.toLowerCase() + '-';
|
|
62
|
+
}
|
|
63
|
+
return a.toLowerCase() + b.toLowerCase();
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// TODO: Could be an array/iterator if the namespace can be extracted from the key, the larva.config API could
|
|
68
|
+
// change to `patterns: { larva: /larva/path/here/, project: /project/path/here }`
|
|
69
|
+
loader.addPath( patternConfig.larvaPatternsDir, 'larva' );
|
|
70
|
+
|
|
71
|
+
if( fs.existsSync( patternConfig.projectPatternsDir ) ) {
|
|
72
|
+
loader.addPath( patternConfig.projectPatternsDir, 'project' );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let twing = new TwingEnvironment( loader, { debug: true } );
|
|
76
|
+
|
|
77
|
+
twing.addFilter( markdownFilter );
|
|
78
|
+
twing.addFilter( markupFilter );
|
|
79
|
+
|
|
80
|
+
// Add custom function support for doing wp action: {{ wp_action( ... ) }}
|
|
81
|
+
twing.addFunction(new TwingFunction('wp_action',() => {
|
|
82
|
+
// We're relying on twig-to-php-parser for translation, so just return empty string for now
|
|
83
|
+
return Promise.resolve('');
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
let patterns = {
|
|
87
|
+
larva: getAllPatternsObj( patternConfig.larvaPatternsDir ),
|
|
88
|
+
project: getAllPatternsObj( patternConfig.projectPatternsDir )
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Use the project version if it exists, else use the larva version
|
|
92
|
+
if ( fs.existsSync( assetsConfig.path ) ) {
|
|
93
|
+
app.use( '/assets' , express.static( assetsConfig.path ) );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Expose any theme directories with assets in the express server
|
|
97
|
+
const themeAssetKeys = Object.keys( themeAssetsConfig );
|
|
98
|
+
|
|
99
|
+
themeAssetKeys.forEach( key => {
|
|
100
|
+
app.use( '/assets/theme/' + key , express.static( themeAssetsConfig[key] ) );
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
app.use( '/:source?/css', function (req, res) {
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generate Larva CSS Docs
|
|
107
|
+
*
|
|
108
|
+
* (Something similar can be done for project CSS unless we eradicate it)
|
|
109
|
+
*
|
|
110
|
+
* 1. Get all CSS from the larva-css npm package.
|
|
111
|
+
* 2. Use PostCSS to generate an abstract syntax tree.
|
|
112
|
+
* 3. Generate a "spec" for the CSS by getting the base selector names
|
|
113
|
+
* from Sass files in larva-scss
|
|
114
|
+
* 4. Walk the rules in the AST, checking the selectors against keys
|
|
115
|
+
* in the spec object, and adding them to an array of
|
|
116
|
+
* selectors for each property. Mark if it is in the hasTokens array.
|
|
117
|
+
* 5. Send that spec object to the template.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
const postcss = require( 'postcss' );
|
|
121
|
+
const cssPath = path.join( process.cwd(), './node_modules/@penskemediacorp/larva/build/css/larva.css' );
|
|
122
|
+
const sassPath = path.join( process.cwd(), './node_modules/@penskemediacorp/larva-css/src/' );
|
|
123
|
+
|
|
124
|
+
const hasTokens = [
|
|
125
|
+
'u-background-color',
|
|
126
|
+
'u-border-color',
|
|
127
|
+
'u-color',
|
|
128
|
+
'u-font-family',
|
|
129
|
+
'u-letter-spacing',
|
|
130
|
+
'u-margin',
|
|
131
|
+
'u-padding',
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const baseNames = ( () => {
|
|
135
|
+
|
|
136
|
+
let files = globby.sync( sassPath, {
|
|
137
|
+
expandDirectories: {
|
|
138
|
+
files: ['*.scss']
|
|
139
|
+
}
|
|
140
|
+
} );
|
|
141
|
+
|
|
142
|
+
return files.map( ( item ) => {
|
|
143
|
+
let parts = item.split( '/' );
|
|
144
|
+
let baseName = parts[ parts.length - 1 ].split( '.' );
|
|
145
|
+
return baseName[0];
|
|
146
|
+
} );
|
|
147
|
+
} )();
|
|
148
|
+
|
|
149
|
+
const cssString = fs.readFileSync( cssPath );
|
|
150
|
+
|
|
151
|
+
const cssRoot = postcss.parse( cssString )
|
|
152
|
+
|
|
153
|
+
const generatedSpec = ( () => {
|
|
154
|
+
let obj = {};
|
|
155
|
+
|
|
156
|
+
baseNames.forEach( ( item ) => {
|
|
157
|
+
obj[item] = {
|
|
158
|
+
selectors: [],
|
|
159
|
+
tokens: false
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
return obj;
|
|
164
|
+
} )();
|
|
165
|
+
|
|
166
|
+
cssRoot.walkRules( rule => {
|
|
167
|
+
|
|
168
|
+
Object.keys( generatedSpec ).forEach( key => {
|
|
169
|
+
let regex = new RegExp( '.*lrv-' + key + '.*', 'g' );
|
|
170
|
+
|
|
171
|
+
if ( -1 !== hasTokens.indexOf( key ) ) {
|
|
172
|
+
generatedSpec[key]['tokens'] = true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if ( rule.selector.match( regex ) ) {
|
|
176
|
+
generatedSpec[key]['selectors'].push( rule.selector );
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
} );
|
|
182
|
+
|
|
183
|
+
req.params[ 'name' ] = 'Larva CSS';
|
|
184
|
+
req.params[ 'spec' ] = generatedSpec;
|
|
185
|
+
|
|
186
|
+
req.params[ 'source' ] = 'larva';
|
|
187
|
+
req.params[ 'pattern_nav' ] = patterns;
|
|
188
|
+
|
|
189
|
+
twing.render( 'css.html', req.params ).then( output => res.end( output ) );
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
app.get( '/:source/:type/:name/:variant?', function (req, res) {
|
|
193
|
+
|
|
194
|
+
let patternsPath;
|
|
195
|
+
|
|
196
|
+
if ( 'larva' === req.params.source ) {
|
|
197
|
+
patternsPath = patternConfig.larvaPatternsDir;
|
|
198
|
+
} else if ( 'project' === req.params.source ) {
|
|
199
|
+
patternsPath = patternConfig.projectPatternsDir;
|
|
200
|
+
} else if ( 'assets' === req.params.source ) {
|
|
201
|
+
return res.end();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Support query parameters for conditionally loading stylesheets and scripts
|
|
205
|
+
req.params[ 'query' ] = req.query;
|
|
206
|
+
req.params[ 'pattern_nav' ] = patterns;
|
|
207
|
+
req.params[ 'data' ] = undefined !== patternsPath ? getPatternData( patternsPath, req.params ) : null;
|
|
208
|
+
req.params[ 'brand' ] = req.query.tokens ? req.query.tokens : brandConfig;
|
|
209
|
+
req.params[ 'variants' ] = patterns[req.params.source][req.params.type][req.params.name];
|
|
210
|
+
|
|
211
|
+
if ( 'algorithms' !== req.params.type ) {
|
|
212
|
+
req.params[ 'json_pretty' ] = JSON.stringify( req.params[ 'data' ], null, '\t' );
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
twing.render( 'pattern.html', req.params ).then( ( output ) => {
|
|
216
|
+
res.end( output );
|
|
217
|
+
}).catch( e => {
|
|
218
|
+
const errorMessage = `Cannot render template! \n\n${e}`;
|
|
219
|
+
|
|
220
|
+
console.log( e );
|
|
221
|
+
|
|
222
|
+
res.end( errorMessage );
|
|
223
|
+
} );
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
app.get( '/:source?/style-guide', function (req, res ) {
|
|
227
|
+
|
|
228
|
+
const brand = req.query.tokens ? req.query.tokens : brandConfig;
|
|
229
|
+
const tokensPath = path.join( assetsConfig.path, 'build/tokens' );
|
|
230
|
+
|
|
231
|
+
const tokensData = (() => {
|
|
232
|
+
try {
|
|
233
|
+
return require( path.join( tokensPath, `${brand}.json` ) );
|
|
234
|
+
} catch ( e ) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
})();
|
|
238
|
+
|
|
239
|
+
const colorsByProperty = ( () => {
|
|
240
|
+
if ( ! tokensData ) return;
|
|
241
|
+
|
|
242
|
+
const colorTokens = Object.keys( tokensData ).filter( item => item.includes( 'COLOR' ) );
|
|
243
|
+
const colorNames = colorTokens.map( token => kebabify( token ) );
|
|
244
|
+
|
|
245
|
+
return colorNames.reduce( (acc, curr) => {
|
|
246
|
+
Object.keys( acc ).forEach( key => {
|
|
247
|
+
if ( curr.startsWith( key ) ) {
|
|
248
|
+
acc[key].push( 'lrv-u-' + curr );
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
return acc;
|
|
253
|
+
}, {
|
|
254
|
+
color: [],
|
|
255
|
+
'background-color': [],
|
|
256
|
+
'border-color': []
|
|
257
|
+
});
|
|
258
|
+
})();
|
|
259
|
+
|
|
260
|
+
req.params[ 'name' ] = `Style Guide`;
|
|
261
|
+
req.params[ 'font_styles' ] = fontData.groupedSelectors;
|
|
262
|
+
req.params[ 'colors' ] = colorsByProperty;
|
|
263
|
+
req.params[ 'brand' ] = req.query.tokens ? req.query.tokens : brandConfig;
|
|
264
|
+
req.params[ 'pattern_nav' ] = patterns;
|
|
265
|
+
|
|
266
|
+
twing.render( 'style-guide/index.html', req.params ).then( output => res.end( output ) ).catch( e => {
|
|
267
|
+
const errorMessage = `Cannot render template! \n\n${e}`;
|
|
268
|
+
|
|
269
|
+
console.log( e );
|
|
270
|
+
|
|
271
|
+
res.end( errorMessage );
|
|
272
|
+
} );
|
|
273
|
+
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
app.get( '/:source?/:type?', function (req, res) {
|
|
277
|
+
req.params[ 'source' ] = 'larva';
|
|
278
|
+
req.params[ 'type' ] = req.params.type;
|
|
279
|
+
req.params[ 'pattern_nav' ] = patterns;
|
|
280
|
+
req.params[ 'brand' ] = req.query.tokens ? req.query.tokens : brandConfig;
|
|
281
|
+
twing.render( 'index.html', req.params ).then( output => res.end( output ) );
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
module.exports = app;
|
package/lib/start.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const path = require( 'path' );
|
|
2
|
+
const clonedeep = require( 'lodash.clonedeep' );
|
|
3
|
+
const getConfig = require( './getAppConfiguration' );
|
|
4
|
+
|
|
5
|
+
const { larvaPatternsDir, projectPatternsDir } = getConfig( 'patterns' );
|
|
6
|
+
|
|
7
|
+
module.exports = function clonePatternData( slug ) {
|
|
8
|
+
try {
|
|
9
|
+
return clonedeep( require( path.join( projectPatternsDir, slug ) ) );
|
|
10
|
+
} catch {
|
|
11
|
+
return clonedeep( require( path.join( larvaPatternsDir, slug ) ) );
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const path = require( 'path' );
|
|
2
|
+
const fs = require( 'fs-extra' );
|
|
3
|
+
const chalk = require( 'chalk' );
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* copySync Helper
|
|
7
|
+
*
|
|
8
|
+
* Wrap the fs.copySync funtion and provide useful logging.
|
|
9
|
+
* See {@link https://github.com/jprichardson/node-fs-extra/blob/master/docs/copy-sync.md fs.copySync}.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} src Path of directory or file to copy.
|
|
12
|
+
* @param {string} dest Path of destination for copied directory or file.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
module.exports = function copySyncHelper( src, dest ) {
|
|
17
|
+
|
|
18
|
+
const name = path.basename( src );
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
fs.copySync( src, dest );
|
|
22
|
+
|
|
23
|
+
console.log( `Copied '${name}'.` );
|
|
24
|
+
} catch ( e ) {
|
|
25
|
+
|
|
26
|
+
if ( 'ENOENT' === e.code ) {
|
|
27
|
+
console.log( chalk.grey( `Can't find '${name}' to copy, skipping.` ) );
|
|
28
|
+
} else {
|
|
29
|
+
console.error( e );
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const path = require( 'path' );
|
|
2
|
+
const getAppConfiguration = require( './getAppConfiguration' );
|
|
3
|
+
const getPatternVariants = require( './getPatternVariants' );
|
|
4
|
+
const getSubDirectoryNames = require( './getSubDirectoryNames' );
|
|
5
|
+
const getModuleNamesFromDirectory = require( './getModuleNamesFromDirectory' );
|
|
6
|
+
|
|
7
|
+
const config = getAppConfiguration( 'patterns' );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get All Patterns
|
|
11
|
+
*
|
|
12
|
+
* Given a directory contianing patterns in the Larva structure (components/object/modules/one-offs),
|
|
13
|
+
* return an object representing all the pattern types, patterns, and their variants.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} startPath - Path to look in for all patterns. Should be assets/src/patterns.
|
|
16
|
+
* @return {object} - Object representing all patterns and variants
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
module.exports = function getAllPatternsObj( startPath ) {
|
|
20
|
+
|
|
21
|
+
const patternDirs = getSubDirectoryNames( startPath );
|
|
22
|
+
|
|
23
|
+
let obj = {};
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
patternDirs.map( ( patternType ) => {
|
|
27
|
+
let patterns = [];
|
|
28
|
+
obj[patternType] = {};
|
|
29
|
+
|
|
30
|
+
// Modules can be ignored, which maybe is unecessary
|
|
31
|
+
// but for now continue on that path.
|
|
32
|
+
if ( 'modules' === patternType ) {
|
|
33
|
+
patterns = getModuleNamesFromDirectory( startPath, config.ignoredModules );
|
|
34
|
+
} else {
|
|
35
|
+
patterns = getSubDirectoryNames( path.join( startPath, patternType ) );
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
patterns.map( ( pattern ) => {
|
|
39
|
+
obj[patternType][pattern] = getPatternVariants( path.join( startPath, `${patternType}/${pattern}` ) );
|
|
40
|
+
} );
|
|
41
|
+
|
|
42
|
+
} );
|
|
43
|
+
} catch ( e ) {
|
|
44
|
+
console.error( e );
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return obj;
|
|
48
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const fs = require( 'fs' );
|
|
2
|
+
const path = require( 'path' );
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get Larva Configuration
|
|
6
|
+
*
|
|
7
|
+
* Find larva.config.js according to the current working directory.
|
|
8
|
+
* For consuming projects, this will be theme/assets/, and for the
|
|
9
|
+
* mono-repo, it will be packages/larva.
|
|
10
|
+
*
|
|
11
|
+
* For test env, the CWD is overridden to the local directory for fixtures.
|
|
12
|
+
* (this is a problem for writing project-level tests, but for a later time.)
|
|
13
|
+
*
|
|
14
|
+
* @param {string} key string that indicates a specific configuration property, e.g. patterns.
|
|
15
|
+
* @param {boolean} usePackageDefault fall back to package default if not defined in app
|
|
16
|
+
*
|
|
17
|
+
* @return value of the specified key.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const defaultConfig = {
|
|
21
|
+
|
|
22
|
+
eslint: {
|
|
23
|
+
configFile: path.join( __dirname, '../../scripts/config/.eslintrc.json' ),
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
webpack: {
|
|
27
|
+
aliases: {
|
|
28
|
+
'@js': path.resolve( './src/js' ),
|
|
29
|
+
'@npm': path.resolve( './node_modules' ),
|
|
30
|
+
'@larva-js': path.resolve( './node_modules/@penskemediacorp/larva-js/src' ),
|
|
31
|
+
},
|
|
32
|
+
entries: {
|
|
33
|
+
'larva-ui': path.resolve( './entries/larva-ui.entry.js' ),
|
|
34
|
+
common: path.resolve( './entries/common.entry.js' )
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
patterns: {
|
|
39
|
+
larvaPatternsDir: path.resolve( './node_modules/@penskemediacorp/larva-patterns' ),
|
|
40
|
+
projectPatternsDir: path.resolve( './src/patterns' ),
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
assets: {
|
|
44
|
+
path: ( () => {
|
|
45
|
+
|
|
46
|
+
// Fragile way to detect existing Larva sites
|
|
47
|
+
if ( fs.existsSync( path.resolve( './build/css' ) ) ) {
|
|
48
|
+
return path.resolve( './' );
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return path.resolve( './node_modules/@penskemediacorp/larva' );
|
|
52
|
+
})(),
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
themeAssets: {},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = function getAppConfiguration( key, usePackageDefault = true ) {
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
|
|
62
|
+
let appRoot = process.cwd();
|
|
63
|
+
|
|
64
|
+
if ( 'test' === process.env.NODE_ENV ) {
|
|
65
|
+
appRoot = path.join( __dirname, '../../__tests__/fixtures/' );
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let config = require( `${appRoot}/larva.config.js` );
|
|
69
|
+
|
|
70
|
+
// If config not found in approot, fallback to package default in root
|
|
71
|
+
if ( undefined === config[key] && usePackageDefault ) {
|
|
72
|
+
return defaultConfig[ key ];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return config[key];
|
|
76
|
+
|
|
77
|
+
} catch ( error ) {
|
|
78
|
+
console.warn( 'Using default configuration. ');
|
|
79
|
+
|
|
80
|
+
return defaultConfig[ key ];
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const getSubDirectoryNames = require( './getSubDirectoryNames' );
|
|
2
|
+
const path = require( 'path' );
|
|
3
|
+
|
|
4
|
+
module.exports = function getModuleNamesFromDirectory( directory, ignoredModules = [] ) {
|
|
5
|
+
let moduleNames = getSubDirectoryNames( path.join( directory , 'modules' ) );
|
|
6
|
+
|
|
7
|
+
return moduleNames.filter( ( moduleName ) => {
|
|
8
|
+
return ! moduleName.startsWith( '_' ) && -1 === ignoredModules.indexOf( moduleName );
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const chalk = require( 'chalk' );
|
|
2
|
+
const path = require( 'path' );
|
|
3
|
+
/**
|
|
4
|
+
* Get Pattern Data
|
|
5
|
+
*
|
|
6
|
+
* @param {string} patternsPath
|
|
7
|
+
* @param {object} params Object containing name of pattern
|
|
8
|
+
*/
|
|
9
|
+
function getPatternData( patternsPath, params ) {
|
|
10
|
+
|
|
11
|
+
const variant = params.variant || 'prototype';
|
|
12
|
+
const patternPath = path.join( patternsPath, params.type, params.name, params.name + '.' + variant + '.js' );
|
|
13
|
+
const jsonPath = path.join( patternsPath, params.type, params.name, params.name + '.json' )
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
return require( patternPath );
|
|
17
|
+
} catch( e ) {
|
|
18
|
+
const originalError = e;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Backwards compat for Deadline when patterns were stored as JSON
|
|
22
|
+
let patternData = require( jsonPath );
|
|
23
|
+
return patternData;
|
|
24
|
+
} catch ( e ) {
|
|
25
|
+
return {
|
|
26
|
+
message: `Error getting data for "${params.name}".<br>There is likely a problem with ${params.name}.${variant}.js.`,
|
|
27
|
+
error: originalError
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = getPatternData;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const fs = require( 'fs' );
|
|
2
|
+
|
|
3
|
+
module.exports = function getPatternPathsToLoad( config ) {
|
|
4
|
+
let paths = [];
|
|
5
|
+
|
|
6
|
+
if ( undefined === config ) {
|
|
7
|
+
throw new Error( `Pattern configuration is undefined.` );
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Look in projectPatternsDir first.
|
|
11
|
+
if( fs.existsSync( config.projectPatternsDir ) ) {
|
|
12
|
+
paths.push( config.projectPatternsDir );
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if( fs.existsSync( config.larvaPatternsDir ) ) {
|
|
16
|
+
paths.push( config.larvaPatternsDir );
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return paths;
|
|
20
|
+
}
|