Skip to content

Commit

Permalink
feat(gatsby-remark-code-repls): include matching css option + refacto…
Browse files Browse the repository at this point in the history
…ring

This is based upon suggestions in PR gatsbyjs#12110 review.
Since there is a breaking change in the API, the version has been ⬆

Signed-off-by: Alessandro De Blasis <[email protected]>
  • Loading branch information
deblasis committed Mar 29, 2019
1 parent 5b5ae42 commit 6434ded
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 158 deletions.
50 changes: 29 additions & 21 deletions packages/gatsby-remark-code-repls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,26 +134,11 @@ specified examples directory. (This will avoid broken links at runtime.)
// eg <a href="...">Click here</a>
defaultText: 'Click here',

// Optional runtime dependencies to load from NPM.
// This option only applies to REPLs that support it (eg CodeSandbox).
// eg ['react', 'react-dom'] or ['react@15', 'react-dom@15']
dependencies: [],

// Example code links are relative to this dir.
// eg examples/path/to/file.js
directory: `${__dirname}/examples/`,

// Optional externals to load from a CDN.
// This option only applies to REPLs that support it (eg Codepen).
// eg '//unpkg.com/react/umd/react.development.js'
externals: [],

// Optional HTML contents to inject into REPL.
// Defaults to `<div id="root"></div>`.
// This option only applies to REPLs that support it (eg Codepen, CodeSandbox).
// eg '<div id="root"></div>'
html: '',

// Optional path to a custom redirect template.
// The redirect page is only shown briefly,
// But you can use this setting to override its CSS styling.
Expand All @@ -164,12 +149,35 @@ specified examples directory. (This will avoid broken links at runtime.)
// eg <a href="..." target="_blank" rel="noreferrer">...</a>
target: '_blank',

// Include CSS with matching name.
// This option only applies to REPLs that support it (eg Codepen).
// If set to `true`, when specifying `file1.js` as example file,
// it will try to inject the CSS in `file1.css` if the file exists,
// otherwise the default behaviour is preserved
includeMatchingCSS: false,

// Provider specific options
codepen: {
// Optional HTML contents to inject into REPL.
// Defaults to `<div id="root"></div>`.
// eg '<div id="root"></div>'
html: '',

// Optional externals to load from a CDN.
// eg '//unpkg.com/react/umd/react.development.js'
externals: [],

// Include CSS with matching name.
// If set to `true`, when specifying `file1.js` as example file,
// it will try to inject the CSS in `file1.css` if the file exists,
// otherwise the default behaviour is preserved
includeMatchingCSS: false,
},

codesandbox: {
// Optional HTML contents to inject into REPL.
// Defaults to `<div id="root"></div>`.
// eg '<div id="root"></div>'
html: '',

// Optional runtime dependencies to load from NPM.
// eg ['react', 'react-dom'] or ['react@15', 'react-dom@15']
dependencies: [],
}
},
},
```
2 changes: 1 addition & 1 deletion packages/gatsby-remark-code-repls/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gatsby-remark-code-repls",
"description": "Gatsby plugin to auto-generate links to popular REPLs like Babel and Codepen",
"version": "2.0.7",
"version": "3.0.0",
"author": "Brian Vaughn <[email protected]>",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
Expand Down
257 changes: 148 additions & 109 deletions packages/gatsby-remark-code-repls/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,148 +161,187 @@ describe(`gatsby-remark-code-repls`, () => {
expect(js_external).toBe(``)
})

it(`should load custom externals if specified`, async () => {
readdir.mockResolvedValue([`file.js`])
describe(`codepen specific`, () => {
it(`should load custom externals if specified`, async () => {
readdir.mockResolvedValue([`file.js`])

await createPages(createPagesParams, {
codepen: {
externals: [`foo.js`, `bar.js`],
},
})
const { js_external } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

await createPages(createPagesParams, { externals: [`foo.js`, `bar.js`] })
expect(js_external).toContain(`foo.js`)
expect(js_external).toContain(`bar.js`)
})
it(`should support custom, user-defined HTML for index page`, async () => {
readdir.mockResolvedValue([`file.js`])

const { js_external } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)
await createPages(createPagesParams, {
codepen: { html: `<span id="foo"></span>` },
})
const { html } = JSON.parse(createPage.mock.calls[0][0].context.payload)

expect(js_external).toContain(`foo.js`)
expect(js_external).toContain(`bar.js`)
})
expect(html).toBe(`<span id="foo"></span>`)
})

it(`should inject the required prop-types for the Codepen prefill API`, async () => {
readdir.mockResolvedValue([`file.js`])
it(`should support includeMatchingCSS = "true" when matching file exists`, async () => {
readdir.mockResolvedValue([`file.js`, `file.css`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else if (path === `file.css`) {
return `html { color: red; }`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
codepen: {
includeMatchingCSS: true,
},
})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

await createPages(createPagesParams)
expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(`html { color: red; }`)
})

const { action, payload } = createPage.mock.calls[0][0].context
it(`should support includeMatchingCSS = "false" when matching file exists`, async () => {
readdir.mockResolvedValue([`file.js`, `file.css`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else if (path === `file.css`) {
return `html { color: red; }`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
codepen: {
includeMatchingCSS: false,
},
})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

expect(action).toBeTruthy()
expect(payload).toBeTruthy()
})
expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
})

it(`should render default HTML for index page if no override specified`, async () => {
readdir.mockResolvedValue([`file.js`])
it(`should support includeMatchingCSS = "true" when matching file doesn't exist`, async () => {
readdir.mockResolvedValue([`file.js`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
codepen: {
includeMatchingCSS: true,
},
})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

