diff --git a/.alexignore b/.alexignore index 90471bcb2796..a925fe2d06d9 100644 --- a/.alexignore +++ b/.alexignore @@ -1 +1,2 @@ -generated/plugins/* +src/content/plugins/_*.md +src/content/loaders/_*.md diff --git a/.babelrc b/.babelrc index a0b12e107425..9484ab7f7de2 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,18 @@ { "presets": [ - "env", + ["env", { "modules": false }], "react" ], "plugins": [ + "syntax-dynamic-import", "transform-object-rest-spread", "transform-class-properties" - ] + ], + "env": { + "development": { + "plugins": [ + "react-hot-loader/babel" + ] + } + } } diff --git a/.editorconfig b/.editorconfig index 2fe4cb4b7040..53a646e2741c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,13 +6,14 @@ root = true trim_trailing_whitespace = true insert_final_newline = true -# Format All Source Files -[*.{md,js,jsx,json,scss,hbs,*rc}] +# Format Source Code +[*.{md,js,jsx,json,scss,hbs}] charset = utf-8 indent_style = space indent_size = 2 +quote_type = single -# Format Any Missing Config Files -[.eslintignore] +# Format Configs +[.eslintignore,*rc] indent_style = space indent_size = 2 diff --git a/.eslintignore b/.eslintignore index b70ad30f2d8f..4915141af784 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,3 @@ -build/ -generated/ -antwar.config.js +dist/ +src/content/loaders/_*.md +src/content/plugins/_*.md diff --git a/.eslintrc b/.eslintrc index 0caf816e7320..ef030ea137d7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,24 +1,18 @@ { "root": true, - "extends": "eslint:recommended", - "parser": "babel-eslint", - "env": { "browser": true, "es6": true, "node": true }, - "plugins": [ "markdown" ], - "globals": { "__DEV__": true }, - "rules": { "no-undef": 2, "no-unreachable": 2, @@ -26,7 +20,6 @@ "no-console": 0, "semi": ["error", "always"] }, - "overrides": [ { "files": ["src/content/**/*.md"], diff --git a/.gitignore b/.gitignore index cbdc7c1002d9..b511fac6ff2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,11 @@ node_modules -npm-debug.log -build -generated -support-*.json -starter-kits-data.json -.antwar +dist +src/**/_*.json +src/**/_*.md .vscode .idea .DS_Store +npm-debug.log yarn-error.log package-lock.json +.cache diff --git a/.travis.yml b/.travis.yml index 7770208100be..f106a112ed9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,55 @@ -branches: - only: - - master - - develop +sudo: false language: node_js node_js: - "8" -sudo: required -install: - - yarn - - sudo pip install proselint -before_script: - - source ./src/scripts/env.sh -script: - - bash ./src/scripts/deploy.sh + +matrix: + fast_finish: true + +cache: + yarn: true + directories: + - node_modules + - dist + - .cache + +stages: + - Build + - Post-build + +jobs: + fast_finish: true + allow_failures: + - name: External Link Check + + include: + - stage: Build + name: Lint and Build + before_install: npm install --global yarn + install: yarn + script: + - yarn lint:js || travis_terminate 1 + - yarn lint:markdown || travis_terminate 1 + - yarn lint:social || travis_terminate 1 + - yarn build || travis_terminate 1 + - yarn lint:links || travis_terminate 1 + + - stage: Build + name: Proselint + language: python + python: 3.6 + cache: + pip: true + directories: + - $HOME/.cache + install: pip install -r requirements.txt + script: cp .proselintrc ~/ && proselint src/content + + - stage: Post-build + name: Deploy + if: branch = master AND type = push + script: bash ./src/scripts/deploy.sh + + - stage: Post-build + name: External Link Check + script: yarn linkcheck diff --git a/antwar.bootstrap.js b/antwar.bootstrap.js deleted file mode 100644 index aee2f118aaa8..000000000000 --- a/antwar.bootstrap.js +++ /dev/null @@ -1,22 +0,0 @@ -const antwar = require('antwar'); - -const environment = process.argv[2]; - -// Patch Babel env to make HMR switch work -process.env.BABEL_ENV = environment; - -antwar[environment]({ - environment, - configurationPaths: { - antwar: require.resolve("./antwar.config.js"), - webpack: require.resolve("./webpack.config.js"), - }, -}).then(() => { - if (environment !== "build") { - console.log("Surf to localhost:3000"); - } -}).catch((err) => { - console.error(err); - - process.exit(1); -}); diff --git a/antwar.config.js b/antwar.config.js deleted file mode 100644 index 5f0a69d82542..000000000000 --- a/antwar.config.js +++ /dev/null @@ -1,82 +0,0 @@ -const path = require('path'); -const combineContexts = require('./src/utilities/combine-contexts'); - -module.exports = () => ({ - maximumWorkers: process.env.TRAVIS && 1, - template: { - file: path.join(__dirname, 'template.ejs') - }, - output: 'build', - title: 'webpack', - keywords: ['webpack', 'javascript', 'web development', 'programming'], - layout: () => require('./src/components/Site/Site.jsx').default, - paths: { - '/': { - title: 'Home', - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content', false, /^\.\/.*\.md$/), - index: () => require('./src/components/Splash/Splash.jsx').default - }, - concepts: { - title: 'Concepts', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/concepts', false, /^\.\/.*\.md$/) - }, - configuration: { - title: 'Configuration', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/configuration', false, /^\.\/.*\.md$/) - }, - api: { - title: 'API', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/api', false, /^\.\/.*\.md$/) - }, - guides: { - title: 'Guides', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/guides', false, /^\.\/.*\.md$/) - }, - plugins: { - title: 'Plugins', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => { - return combineContexts( - require.context('./loaders/page-loader!./src/content/plugins', false, /^\.\/.*\.md$/), - require.context('./loaders/page-loader!./generated/plugins', false, /^\.\/.*\.md$/) - ); - } - }, - 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$/) - ); - } - }, - contribute: { - title: 'Contribute', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/contribute', false, /^\.\/.*\.md$/) - }, - migrate: { - title: 'Migrate', - url: ({ sectionName, fileName }) => `/${sectionName}/${fileName}/`, - layout: () => require('./src/components/Page/Page.jsx').default, - content: () => require.context('./loaders/page-loader!./src/content/migrate', false, /^\.\/.*\.md$/) - }, - vote: () => require('./src/components/Vote/Vote.jsx').default, - organization: () => require('./src/components/Organization/Organization.jsx').default, - 'starter-kits': () => require('./src/components/StarterKits/StarterKits.jsx').default - } -}); diff --git a/loaders/page-loader.js b/loaders/page-loader.js deleted file mode 100644 index 698bce4b2229..000000000000 --- a/loaders/page-loader.js +++ /dev/null @@ -1,31 +0,0 @@ -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.group = result.attributes.group || '-'; - 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 96f6834bb6f5..7dd08a9b38bc 100644 --- a/package.json +++ b/package.json @@ -21,23 +21,32 @@ "url": "https://github.com/webpack/webpack.js.org/issues" }, "engines": { - "node": ">=6.9" + "node": ">=8.9.4" }, "scripts": { - "start": "run-s -n init:generated fetch start-only", - "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", + "clean": "rimraf ./dist src/content/**/_*.md src/**/_*.json", + "start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.dev.js --env.dev", + "update-repos": "node src/utilities/fetch-package-repos.js", + "content": "node src/scripts/build-content-tree.js ./src/content ./src/_content.json", "build-test": "npm run build && http-server build/", - "deploy": "gh-pages -d build", - "fetch": "sh src/scripts/fetch.sh", - "init:generated": "mkdirp ./generated/loaders && mkdirp ./generated/plugins ", + "fetch": "run-p fetch:*", + "fetch:readmes": "node src/utilities/fetch-package-readmes.js", + "fetch:supporters": "node src/utilities/fetch-supporters.js", + "fetch:starter-kits": "node src/utilities/fetch-starter-kits.js", + "prebuild": "npm run clean", + "build": "run-s fetch content && cross-env NODE_ENV=production webpack --config webpack.prod.js", + "postbuild": "npm run sitemap", + "test": "npm run lint", "lint": "run-s lint:*", - "lint:js": "eslint . --ext .js,.jsx,.md", - "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json *.md ./src/content/*.md ./src/content/**/*.md", + "lint:js": "eslint src --ext .js,.jsx,.md --cache true --cache-location .cache/.eslintcache", + "lint:markdown": "markdownlint --rules markdownlint-rule-emphasis-style --config ./.markdownlint.json *.md ./src/content/**/*.md --ignore './src/content/**/_*.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" + "lint:links": "hyperlink -r dist/index.html --canonicalroot https://webpack.js.org/ -i --todo https://img.shields.io --todo https://codecov.io/gh --todo 'content-type-mismatch https://travis-ci.org' | tee internal-links.tap | tap-spot", + "linkcheck": "hyperlink -r dist/index.html --canonicalroot https://webpack.js.org/ --skip support__ --skip sidecar.gitter.im --skip vimdoc.sourceforge.net --skip img.shields.io --skip npmjs.com/package/ --skip opencollective.com/webpack --todo external-redirect | tee external-links.tap | tap-spot", + "sitemap": "cd dist && sitemap-static --prefix=https://webpack.js.org/ > sitemap.xml", + "serve": "npm run build && sirv start ./dist --port 4000", + "deploy": "gh-pages -d dist" }, "husky": { "hooks": { @@ -53,75 +62,95 @@ ] }, "devDependencies": { - "alex": "^4.1.0", - "antwar": "^0.28.3", - "antwar-helpers": "^0.28.0", - "antwar-interactive": "^0.28.0", - "async": "^2.5.0", + "@mdx-js/loader": "0.15.7", + "@mdx-js/mdx": "0.15.7", + "@octokit/rest": "^15.9.4", + "alex": "^5.1.0", "autoprefixer": "^7.2.3", "babel-core": "^6.26.0", "babel-eslint": "^7.2.3", "babel-loader": "^7.1.2", + "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.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.4.2", - "css-loader": "^0.28.10", + "copy-webpack-plugin": "4.5.2", + "cross-env": "5.2.0", + "css-loader": "^0.28.5", + "directory-tree": "2.2.0", + "directory-tree-webpack-plugin": "0.3", "duplexer": "^0.1.1", "eslint": "4.19.1", "eslint-loader": "^2.0.0", - "eslint-plugin-markdown": "^1.0.0-rc.0", + "eslint-plugin-markdown": "1.0.0-rc.0", + "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.11", "fontgen-loader": "git://github.com/EugeneHlushko/fontgen-loader.git#a26a73843900ca4b518853952b1fc3c816103512", - "front-matter": "^2.2.0", + "front-matter": "^2.3.0", "gh-pages": "^1.0.0", - "github": "^10.0.0", - "html-webpack-plugin": "^3.1.0", + "html-webpack-plugin": "^2.30.1", + "html-webpack-template": "^6.1.0", "http-server": "^0.10.0", "husky": "^1.0.0-rc.8", - "hyperlink": "^3.0.1", - "lint-staged": "^7.2.0", + "hyperlink": "^4.0.0", + "lint-staged": "^8.1.0", "loader-utils": "^1.1.0", "lodash": "^4.17.4", - "markdown-loader": "^2.0.1", + "markdown-loader": "^4.0.0", "markdownlint": "^0.11.0", "markdownlint-cli": "^0.13.0", "markdownlint-rule-emphasis-style": "^1.0.0", - "marked": "^0.3.7", - "mini-css-extract-plugin": "^0.2.0", + "marked": "^0.5.2", + "mermaid.cli": "^0.3.6", + "minimist": "1.2.0", "mkdirp": "^0.5.1", "modularscale-sass": "^3.0.3", - "moment": "^2.20.1", - "ncp": "^2.0.0", "node-sass": "^4.5.3", "npm-run-all": "^4.1.1", - "postcss-loader": "^2.1.3", - "prism-languages": "^0.3.3", - "prismjs": "^1.9.0", - "raw-loader": "^0.5.1", + "postcss-loader": "^2.0.6", "redirect-webpack-plugin": "^0.1.1", + "remark": "^10.0.1", + "remark-autolink-headings": "^5.0.0", + "remark-custom-blockquotes": "1.0.0", + "remark-extract-anchors": "1.0.0", + "remark-loader": "^0.3.0", + "remark-mermaid": "^0.2.0", + "remark-refractor": "1.1.0", + "remark-responsive-tables": "1.0.0", + "remark-slug": "^5.0.0", "request": "^2.81.0", + "request-promise": "^4.2.2", + "rimraf": "^2.6.2", "sass-loader": "^6.0.6", + "sirv-cli": "^0.1.2", "sitemap-static": "^0.4.2", - "tap-min": "^1.2.1", - "tap-parser": "^6.0.1", + "static-site-generator-webpack-plugin": "^3.4.1", + "style-loader": "^0.18.2", + "tap-spot": "^1.1.1", "through2": "^2.0.3", - "url-loader": "^0.5.9", - "webpack": "^4.2.0", - "webpack-dev-server": "^3.1.1", - "webpack-merge": "^4.1.0", - "yaml-frontmatter-loader": "^0.1.0" + "uglifyjs-webpack-plugin": "^1.1.6", + "webpack": "^3.10.0", + "webpack-dev-server": "^2.9.7", + "webpack-merge": "^4.1.0" }, "dependencies": { + "@rigor789/remark-autolink-headings": "^5.1.0", "ajv": "^5.5.2", + "docsearch.js": "^2.5.2", + "gitter-sidecar": "^1.2.3", "javascriptstuff-db": "^1.12.0", "lodash.throttle": "^4.1.1", "prop-types": "^15.5.10", - "react": "^15.6.1", - "react-dom": "^15.6.1", - "react-router": "^4.2.0", + "react": "^16.2.0", + "react-banner": "^1.0.0-rc.0", + "react-document-title": "^2.0.3", + "react-dom": "^16.2.0", + "react-g-analytics": "0.4.2", + "react-hot-loader": "^4.0.0-beta.12", + "react-markdown": "4.0.4", "react-router-dom": "^4.2.2", + "react-tiny-popover": "3.4.2", "webpack.vote": "^0.1.2", "whatwg-fetch": "^2.0.3" } diff --git a/repositories/README.md b/repositories/README.md new file mode 100644 index 000000000000..ef2e81f5f1cb --- /dev/null +++ b/repositories/README.md @@ -0,0 +1,3 @@ +# Webpack documentation repositories + +The files in this directory are auto generated from `src/utils/fetch-package-repos.js` and should not be edited by hand. Any manual changes will be overwritten by the automation next time it runs. diff --git a/repositories/loaders.json b/repositories/loaders.json new file mode 100644 index 000000000000..01af11ec9789 --- /dev/null +++ b/repositories/loaders.json @@ -0,0 +1,44 @@ +[ + "webpack-contrib/json-loader", + "webpack-contrib/raw-loader", + "webpack-contrib/coffee-loader", + "webpack-contrib/css-loader", + "webpack-contrib/style-loader", + "webpack-contrib/script-loader", + "webpack-contrib/less-loader", + "webpack-contrib/bundle-loader", + "webpack-contrib/val-loader", + "webpack-contrib/file-loader", + "webpack-contrib/url-loader", + "webpack-contrib/i18n-loader", + "webpack-contrib/json5-loader", + "webpack-contrib/worker-loader", + "webpack-contrib/jshint-loader", + "webpack-contrib/imports-loader", + "webpack-contrib/exports-loader", + "webpack-contrib/mocha-loader", + "webpack-contrib/coverjs-loader", + "webpack-contrib/expose-loader", + "webpack-contrib/node-loader", + "webpack-contrib/coffee-redux-loader", + "webpack-contrib/transform-loader", + "webpack-contrib/html-loader", + "webpack-contrib/sass-loader", + "webpack-contrib/source-map-loader", + "webpack-contrib/react-proxy-loader", + "webpack-contrib/null-loader", + "webpack-contrib/multi-loader", + "webpack-contrib/istanbul-instrumenter-loader", + "webpack-contrib/eslint-loader", + "webpack-contrib/yaml-frontmatter-loader", + "webpack-contrib/svg-inline-loader", + "webpack-contrib/restyle-loader", + "webpack-contrib/gzip-loader", + "webpack-contrib/cache-loader", + "webpack-contrib/thread-loader", + "webpack-contrib/polymer-webpack-loader", + "webpack-contrib/config-loader", + "babel/babel-loader", + "postcss/postcss-loader", + "peerigon/extract-loader" +] \ No newline at end of file diff --git a/repositories/plugins.json b/repositories/plugins.json new file mode 100644 index 000000000000..8c6674519a42 --- /dev/null +++ b/repositories/plugins.json @@ -0,0 +1,15 @@ +[ + "webpack-contrib/i18n-webpack-plugin", + "webpack-contrib/component-webpack-plugin", + "webpack-contrib/compression-webpack-plugin", + "webpack-contrib/extract-text-webpack-plugin", + "webpack-contrib/copy-webpack-plugin", + "webpack-contrib/npm-install-webpack-plugin", + "webpack-contrib/stylelint-webpack-plugin", + "webpack-contrib/babel-minify-webpack-plugin", + "webpack-contrib/uglifyjs-webpack-plugin", + "webpack-contrib/zopfli-webpack-plugin", + "webpack-contrib/closure-webpack-plugin", + "webpack-contrib/mini-css-extract-plugin", + "webpack-contrib/terser-webpack-plugin" +] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000000..6169a9005505 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +proselint diff --git a/CNAME b/src/CNAME similarity index 100% rename from CNAME rename to src/CNAME diff --git a/src/assets/awesome-badge.svg b/src/assets/awesome-badge.svg deleted file mode 100644 index 24c2bc6e5942..000000000000 --- a/src/assets/awesome-badge.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/Configuration/Configuration.jsx b/src/components/Configuration/Configuration.jsx new file mode 100644 index 000000000000..1200a1d5ba4d --- /dev/null +++ b/src/components/Configuration/Configuration.jsx @@ -0,0 +1,39 @@ +import React from "react"; +import ReactMarkdown from "react-markdown"; +import { Details } from "./components"; + +const detailComponentsList = ['link', 'mode', 'entry', 'filename', 'publicPath', 'advancedOutput', 'expert', 'advancedModule', 'alias', 'advancedResolve', 'hints', 'devtool', 'target', 'externals', 'stats', 'advanced', 'libraryTarget']; + +const Pre = props => { + const newChildren = React.Children.map(props.children.props.children, child => { + if (React.isValidElement(child)) { + if (child.props.props.className.includes("keyword")) { + if (!detailComponentsList.includes(child.props.props.componentname)) return child; + + return
; + } + + if (child.props.props.className.includes("comment")) { + return ; + } + } + + return child; + }); + + const newProps = { + children: newChildren + }; + + return ( +
+      
+    
+ ); +}; + +export default { + components: { + pre: Pre + } +}; diff --git a/src/components/Configuration/Configuration.scss b/src/components/Configuration/Configuration.scss new file mode 100644 index 000000000000..42a056dd1af2 --- /dev/null +++ b/src/components/Configuration/Configuration.scss @@ -0,0 +1,10 @@ +.shadow { + overflow: visible; + border-radius: 4px; + box-shadow: -1px 1px 10px 0 rgba(255, 255, 255, 0.44); +} + +.inline { + padding-right: 15px !important; + margin: 0 !important; +} diff --git a/src/components/Configuration/components.js b/src/components/Configuration/components.js new file mode 100644 index 000000000000..223a62499bcd --- /dev/null +++ b/src/components/Configuration/components.js @@ -0,0 +1,98 @@ +import React from 'react'; +import Popover from 'react-tiny-popover'; +import './Configuration.scss'; +import { timeout } from 'q'; + +const DEFAULT_CHILDREN_SIZE = 4; + +const isFirstChild = child => typeof child === 'string' && child !== ' '; + +const removeSpaces = child => (isFirstChild(child) ? child.trim() : child); + +const addLink = (child, i, url) => { + return isFirstChild(child) ? ( + + {child} + + ) : ( + child + ); +}; + +const Card = ({ body }) => { + return ( +
+
+        {body}
+      
+
+ ); +}; + +export class Details extends React.Component { + constructor(props) { + super(props); + this.state = { + open: false, + summary: null, + content: null + }; + } + + componentDidMount() { + const { children, url } = this.props; + + // Find the index of + const closeDefaultTagIndex = children.findIndex(child => { + if (React.isValidElement(child)) { + return ( + child.props.props.className.includes('tag') && + child.props.children.length === DEFAULT_CHILDREN_SIZE + ); + } + }); + + // Summary is the part of the snippet that would be shown in the code snippet, + // to get it we need to cut the enclosing tags + const summary = children + .splice(2, closeDefaultTagIndex - 3) + .map(removeSpaces) + .map((child, i) => addLink(child, i, url)); + + children.splice(0, DEFAULT_CHILDREN_SIZE); // Remove information + + this.setState({ + summary, + content: children + }); + } + + clickOutsideHandler = () => { + this.setState({ open: false }); + }; + + toggleVisibility = () => { + this.setState({ open: !this.state.open }); + }; + + render() { + const { open, summary, content } = this.state; + return ( + } + > + + {summary} + + + ); + } +} diff --git a/src/components/Container/Container.jsx b/src/components/Container/Container.jsx index 9f00bd0a8493..b13a357e982d 100644 --- a/src/components/Container/Container.jsx +++ b/src/components/Container/Container.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import './Container.scss'; export default (props = {}) => { let { className = '' } = props; diff --git a/src/components/Cube/Cube.jsx b/src/components/Cube/Cube.jsx index d80084ed565d..37348a044f3e 100644 --- a/src/components/Cube/Cube.jsx +++ b/src/components/Cube/Cube.jsx @@ -1,6 +1,10 @@ +// Import External Dependencies import React from 'react'; import PropTypes from 'prop-types'; +// Load Styling +import './Cube.scss'; + export default class Cube extends React.Component { static propTypes = { hover: PropTypes.bool, diff --git a/src/components/Dropdown/Dropdown.jsx b/src/components/Dropdown/Dropdown.jsx index a8f7a55f012d..126e8f25f8d0 100644 --- a/src/components/Dropdown/Dropdown.jsx +++ b/src/components/Dropdown/Dropdown.jsx @@ -1,37 +1,69 @@ import React from 'react'; import LanguageIcon from '../../assets/language-icon.svg'; +import './Dropdown.scss'; export default class Dropdown extends React.Component { state = { active: false }; + componentDidMount() { + document.addEventListener('keyup', this._closeDropdownOnEsc.bind(this), true); + document.addEventListener('focus', this._closeDropdownIfFocusLost.bind(this), true); + document.addEventListener('click', this._closeDropdownIfFocusLost.bind(this), true); + } + + _closeDropdownOnEsc(e) { + if (e.key === "Escape" && this.state.active) { + this.setState({ active: false}, () => { + this.dropdownButton.focus(); + }); + } + } + + _closeDropdownIfFocusLost(e) { + if (this.state.active && !this.dropdown.contains(e.target)) { + this.setState({ active: false }); + } + } + render() { let { className = '', items = [] } = this.props; let activeMod = this.state.active ? "dropdown__list--active" : ""; return ( -
this.dropdown = el } onMouseOver={ this._toggle.bind(this, true) } - onMouseLeave={ this._toggle.bind(this, false) }> - select language - {/* Commented out until media breakpoints are in place - { items[0].title } */} -