diff --git a/package-lock.json b/package-lock.json index 43a659e3aa8..e0b559532fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4163,6 +4163,17 @@ "null-check": "1.0.0" } }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -6516,6 +6527,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, "jsonfilter": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", @@ -12209,6 +12229,12 @@ "crypto-random-string": "1.0.0" } }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index ce219d5c062..908b3193b06 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,10 @@ "license": "Apache-2.0", "scripts": { "build": "mkdirp build && webpack --progress --colors", + "build:demo": "cross-env MDC_ENV=development MDC_BUILD_STATIC_DEMO_ASSETS=true MDC_WRAP_CSS_IN_JS=false npm run build", "build:min": "mkdirp build && cross-env MDC_ENV=production webpack -p --progress --colors", "changelog": "standard-changelog -i CHANGELOG.md -k packages/material-components-web/package.json -w", - "clean": "del-cli build/**", + "clean": "del-cli build/** build", "commitmsg": "validate-commit-msg", "dist": "npm run clean && npm run build && npm run build:min", "dev": "npm run clean && cross-env MDC_ENV=development webpack-dev-server --progress --content-base demos --inline --hot --host 0.0.0.0", @@ -51,6 +52,7 @@ "eslint-config-google": "^0.8.1", "eslint-plugin-mocha": "^4.8.0", "extract-text-webpack-plugin": "^3.0.0", + "fs-extra": "^4.0.2", "glob": "^7.1.1", "google-closure-compiler": "^20170521.0.0", "husky": "^0.14.0", diff --git a/webpack.config.js b/webpack.config.js index 77e22af452b..dd01f884133 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,16 +16,20 @@ 'use strict'; +const os = require('os'); const path = require('path'); + +const fsx = require('fs-extra'); const glob = require('glob'); const webpack = require('webpack'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const OUT_PATH = path.resolve('./build'); -// Used with webpack-dev-server -const PUBLIC_PATH = '/assets/'; +const OUT_DIR_ABS = path.resolve('./build'); +const DEMO_ASSET_DIR_REL = '/assets/'; // Used by webpack-dev-server and MDC_BUILD_STATIC_DEMO_ASSETS + const IS_DEV = process.env.MDC_ENV === 'development'; const IS_PROD = process.env.MDC_ENV === 'production'; + const WRAP_CSS_IN_JS = process.env.MDC_WRAP_CSS_IN_JS !== 'false' && IS_DEV; // Source maps break extract-text-webpack-plugin, so they need to be disabled when WRAP_CSS_IN_JS is set to false. const GENERATE_SOURCE_MAPS = @@ -33,6 +37,7 @@ const GENERATE_SOURCE_MAPS = (process.env.MDC_GENERATE_SOURCE_MAPS !== 'false' && IS_DEV && WRAP_CSS_IN_JS); const DEVTOOL = GENERATE_SOURCE_MAPS ? 'source-map' : false; const GENERATE_DEMO_THEMES = process.env.MDC_GENERATE_DEMO_THEMES === 'true' && IS_DEV; +const BUILD_STATIC_DEMO_ASSETS = process.env.MDC_BUILD_STATIC_DEMO_ASSETS === 'true'; const banner = [ '/*!', @@ -92,12 +97,60 @@ const createCssLoaderConfig = () => const createCssExtractTextPlugin = () => new ExtractTextPlugin(CSS_FILENAME_OUTPUT_PATTERN); +class PostCompilePlugin { + constructor(fn) { + this.fn = fn; + } + + apply(compiler) { + compiler.plugin('done', (stats) => this.fn(stats)); + } +} + +const createStaticDemoPlugin = () => { + return new PostCompilePlugin(() => { + if (!BUILD_STATIC_DEMO_ASSETS || !fsx.existsSync(OUT_DIR_ABS)) { + return; + } + + const demosDirAbs = path.resolve('./demos'); + const tmpDirAbs = fsx.mkdtempSync(path.join(os.tmpdir(), 'mdc-web-demo-output-')); + + const copyOptions = { + filter: (src) => { + return !/\.(scss|css.js)$/.test(src); + }, + }; + + fsx.copySync(demosDirAbs, tmpDirAbs, copyOptions); + fsx.copySync(OUT_DIR_ABS, path.join(tmpDirAbs, DEMO_ASSET_DIR_REL), copyOptions); + + if (!WRAP_CSS_IN_JS) { + glob.sync(path.join(tmpDirAbs, '**/*.html')) + .forEach((absPath) => { + const oldHtml = fsx.readFileSync(absPath, {encoding: 'utf8'}); + const newHtml = oldHtml.replace( + /