await createPages(createPagesParams, {})
expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
})

const { html } = JSON.parse(createPage.mock.calls[0][0].context.payload)
it(`should support includeMatchingCSS = "false" when matching file doesn't exist`, async () => {
readdir.mockResolvedValue([`file.js`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
codepen: {
includeMatchingCSS: false,
},
})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

expect(html).toBe(OPTION_DEFAULT_HTML)
expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
})
})

it(`should support custom, user-defined HTML for index page`, async () => {
readdir.mockResolvedValue([`file.js`])

await createPages(createPagesParams, { html: `<span id="foo"></span>` })
describe(`codesandbox specific`, () => {
beforeEach(() => {
fs.existsSync.mockReset()
fs.existsSync.mockReturnValue(true)

const { html } = JSON.parse(createPage.mock.calls[0][0].context.payload)

expect(html).toBe(`<span id="foo"></span>`)
})
fs.readFileSync.mockReset()
fs.readFileSync.mockReturnValue(`const foo = "bar";`)

it(`should support includeMatchingCSS = "true" when matching file exists`, async () => {
readdir.mockResolvedValue([`file.js`, `file.css`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else if (path === `file.css`) {
return `html { color: red; }`
} else {
throwFileNotFoundErr(path)
}
return null
})
readdir.mockReset()
readdir.mockResolvedValue([`file.js`])

await createPages(createPagesParams, {
includeMatchingCSS: true,
createPage.mockReset()
})
it(`should support custom, user-defined HTML for index page`, async () => {
readdir.mockResolvedValue([`file.js`])

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)
await createPages(createPagesParams, {
codepen: { html: `<span id="foo"></span>` },
})

expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(`html { color: red; }`)
})
const { html } = JSON.parse(createPage.mock.calls[0][0].context.payload)

it(`should support includeMatchingCSS = "false" when matching file exists`, async () => {
readdir.mockResolvedValue([`file.js`, `file.css`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else if (path === `file.css`) {
return `html { color: red; }`
} else {
throwFileNotFoundErr(path)
}
return null
expect(html).toBe(`<span id="foo"></span>`)
})

await createPages(createPagesParams, {
includeMatchingCSS: false,
})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)

expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
})

it(`should support includeMatchingCSS = "true" when matching file doesn't exist`, async () => {
it(`should inject the required prop-types for the Codepen prefill API`, async () => {
readdir.mockResolvedValue([`file.js`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
includeMatchingCSS: true,
})
await createPages(createPagesParams)

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)
const { action, payload } = createPage.mock.calls[0][0].context

expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
expect(action).toBeTruthy()
expect(payload).toBeTruthy()
})

it(`should support includeMatchingCSS = "false" when matching file doesn't exist`, async () => {
it(`should render default HTML for index page if no override specified`, async () => {
readdir.mockResolvedValue([`file.js`])
fs.readFileSync.mockReset()
fs.readFileSync.mockImplementation((path, options) => {
if (path === `file.js`) {
return `const foo = "bar";`
} else {
throwFileNotFoundErr(path)
}
return null
})

await createPages(createPagesParams, {
includeMatchingCSS: false,
})
await createPages(createPagesParams, {})

const { css, js } = JSON.parse(
createPage.mock.calls[0][0].context.payload
)
const { html } = JSON.parse(createPage.mock.calls[0][0].context.payload)

expect(js).toBe(`const foo = "bar";`)
expect(css).toBe(undefined)
expect(html).toBe(OPTION_DEFAULT_HTML)
})
})
})
Loading

0 comments on commit 6434ded

Please sign in to comment.