diff --git a/.alexignore b/.alexignore new file mode 100644 index 000000000000..94c96d1f7837 --- /dev/null +++ b/.alexignore @@ -0,0 +1 @@ +generated/plugins/npm-install-webpack-plugin.md diff --git a/.alexrc b/.alexrc index 22e6d90c3208..d8c00c6511c9 100644 --- a/.alexrc +++ b/.alexrc @@ -1,20 +1,24 @@ { "allow": [ + "attacks", "bigger", "color", "colors", "crash", "dead", + "dirty", + "disabled", "dive", "execute", "executed", + "executes", "execution", - "dirty", - "disabled", "failed", "failure", + "failures", "fire", "hook", + "hooks", "host-hostess", "hosts", "jade", @@ -23,6 +27,7 @@ "period", "pros", "reject", + "remain", "remains", "white" ] diff --git a/.editorconfig b/.editorconfig index ef11db305ed6..2fe4cb4b7040 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,20 +1,18 @@ # Top-most EditorConfig file root = true -# Set default charset -[*.{js}] -charset = utf-8 - +# AutoFormat All Files [*] trim_trailing_whitespace = true insert_final_newline = true -# 4 space indentation -[*.{md,js,jsx,scss,hbs}] +# Format All Source Files +[*.{md,js,jsx,json,scss,hbs,*rc}] +charset = utf-8 indent_style = space indent_size = 2 -# Format Config -[{package.json,.alexrc,babelrc,.eslintignore,.eslintrc,.markdownlint.json,.proselintrc}] +# Format Any Missing Config Files +[.eslintignore] indent_style = space indent_size = 2 diff --git a/.postcssrc.js b/.postcssrc.js new file mode 100644 index 000000000000..88752c6cb06b --- /dev/null +++ b/.postcssrc.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + require('autoprefixer') + ] +} diff --git a/bootstrap.js b/antwar.bootstrap.js similarity index 75% rename from bootstrap.js rename to antwar.bootstrap.js index 78788a1ec28b..7206af47fe7a 100644 --- a/bootstrap.js +++ b/antwar.bootstrap.js @@ -1,6 +1,6 @@ const antwar = require('antwar'); -const environment = process.env.npm_lifecycle_event || 'build'; +const environment = process.argv[2]; // Patch Babel env to make HMR switch work process.env.BABEL_ENV = environment; @@ -9,7 +9,7 @@ antwar[environment]({ environment, antwar: require('./antwar.config'), webpack: require('./webpack.config') -}).catch(function (err) { +}).catch((err) => { console.error(err); process.exit(1); diff --git a/antwar.config.js b/antwar.config.js index 38257ba7b14c..50f3b3294116 100644 --- a/antwar.config.js +++ b/antwar.config.js @@ -1,44 +1,29 @@ -var _ = require('lodash'); -var path = require('path'); -var prevnextPlugin = require('antwar-prevnext-plugin'); -var markdown = require('./src/utilities/markdown'); -var highlight = require('./src/utilities/highlight'); +const path = require('path'); +const _ = require('lodash'); +const combineContexts = require('./src/utilities/combine-contexts'); module.exports = { + maximumWorkers: process.env.TRAVIS && 1, template: { - title: 'webpack', - description: 'webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.', file: path.join(__dirname, 'template.ejs') }, output: 'build', title: 'webpack', keywords: ['webpack', 'javascript', 'web development', 'programming'], - pageTitle: function(config, pageTitle) { - var siteName = config.name; - - if (pageTitle === 'index') { - return siteName; - } - - return siteName + ' - ' + pageTitle; - }, - plugins: [ - prevnextPlugin() - ], - layout: function() { - return require('./src/components/Site/Site.jsx').default - }, + layout: () => require('./src/components/Site/Site.jsx').default, paths: { - '/': root( - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content', - false, - /^\.\/.*\.md$/ - ); - } - ), - + '/': { + title: "Home", + content: () => require.context('./loaders/page-loader!./src/content', false, /^\.\/.*\.md$/), + index: () => { + const index = require('./src/components/Splash/Splash.jsx').default; + index.title = 'webpack'; + index.description = 'webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.'; + + return index; + }, + layout: () => require('./src/components/Page/Page.jsx').default, + }, 'get-started': { redirects: { '': '/guides/getting-started', @@ -46,244 +31,137 @@ module.exports = { 'why-webpack': '/guides/why-webpack', } }, - - concepts: section( - 'Concepts', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/concepts', - false, - /^\.\/.*\.md$/ - ); - } - ), - - guides: section( - 'Guides', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/guides', - true, - /^\.\/.*\.md$/ - ); - }, { - 'code-splitting-import': '/guides/code-splitting', - 'code-splitting-require': '/guides/code-splitting', - 'code-splitting-async': '/guides/code-splitting', - 'code-splitting-css': '/guides/code-splitting', - 'code-splitting-libraries': '/guides/code-splitting', - 'why-webpack': '/guides/comparison', - 'production-build': '/guides/production' - } - ), - - 'guides/starter-kits': { - title: 'Starter Kits', - path() { - return require('./src/components/StarterKits/StarterKits.jsx').default; + api: { + title: "API", + layout: () => require('./src/components/Page/Page.jsx').default, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + content: () => require.context('./loaders/page-loader!./src/content/api', false, /^\.\/.*\.md$/), + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) + }, + redirects: { + 'passing-a-config': 'configuration-types' } }, - - development: section( - 'Development', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/development', - true, - /^\.\/.*\.md$/ - ); - } - ), - - configuration: section( - 'Configuration', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/configuration', - false, - /^\.\/.*\.md$/ - ); - }, { - 'external-configs': 'javascript-alternatives' - } - ), - - api: section( - 'API', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/api', - false, - /^\.\/.*\.md$/ - ); - }, { + 'api/plugins': { + title: "API Plugins", + layout: () => require('./src/components/Page/Page.jsx').default, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + content: () => require.context('./loaders/page-loader!./src/content/api/plugins', false, /^\.\/.*\.md$/), + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) + }, + redirects: { 'passing-a-config': 'configuration-types' } - ), - - 'api/plugins': section( - 'API', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/api/plugins', - false, - /^\.\/.*\.md$/ - ); - } - ), - + }, pluginsapi: { + title: 'API Plugin', redirects: { '': '/api/plugins', 'compiler': '/api/plugins/compiler', 'template': '/api/plugins/template' - } + }, + hideInSidebar: true }, - - loaders: section( - 'Loaders', - function() { - const content = require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/loaders', - false, - /^\.\/.*\.md$/ - ); - const generated = require.context( - 'json-loader!yaml-frontmatter-loader!./generated/loaders', - false, - /^\.\/.*\.md$/ - ); - return combineContexts(content, generated); - } - ), - - plugins: section( - 'Plugins', - function() { - const content = require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/plugins', - false, - /^\.\/.*\.md$/ - ); - const generated = require.context( - 'json-loader!yaml-frontmatter-loader!./generated/plugins', - false, - /^\.\/.*\.md$/ - ); - return combineContexts(content, generated); - } - ), - - support: section( - 'Support', - function() { - return require.context( - 'json-loader!yaml-frontmatter-loader!./src/content/support', - false, - /^\.\/.*\.md$/ - ); - } - ), - - vote: { - path() { - return require('./src/components/Vote/List.jsx').default + concepts: { + title: "Concepts", + layout: () => require('./src/components/Page/Page.jsx').default, + content: () => require.context('./loaders/page-loader!./src/content/concepts', false, /^\.\/.*\.md$/), + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) } }, - - 'vote/feedback': { - path() { - return require('./src/components/Vote/List.jsx').default + development: { + title: "Development", + layout: () => require('./src/components/Page/Page.jsx').default, + content: () => require.context('./loaders/page-loader!./src/content/development', false, /^\.\/.*\.md$/), + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) } }, - - 'vote/moneyDistribution': { - path() { - return require('./src/components/Vote/List.jsx').default - } + plugins: { + title: "Plugin", + content: () => { + return combineContexts( + require.context('./loaders/page-loader!./src/content/plugins', false, /^\.\/.*\.md$/), + require.context('./loaders/page-loader!./generated/plugins', false, /^\.\/.*\.md$/) + ); + }, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) + }, + layout: () => require('./src/components/Page/Page.jsx').default }, - - organization: { - path() { - return require('./src/components/Organization/Organization.jsx').default - } - } - } -}; - -function root(contentCb) { - return { - title: 'webpack', - path: function() { // Load path content - return contentCb(); + loaders: { + title: "Loaders", + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + layout: () => require('./src/components/Page/Page.jsx').default, + content: () => { + return combineContexts( + require.context('./loaders/page-loader!./src/content/loaders', false, /^\.\/.*\.md$/), + require.context('./loaders/page-loader!./generated/loaders', false, /^\.\/.*\.md$/) + ); + }, }, - processPage: processPage(), // Process individual page (url, content) - layouts: { // Layouts (page/section) - index: function() { - return require('./src/components/Splash/Splash.jsx').default + guides: { + title: "Guides", + layout: () => require('./src/components/Page/Page.jsx').default, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + content: () => require.context('./loaders/page-loader!./src/content/guides', false, /^\.\/.*\.md$/), + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) }, - page: function() { - return require('./src/components/Page/Page.jsx').default + redirects: { + 'code-splitting-import': '/guides/code-splitting', + 'code-splitting-require': '/guides/code-splitting', + 'code-splitting-async': '/guides/code-splitting', + 'code-splitting-css': '/guides/code-splitting', + 'code-splitting-libraries': '/guides/code-splitting', + 'why-webpack': '/comparison', + 'production-build': '/guides/production' } }, - redirects: {} // Redirects : - }; -} - -function section(title, contentCb, redirects = {}) { - return { - title: title, - path: function() { - return contentCb(); - }, - sort(pages) { - return _.sortBy(pages, (page) => page.file.sort) + configuration: { + title: "Configuration", + layout: () => require('./src/components/Page/Page.jsx').default, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + content: () => require.context('./loaders/page-loader!./src/content/configuration', false, /^\.\/.*\.md$/), + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) + } }, - processPage: processPage(), - layouts: { - index: function() { - return require('./src/components/Page/Page.jsx').default - }, - page: function() { - return require('./src/components/Page/Page.jsx').default + support: { + title: "Support", + layout: () => require('./src/components/Page/Page.jsx').default, + url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, + content: () => require.context('./loaders/page-loader!./src/content/support', false, /^\.\/.*\.md$/), + transform: (pages) => { + return _.sortBy(pages, (page) => page.file.sort) } }, - redirects: redirects // : - }; -} + vote: () => { + const page = require('./src/components/Vote/List.jsx').default; + page.title = 'Vote'; -function processPage() { - return { - url: function(o) { - return o.sectionName + '/' + o.fileName.split('.')[0] - }, - content: function(o) { - return markdown().process(o.file.__content, highlight); - }, - anchors: function(o) { - return markdown().getAnchors(o.file.__content); + return page; }, - contributors: function(o) { - return Array.isArray(o.file.contributors) && o.file.contributors.length && o.file.contributors.slice().sort(); + organization: () => { + const page = require('./src/components/Organization/Organization.jsx').default; + + page.title = 'Organization'; + + return page; }, - related: function(o) { - return Array.isArray(o.file.related) ? o.file.related : [] - } - }; -} + 'guides/starter-kits': () => { + const page = require('./src/components/StarterKits/StarterKits.jsx').default; -function combineContexts(context1, context2) { - function webpackContext(req) { - try { - return context1(req); - } catch (e) { - return context2(req); + page.title = 'Starter kits'; + + return page; } } - webpackContext.keys = () => { - let keys1 = context1.keys(); - let keys2 = context2.keys(); - return _.chain(keys1).concat(keys2).sortBy().uniq().value(); - }; - return webpackContext; -} +}; diff --git a/loaders/page-loader.js b/loaders/page-loader.js new file mode 100644 index 000000000000..69361f2e3955 --- /dev/null +++ b/loaders/page-loader.js @@ -0,0 +1,30 @@ +const _ = require('lodash'); +const frontmatter = require('front-matter'); +const loaderUtils = require('loader-utils'); +const markdown = require('../src/utilities/markdown'); +const highlight = require('../src/utilities/highlight'); + +module.exports = function (source) { + const result = frontmatter(source); + + result.attributes = result.attributes || {}; + result.attributes.anchors = markdown().getAnchors(result.body); + result.attributes.contributors = (result.attributes.contributors || []).sort(); + result.attributes.related = Array.isArray(result.attributes.related) ? result.attributes.related : []; + result.title = result.attributes.title || 'webpack'; + result.body = markdown().process(result.body, highlight); + + delete result.frontmatter; + + const context = this; + + return `module.exports = ${JSON.stringify(result)};`.replace( + /__IMG_START__([^,\]]+)__IMG_END__/g, (match, src) => { + if (_.startsWith(src, 'http')) { + return src; + } + + return `" + require(${loaderUtils.stringifyRequest(context, src)}) + "`; + } + ); +}; diff --git a/package.json b/package.json index 174ce267eb6c..b1ffe261ad3a 100644 --- a/package.json +++ b/package.json @@ -24,87 +24,90 @@ "node": ">=6.9" }, "scripts": { - "start": "npm run init:generated && npm run fetch && node ./bootstrap.js", - "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./bootstrap.js && npm run sitemap && echo webpack.js.org > build/CNAME", + "start": "npm run init:generated && npm run fetch && node ./antwar.bootstrap.js develop", + "start-only": "node ./antwar.bootstrap.js develop", + "build": "npm run init:generated && npm run fetch && rm -rf build/ && node ./antwar.bootstrap.js build && npm run sitemap && echo webpack.js.org > build/CNAME", "build-test": "npm run build && http-server build/", "deploy": "gh-pages -d build", - "fetch": "bash src/scripts/fetch.sh", + "fetch": "sh src/scripts/fetch.sh", "init:generated": "mkdirp ./generated/loaders && mkdirp ./generated/plugins ", "lint": "run-s lint:*", "lint:links": "hyperlink -r build/index.html --canonicalroot https://webpack.js.org/ | node ./src/scripts/check-links.js", "lint:js": "eslint . --ext .js --ext .jsx", "lint:markdown": "markdownlint --config ./.markdownlint.json *.md ./src/content/**/*.md", - "lint:social": "alex ./**/*.md", + "lint:social": "alex . -q", "lint:prose": "cp .proselintrc ~/ && proselint src/content", "test": "npm run lint", "sitemap": "cd build && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml" }, "devDependencies": { - "alex": "^3.1.0", - "antwar": "0.8.1-alpha.078b5fbf", - "antwar-helpers": "0.8.1-alpha.078b5fbf", - "antwar-interactive": "0.8.1-alpha.078b5fbf", - "antwar-prevnext-plugin": "0.8.1-alpha.078b5fbf", - "async": "^2.1.2", - "autoprefixer": "^6.3.7", - "babel-core": "^6.10.4", - "babel-eslint": "^6.1.2", - "babel-loader": "^6.2.5", + "alex": "^4.1.0", + "antwar": "^0.19.0", + "antwar-helpers": "^0.19.0", + "antwar-interactive": "^0.19.0", + "async": "^2.5.0", + "autoprefixer": "^7.1.3", + "babel-core": "^6.26.0", + "babel-eslint": "^7.2.3", + "babel-loader": "^7.1.2", "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.16.0", - "babel-preset-env": "^0.0.8", - "babel-preset-react": "^6.11.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-preset-env": "^1.6.0", + "babel-preset-react": "^6.24.1", "copy-webpack-plugin": "^4.0.1", - "css-loader": "^0.25.0", + "css-loader": "^0.28.5", "duplexer": "^0.1.1", - "eslint": "3.6.0", - "eslint-loader": "^1.5.0", - "eslint-plugin-markdown": "^1.0.0-beta.2", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.9.0", + "eslint": "4.5.0", + "eslint-loader": "^1.9.0", + "eslint-plugin-markdown": "^1.0.0-beta.6", + "extract-text-webpack-plugin": "^3.0.0", + "file-loader": "^0.11.2", "fontgen-loader": "^0.2.1", - "gh-pages": "^0.12.0", - "github": "^5.2.3", - "html-webpack-plugin": "^2.22.0", - "http-server": "^0.9.0", + "front-matter": "^2.2.0", + "gh-pages": "^1.0.0", + "github": "^10.0.0", + "html-webpack-plugin": "^2.30.1", + "http-server": "^0.10.0", "hyperlink": "^3.0.0", - "json-loader": "^0.5.4", - "lodash": "^4.16.1", - "markdown-loader": "^0.1.7", - "markdownlint": "^0.2.0", - "markdownlint-cli": "^0.2.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.4", + "markdown-loader": "^2.0.1", + "markdownlint": "^0.6.0", + "markdownlint-cli": "^0.3.1", "marked": "^0.3.6", "mkdirp": "^0.5.1", - "modularscale-sass": "^2.1.1", - "moment": "^2.15.1", + "modularscale-sass": "^3.0.3", + "moment": "^2.18.1", "ncp": "^2.0.0", - "node-sass": "^3.9.3", - "npm-run-all": "^3.1.0", - "postcss-loader": "^0.13.0", - "prism-languages": "^0.3.1", - "prismjs": "^1.5.1", + "node-sass": "^4.5.3", + "npm-run-all": "^4.1.1", + "postcss-loader": "^2.0.6", + "prism-languages": "^0.3.3", + "prismjs": "^1.6.0", "raw-loader": "^0.5.1", - "request": "^2.75.0", - "sass-loader": "^4.0.2", - "sitemap-static": "^0.3.1", - "style-loader": "^0.13.1", - "tap-min": "^1.1.0", - "tap-parser": "^5.3.3", + "request": "^2.81.0", + "sass-loader": "^6.0.6", + "sitemap-static": "^0.4.2", + "style-loader": "^0.18.2", + "tap-min": "^1.2.1", + "tap-parser": "^6.0.1", "through2": "^2.0.3", - "url-loader": "^0.5.7", - "webpack": "^1.13.2", - "webpack-dev-server": "^1.16.1", - "webpack-merge": "^0.14.1", - "yaml-frontmatter-loader": "0.0.3" + "url-loader": "^0.5.9", + "webpack": "^3.5.5", + "webpack-dev-server": "^2.7.1", + "webpack-merge": "^4.1.0", + "yaml-frontmatter-loader": "^0.1.0" }, "dependencies": { - "preact": "^6.2.1", - "preact-compat": "3.11.0", - "prop-types": "^15.5.8", - "react": "^15.3.2", - "react-dom": "^15.3.2", - "react-router": "^2.8.1", - "tool-list": "^0.9.1", - "whatwg-fetch": "^2.0.1" + "ajv": "^5.2.2", + "preact": "^8.2.5", + "preact-compat": "3.17.0", + "prop-types": "^15.5.10", + "react": "^15.6.1", + "react-dom": "^15.6.1", + "react-router": "^4.2.0", + "react-router-dom": "^4.2.2", + "tool-list": "^0.11.0", + "whatwg-fetch": "^2.0.3" } } diff --git a/src/components/Cube/Cube.jsx b/src/components/Cube/Cube.jsx index 0b3d97b88002..d80084ed565d 100644 --- a/src/components/Cube/Cube.jsx +++ b/src/components/Cube/Cube.jsx @@ -1,20 +1,26 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; export default class Cube extends React.Component { - constructor(props) { - super(props); - - this.listeners = { - spin: this._spin.bind(this), - reset: this._reset.bind(this) - }; - - this.state = { - x: 0, - y: 0, - z: 0, - iteration: 0, - }; + static propTypes = { + hover: PropTypes.bool, + theme: PropTypes.string, + depth: PropTypes.number, + repeatDelay: PropTypes.number + }; + + static defaultProps = { + hover: false, + theme: 'dark', + depth: 30, + repeatDelay: 1000, + }; + + state = { + x: 0, + y: 0, + z: 0, + iteration: 0, } render() { @@ -71,8 +77,8 @@ export default class Cube extends React.Component { let { hover, continuous, repeatDelay } = this.props; if (hover) { - this.container.addEventListener('mouseenter', this.listeners.spin); - this.container.addEventListener('mouseleave', this.listeners.reset); + this.container.addEventListener('mouseenter', this._spin); + this.container.addEventListener('mouseleave', this._reset); } else if (continuous) { let degrees = 0; @@ -101,8 +107,8 @@ export default class Cube extends React.Component { let { hover, continuous } = this.props; if (hover) { - this.container.removeEventListener('mouseenter', this.listeners.spin); - this.container.removeEventListener('mouseleave', this.listeners.reset); + this.container.removeEventListener('mouseenter', this._spin); + this.container.removeEventListener('mouseleave', this._reset); } else if (continuous) { cancelAnimationFrame(this._requestAnimation); @@ -175,8 +181,8 @@ export default class Cube extends React.Component { } : {}; return ( -
{ let obj = {}; let axis = this._getRandomAxis(); let sign = Math.random() < 0.5 ? -1 : 1; @@ -217,7 +223,7 @@ export default class Cube extends React.Component { * * @param {object} e - Native event */ - _reset(e) { + _reset = e => { this.setState({ x: 0, y: 0, @@ -225,17 +231,3 @@ export default class Cube extends React.Component { }); } } - -Cube.propTypes = { - hover: PropTypes.bool, - theme: PropTypes.string, - depth: PropTypes.number, - repeatDelay: PropTypes.number -}; - -Cube.defaultProps = { - hover: false, - theme: 'dark', - depth: 30, - repeatDelay: 1000, -}; diff --git a/src/components/Footer/Footer.jsx b/src/components/Footer/Footer.jsx index 344058dbd79b..29f57c5fad52 100644 --- a/src/components/Footer/Footer.jsx +++ b/src/components/Footer/Footer.jsx @@ -6,38 +6,38 @@ import CC from '../../assets/cc.svg'; import BY from '../../assets/by.svg'; import './Footer.scss'; -export default (props) => { - return ( -
- -
- Getting Started - Organization - Support - Comparison -
+const Footer = () => ( +
+ +
+ Get Started + Organization + Support + Comparison +
-
- - webpack icon - -
+
+ + webpack icon + +
-
- Glossary - Branding - Gitter - Changelog - - Creative Commons License - Creative Commons License - -
-
-
- ); -}; +
+ Glossary + Branding + Gitter + Changelog + + Creative Commons License + Creative Commons License + +
+
+
+); + +export default Footer; diff --git a/src/components/Gitter/Gitter.jsx b/src/components/Gitter/Gitter.jsx index d380c3bf3014..9d1f380a44e8 100644 --- a/src/components/Gitter/Gitter.jsx +++ b/src/components/Gitter/Gitter.jsx @@ -1,21 +1,17 @@ import React from 'react'; export default class Gitter extends React.Component { - constructor(props) { - super(props); - - this.state = { - offset: 0 - }; - } + state = { + offset: 0 + }; render() { let { offset } = this.state; return ( -
@@ -32,14 +28,14 @@ export default class Gitter extends React.Component { ); document.addEventListener( - 'scroll', + 'scroll', this._recalculate.bind(this) ); } componentWillUnmount() { document.removeEventListener( - 'scroll', + 'scroll', this._recalculate.bind(this) ); } @@ -54,4 +50,4 @@ export default class Gitter extends React.Component { offset: distToBottom < footerHeight ? footerHeight - distToBottom : 0 }); } -} \ No newline at end of file +} diff --git a/src/components/Link/Link.jsx b/src/components/Link/Link.jsx index ef1932898b6b..d8da984a258c 100644 --- a/src/components/Link/Link.jsx +++ b/src/components/Link/Link.jsx @@ -3,7 +3,7 @@ import startsWith from 'lodash/startsWith'; let RRouter; if (__DEV__) { - RRouter = require('react-router'); + RRouter = require('react-router-dom'); } export default ({ to, ...props }) => { diff --git a/src/components/Navigation/Navigation.jsx b/src/components/Navigation/Navigation.jsx index a100f56f0370..169cf9945237 100644 --- a/src/components/Navigation/Navigation.jsx +++ b/src/components/Navigation/Navigation.jsx @@ -66,7 +66,7 @@ export default class Navigation extends React.Component { + to={ `/${section.url}/` }> { section.title } ); @@ -123,7 +123,7 @@ export default class Navigation extends React.Component { + to={ `/${child.url}/` }> { child.title } ); @@ -171,9 +171,9 @@ export default class Navigation extends React.Component { let { pageUrl = '' } = this.props; if (section.children) { - return section.children.some(child => pageUrl.includes(`${child.url}/`)); + return section.children.some(child => { return (new RegExp("^/" + child.url +".*/")).test(pageUrl); }); - } else return pageUrl.includes(`${section.url}/`); + } else return (new RegExp("^/" + section.url +".*/")).test(pageUrl); } /** diff --git a/src/components/Page/Page.jsx b/src/components/Page/Page.jsx index 3acd5ba592a0..a9e1da62cfa2 100644 --- a/src/components/Page/Page.jsx +++ b/src/components/Page/Page.jsx @@ -11,62 +11,80 @@ import '../Sidebar/Sidebar.scss'; import '../Sponsors/Sponsors.scss'; import '../Gitter/Gitter.scss'; -export default ({ section, page }) => ( - +const Page = ({ page, section }) => { + let { contributors, title, related } = page.file.attributes; + let indexPage = section.title !== 'Home' ? require(`page-loader!../../content/${section.name}/index.md`) : null; + let pages = ( + section.pages() + .sort((a, b) => a.file.attributes.sort - b.file.attributes.sort) + .map(page => ({ + url: page.url, + title: page.file.attributes.title, + anchors: page.file.attributes.anchors + })) + ); - + // TODO: This hack adds the index page to the array + // Ideally this would be resolved at the antwar/build level + // Index pages should just be treated normally + if (indexPage) { + pages.unshift({ + url: `/${section.name}/`, + title: indexPage.attributes.title, + anchors: indexPage.attributes.anchors + }); + } - ({ - url: page.url, - title: page.title, - anchors: page.anchors - })) } - currentPage={ page.url.replace('/index', '') } /> + return ( + + + -
-

{ page.title }

+
+

{ title }

- + -
+
- { page.related.length > 0 ? ( -
-
-

Further Reading

- -
- ) : null } + { related.length > 0 && ( +
+
+

Further Reading

+ +
+ )} - { page.contributors.length > 0 ? ( -
-
-

Contributors

- -
- ) : null } + { contributors.length > 0 && ( +
+
+

Contributors

+ +
+ )} - -
- -); + +
+
+ ); +}; + +export default Page; diff --git a/src/components/PageLinks/PageLinks.jsx b/src/components/PageLinks/PageLinks.jsx index 8814a5093109..6e3a8cd300c9 100644 --- a/src/components/PageLinks/PageLinks.jsx +++ b/src/components/PageLinks/PageLinks.jsx @@ -9,13 +9,13 @@ export default ({ let baseURL = 'https://github.com/webpack/webpack.js.org/edit/master/src/content'; let indexPath = page.type === 'index' ? '/index' : ''; let mainPath = page.url.startsWith('/') ? page.url : `/${page.url}`; - let editLink = page.edit || baseURL + TrimEnd(mainPath, '/') + indexPath + '.md'; + let editLink = page.file.attributes.edit || baseURL + TrimEnd(mainPath, '/') + indexPath + '.md'; return (
- { page.repo ? ( + { page.file.attributes.repo ? ( - + Jump to Repository diff --git a/src/components/Sidebar/Sidebar.jsx b/src/components/Sidebar/Sidebar.jsx index 69eb1f857f68..974b7d358a8e 100644 --- a/src/components/Sidebar/Sidebar.jsx +++ b/src/components/Sidebar/Sidebar.jsx @@ -3,20 +3,15 @@ import Shield from '../Shield/Shield'; import SidebarItem from '../SidebarItem/SidebarItem'; export default class Sidebar extends Component { - constructor(props) { - super(props); - - this.state = { - fixed: false, - availableHeight: null, - maxWidth: null - }; - } + state = { + fixed: false, + availableHeight: null, + maxWidth: null + }; render() { - let { sectionName, pages, currentPage } = this.props; + let { pages, currentPage } = this.props; let { fixed, availableHeight, maxWidth } = this.state; - let isGuides = sectionName === 'guides'; return (