diff --git a/.eslintrc b/.eslintrc index 025abf510e442..81f9691a139cb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -27,6 +27,7 @@ }, "rules": { "no-console": "off", + "no-inner-declarations": "off", "valid-jsdoc": "off", "require-jsdoc": "off", "quotes": ["error", "backtick"], diff --git a/docs/docs/plugins.md b/docs/docs/plugins.md index d5ed554e48071..b1b420d0cec82 100644 --- a/docs/docs/plugins.md +++ b/docs/docs/plugins.md @@ -77,7 +77,7 @@ root. ## Official plugins * [gatsby-plugin-catch-links](/packages/gatsby-plugin-catch-links/) -* [gatsby-plugin-client-only-paths](/packages/gatsby-plugin-client-only-paths/) +* [gatsby-plugin-create-client-paths](/packages/gatsby-plugin-create-client-paths/) * [gatsby-plugin-coffeescript](/packages/gatsby-plugin-coffeescript/) * [gatsby-plugin-feed](/packages/gatsby-plugin-feed/) * [gatsby-plugin-glamor](/packages/gatsby-plugin-glamor/) diff --git a/packages/gatsby-remark-autolink-headers/package.json b/packages/gatsby-remark-autolink-headers/package.json index b7a49b9ee9d87..d970d7db3fb1e 100644 --- a/packages/gatsby-remark-autolink-headers/package.json +++ b/packages/gatsby-remark-autolink-headers/package.json @@ -1,7 +1,7 @@ { "name": "gatsby-remark-autolink-headers", "description": "Gatsby plugin to autolink headers in markdown processed by Remark", - "version": "1.4.10", + "version": "1.4.11", "author": "Kyle Mathews ", "dependencies": { "babel-runtime": "^6.26.0", diff --git a/packages/gatsby-remark-autolink-headers/src/gatsby-browser.js b/packages/gatsby-remark-autolink-headers/src/gatsby-browser.js index 223671f5edb1d..0d82719482752 100644 --- a/packages/gatsby-remark-autolink-headers/src/gatsby-browser.js +++ b/packages/gatsby-remark-autolink-headers/src/gatsby-browser.js @@ -1,7 +1,7 @@ const scrollToHash = offsetY => { - // Make sure React has had a change to flush to DOM first. + // Make sure React has had a chance to flush to DOM first. setTimeout(() => { - const hash = window.location.hash.replace(`#`, ``) + const hash = window.decodeURI(window.location.hash.replace(`#`, ``)) if (hash !== ``) { const element = document.getElementById(hash) if (element) { diff --git a/packages/gatsby-remark-autolink-headers/src/gatsby-ssr.js b/packages/gatsby-remark-autolink-headers/src/gatsby-ssr.js index 6ebd10c1e9d02..11648c1fb0e39 100644 --- a/packages/gatsby-remark-autolink-headers/src/gatsby-ssr.js +++ b/packages/gatsby-remark-autolink-headers/src/gatsby-ssr.js @@ -32,7 +32,7 @@ exports.onRenderBody = ({ setHeadComponents }, pluginOptions) => { const script = ` document.addEventListener("DOMContentLoaded", function(event) { - var hash = location.hash.replace('#', '') + var hash = window.decodeURI(location.hash.replace('#', '')) if (hash !== '') { var element = document.getElementById(hash) if (element) { diff --git a/packages/gatsby-remark-custom-blocks/.gitignore b/packages/gatsby-remark-custom-blocks/.gitignore new file mode 100644 index 0000000000000..de4d1f007dd19 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/.gitignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/packages/gatsby-remark-custom-blocks/.npmignore b/packages/gatsby-remark-custom-blocks/.npmignore new file mode 100644 index 0000000000000..e771d2c9fa299 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/.npmignore @@ -0,0 +1,34 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules +*.un~ +yarn.lock +src +flow-typed +coverage +decls +examples diff --git a/packages/gatsby-remark-custom-blocks/README.md b/packages/gatsby-remark-custom-blocks/README.md new file mode 100644 index 0000000000000..a8b81f55288f4 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/README.md @@ -0,0 +1,31 @@ +# gatsby-remark-custom-blocks + +Adds custom blocks to `MarkdownRemark` using [remark-custom-blocks](https://github.com/zestedesavoir/zmarkdown/tree/master/packages/remark-custom-blocks). + +## Install + +`npm install --save gatsby-remark-custom-blocks` + +## How to use + +```javascript +// In your gatsby-config.js +plugins: [ + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + { + resolve: "gatsby-remark-custom-blocks", + options: { + blocks: { + danger: "custom-block-danger", + info: "custom-block-info", + }, + }, + }, + ], + }, + }, +]; +``` diff --git a/packages/gatsby-remark-custom-blocks/package.json b/packages/gatsby-remark-custom-blocks/package.json new file mode 100644 index 0000000000000..f9a36801cf4c1 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/package.json @@ -0,0 +1,33 @@ +{ + "name": "gatsby-remark-custom-blocks", + "version": "1.0.1", + "description": "Gatsby remark plugin for adding custom blocks in markdown", + "main": "dist/index.js", + "scripts": { + "prebuild": "rimraf dist", + "build": "yarn prebuild && babel --out-dir dist --ignore __tests__ src", + "prepublish": "yarn build" + }, + "repository": "https://github.com/AlahmadiQ8/gatsby-remark-custom-blocks", + "keywords": [ + "gatsby", + "gatsby-plugin", + "markdown", + "remark" + ], + "author": "Mohammad Asad Mohammad ", + "license": "MIT", + "private": false, + "files": [ + "dist", + "README.md" + ], + "devDependencies": { + "babel-cli": "^6.26.0", + "rimraf": "^2.6.2", + "unist-util-find": "^1.0.1" + }, + "dependencies": { + "remark-custom-blocks": "^1.0.6" + } +} diff --git a/packages/gatsby-remark-custom-blocks/src/__tests__/index.js b/packages/gatsby-remark-custom-blocks/src/__tests__/index.js new file mode 100644 index 0000000000000..cc3b2e3efdf37 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/src/__tests__/index.js @@ -0,0 +1,30 @@ +const Remark = require(`remark`) +const find = require(`unist-util-find`) +const plugin = require(`../index`) + +describe(`gatsby-remark-custom-blocks`, () => { + let remark + + beforeEach(() => { + remark = new Remark() + }) + + it(`errors if missing required plugin options`, () => { + expect(plugin.setParserPlugins).toThrow(`missing required "blocks" option`) + }) + + it(`creates nodes of blocks given in options`, () => { + const parserPlugins = plugin.setParserPlugins({ + blocks: { someType: `test`, anotherType: `another` }, + }) + const [parser, options] = parserPlugins[0] + remark.use(parser, options) + const markdownAST = remark.parse(` +[[someType]] +| content +[[anotherType]] +| content`) + expect(find(markdownAST, { type: `someTypeCustomBlock` })).toBeTruthy() + expect(find(markdownAST, { type: `anotherTypeCustomBlock` })).toBeTruthy() + }) +}) diff --git a/packages/gatsby-remark-custom-blocks/src/index.js b/packages/gatsby-remark-custom-blocks/src/index.js new file mode 100644 index 0000000000000..e901d5c9a84c7 --- /dev/null +++ b/packages/gatsby-remark-custom-blocks/src/index.js @@ -0,0 +1,10 @@ +const isNil = require(`lodash/isNil`) +const has = require(`lodash/has`) +const remarkCustomBlocks = require(`remark-custom-blocks`) + +module.exports.setParserPlugins = options => { + if (isNil(options) || !has(options, `blocks`)) { + throw Error(`missing required "blocks" option`) + } + return [[remarkCustomBlocks, options.blocks]] +} diff --git a/packages/gatsby-transformer-remark/package.json b/packages/gatsby-transformer-remark/package.json index efaf7e092c78d..6476cce6ccb93 100644 --- a/packages/gatsby-transformer-remark/package.json +++ b/packages/gatsby-transformer-remark/package.json @@ -1,7 +1,7 @@ { "name": "gatsby-transformer-remark", "description": "Gatsby transformer plugin for Markdown using the Remark library and ecosystem", - "version": "1.7.25", + "version": "1.7.26", "author": "Kyle Mathews ", "dependencies": { "babel-runtime": "^6.26.0", diff --git a/packages/gatsby-transformer-remark/src/extend-node-type.js b/packages/gatsby-transformer-remark/src/extend-node-type.js index 97a5e191473fd..3390f36b36a6d 100644 --- a/packages/gatsby-transformer-remark/src/extend-node-type.js +++ b/packages/gatsby-transformer-remark/src/extend-node-type.js @@ -60,8 +60,15 @@ module.exports = ( for (let plugin of pluginOptions.plugins) { const requiredPlugin = require(plugin.resolve) if (_.isFunction(requiredPlugin.setParserPlugins)) { - for (let parserPlugin of requiredPlugin.setParserPlugins()) { - remark = remark.use(parserPlugin) + for (let parserPlugin of requiredPlugin.setParserPlugins( + plugin.pluginOptions + )) { + if (_.isArray(parserPlugin)) { + const [parser, options] = parserPlugin + remark = remark.use(parser, options) + } else { + remark = remark.use(parserPlugin) + } } } } diff --git a/packages/gatsby/cache-dir/__tests__/loader.js b/packages/gatsby/cache-dir/__tests__/loader.js index dfd3c2dd5deee..f2203d0c0e5b6 100644 --- a/packages/gatsby/cache-dir/__tests__/loader.js +++ b/packages/gatsby/cache-dir/__tests__/loader.js @@ -2,6 +2,13 @@ import loader from "../loader.js" describe(`Loader`, () => { beforeEach(() => { + delete global.__PATH_PREFIX__ + delete global.__PREFIX_PATHS__ + + // Workaround for Node 6 issue: https://github.com/facebook/jest/issues/5159 + if (global.hasOwnProperty(`__PATH_PREFIX__`)) global.__PATH_PREFIX__ = undefined + if (global.hasOwnProperty(`__PREFIX_PATHS__`)) global.__PREFIX_PATHS__ = undefined + loader.empty() loader.addPagesArray([ { @@ -68,3 +75,72 @@ describe(`Loader`, () => { expect(loader.getResources()).toMatchSnapshot() }) }) + +describe(`Loader path prefixing`, () => { + let pagesArray + + beforeEach(() => { + delete global.__PATH_PREFIX__ + delete global.__PREFIX_PATHS__ + + // Workaround for Node 6 issue: https://github.com/facebook/jest/issues/5159 + if (global.hasOwnProperty(`__PATH_PREFIX__`)) global.__PATH_PREFIX__ = undefined + if (global.hasOwnProperty(`__PREFIX_PATHS__`)) global.__PREFIX_PATHS__ = undefined + + pagesArray = [ + { + path: `/about/`, + componentChunkName: `page-component---src-pages-test-js`, + jsonName: `about.json`, + }, + { + path: `/about/me/`, + componentChunkName: `page-component---src-pages-test-js`, + jsonName: `about-me.json`, + }, + ] + + loader.empty() + }) + + test(`Path prefix present and enabled`, () => { + global.__PATH_PREFIX__ = `/foo` + global.__PREFIX_PATHS__ = true + loader.addPagesArray(pagesArray) + loader.enqueue(`/foo/about/`) + expect(loader.has(`/about/`)).toEqual(true) + expect(loader.has(`/foo/about/`)).toEqual(false) + }) + + test(`Path prefix present but not enabled`, () => { + global.__PATH_PREFIX__ = `/foo` + delete global.__PREFIX_PATHS__ + loader.addPagesArray(pagesArray) + + // don't enqueue prefixed paths + loader.enqueue(`/foo/about/`) + expect(loader.has(`/about/`)).toEqual(false) + expect(loader.has(`/foo/about/`)).toEqual(false) + + // do enqueue unprefixed paths + loader.enqueue(`/about/`) + expect(loader.has(`/about/`)).toEqual(true) + expect(loader.has(`/foo/about/`)).toEqual(false) + }) + + test(`Path prefix missing but enabled`, () => { + delete global.__PATH_PREFIX__ + global.__PREFIX_PATHS__ = true + loader.addPagesArray(pagesArray) + + // don't enqueue prefixed paths + loader.enqueue(`/foo/about/`) + expect(loader.has(`/about/`)).toEqual(false) + expect(loader.has(`/foo/about/`)).toEqual(false) + + // do enqueue unprefixed paths + loader.enqueue(`/about/`) + expect(loader.has(`/about/`)).toEqual(true) + expect(loader.has(`/foo/about/`)).toEqual(false) + }) +}) diff --git a/packages/gatsby/cache-dir/__tests__/strip-prefix.js b/packages/gatsby/cache-dir/__tests__/strip-prefix.js new file mode 100644 index 0000000000000..78fc19be1d27c --- /dev/null +++ b/packages/gatsby/cache-dir/__tests__/strip-prefix.js @@ -0,0 +1,23 @@ +const stripPrefix = require(`../strip-prefix`).default + +describe(`strip-prefix`, () => { + it(`strips a prefix`, () => { + expect(stripPrefix(`/foo/bar/`, `/foo`)).toBe(`/bar/`) + }) + + it(`strips first instance only`, () => { + expect(stripPrefix(`/foo/foo/bar/`, `/foo`)).toBe(`/foo/bar/`) + }) + + it(`ignores prefix appearing elsewhere in the string`, () => { + expect(stripPrefix(`/foo/bar/`, `bar`)).toBe(`/foo/bar/`) + }) + + it(`ignores a non-existent prefix`, () => { + expect(stripPrefix(`/bar`, `/foo`)).toBe(`/bar`) + }) + + it(`returns input str if no prefix is provided`, () => { + expect(stripPrefix(`/bar`)).toBe(`/bar`) + }) +}) diff --git a/packages/gatsby/cache-dir/find-page.js b/packages/gatsby/cache-dir/find-page.js index f32c2f0ea16a4..55904b449438f 100644 --- a/packages/gatsby/cache-dir/find-page.js +++ b/packages/gatsby/cache-dir/find-page.js @@ -1,12 +1,14 @@ // TODO add tests especially for handling prefixed links. import { matchPath } from "react-router-dom" +import stripPrefix from "./strip-prefix" const pageCache = {} module.exports = (pages, pathPrefix = ``) => rawPathname => { let pathname = decodeURIComponent(rawPathname) + // Remove the pathPrefix from the pathname. - let trimmedPathname = pathname.slice(pathPrefix.length) + let trimmedPathname = stripPrefix(pathname, pathPrefix) // Remove any hashfragment if (trimmedPathname.split(`#`).length > 1) { diff --git a/packages/gatsby/cache-dir/loader.js b/packages/gatsby/cache-dir/loader.js index 2659118d33889..51a8006b8cda1 100644 --- a/packages/gatsby/cache-dir/loader.js +++ b/packages/gatsby/cache-dir/loader.js @@ -1,6 +1,7 @@ import React, { createElement } from "react" import pageFinderFactory from "./find-page" import emitter from "./emitter" +import stripPrefix from "./strip-prefix" let findPage let syncRequires = {} @@ -14,6 +15,7 @@ let pages = [] // we load all resources for likely-to-be-visited paths. let pathArray = [] let pathCount = {} +let pathPrefix = `` let resourcesArray = [] let resourcesCount = {} const preferDefault = m => (m && m.default) || m @@ -153,12 +155,15 @@ const queue = { resourcesCount = {} resourcesArray = [] pages = [] + pathPrefix = `` }, addPagesArray: newPages => { pages = newPages - let pathPrefix = `` - if (typeof __PREFIX_PATHS__ !== `undefined`) { - pathPrefix = __PATH_PREFIX__ + if ( + typeof __PREFIX_PATHS__ !== `undefined` && + typeof __PATH_PREFIX__ !== `undefined` + ) { + if (__PREFIX_PATHS__ === true) pathPrefix = __PATH_PREFIX__ } findPage = pageFinderFactory(newPages, pathPrefix) }, @@ -168,9 +173,10 @@ const queue = { addProdRequires: prodRequires => { asyncRequires = prodRequires }, - dequeue: path => pathArray.pop(), - enqueue: path => { + dequeue: () => pathArray.pop(), + enqueue: rawPath => { // Check page exists. + const path = stripPrefix(rawPath, pathPrefix) if (!pages.some(p => p.path === path)) { return false } diff --git a/packages/gatsby/cache-dir/production-app.js b/packages/gatsby/cache-dir/production-app.js index 467d85400dd6a..613d52eeb4875 100644 --- a/packages/gatsby/cache-dir/production-app.js +++ b/packages/gatsby/cache-dir/production-app.js @@ -8,6 +8,7 @@ import { Router, Route, withRouter, matchPath } from "react-router-dom" import { ScrollContext } from "gatsby-react-router-scroll" import domReady from "domready" import history from "./history" +window.___history = history import emitter from "./emitter" window.___emitter = emitter import pages from "./pages.json" @@ -101,9 +102,11 @@ apiRunnerAsync(`onClientEntry`).then(() => { action: history.action, }) + let initialAttachDone = false function attachToHistory(history) { - if (!window.___history) { + if (!window.___history || initialAttachDone === false) { window.___history = history + initialAttachDone = true history.listen((location, action) => { if (!maybeRedirect(location.pathname)) { diff --git a/packages/gatsby/cache-dir/strip-prefix.js b/packages/gatsby/cache-dir/strip-prefix.js new file mode 100644 index 0000000000000..f5b83ccb56c71 --- /dev/null +++ b/packages/gatsby/cache-dir/strip-prefix.js @@ -0,0 +1,9 @@ +/** + * Remove a prefix from a string. Return the input string if the given prefix + * isn't found. + */ + +export default (str, prefix = ``) => { + if (str.substr(0, prefix.length) === prefix) return str.slice(prefix.length) + return str +} diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 30ef1d82e41d2..5511836e05d97 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -1,7 +1,7 @@ { "name": "gatsby", "description": "React.js Static Site Generator", - "version": "1.9.147", + "version": "1.9.149", "author": "Kyle Mathews ", "bin": { "gatsby": "./dist/bin/gatsby.js" diff --git a/packages/gatsby/src/commands/develop.js b/packages/gatsby/src/commands/develop.js index 0326ccc4e6540..69786ac445ee6 100644 --- a/packages/gatsby/src/commands/develop.js +++ b/packages/gatsby/src/commands/develop.js @@ -96,7 +96,10 @@ async function startServer(program) { // Allow requests from any origin. Avoids CORS issues when using the `--host` flag. app.use((req, res, next) => { res.header(`Access-Control-Allow-Origin`, `*`) - res.header(`Access-Control-Allow-Headers`, `Origin, X-Requested-With, Content-Type, Accept`) + res.header( + `Access-Control-Allow-Headers`, + `Origin, X-Requested-With, Content-Type, Accept` + ) next() }) diff --git a/yarn.lock b/yarn.lock index c82d2767a7879..2affa1805775f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10416,6 +10416,12 @@ relay-runtime@1.4.1: fbjs "^0.8.14" relay-debugger-react-native-runtime "0.0.10" +remark-custom-blocks@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/remark-custom-blocks/-/remark-custom-blocks-1.0.6.tgz#2a756630cbfa6943ee69fa76432c59e4cd36112e" + dependencies: + space-separated-tokens "^1.1.1" + remark-html@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-6.0.1.tgz#5094d2c71f7941fdb2ae865bac76627757ce09c1" @@ -10883,7 +10889,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.6, rimraf@^2.2.8, rimraf@^2.3.2, rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.0, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.6, rimraf@^2.2.8, rimraf@^2.3.2, rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.0, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -11614,7 +11620,7 @@ sourcemapped-stacktrace@^1.1.6: dependencies: source-map "0.5.6" -space-separated-tokens@^1.0.0: +space-separated-tokens@^1.0.0, space-separated-tokens@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.1.tgz#9695b9df9e65aec1811d4c3f9ce52520bc2f7e4d" dependencies: @@ -12696,7 +12702,7 @@ unist-builder@^1.0.0, unist-builder@^1.0.1: unist-util-find@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/unist-util-find/-/unist-util-find-1.0.1.tgz#1062bbb6928c7a97c6adc89b53745d4c46c222a2" + resolved "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.1.tgz#1062bbb6928c7a97c6adc89b53745d4c46c222a2" dependencies: lodash.iteratee "^4.5.0" remark "^5.0.1"