Skip to content

Commit

Permalink
feat(gatsby): Make __experimentalThemes part of plugin APIs (#15144)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristopherBiscardi authored and sidharthachatterjee committed Jul 2, 2019
1 parent 6ce0411 commit 3dce8cb
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 38 deletions.
6 changes: 5 additions & 1 deletion packages/gatsby/src/bootstrap/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,17 @@ module.exports = async (args: BootstrapArgs) => {

// theme gatsby configs can be functions or objects
if (config && config.__experimentalThemes) {
const themes = await loadThemes(config)
// TODO: deprecation message for old __experimentalThemes
const themes = await loadThemes(config, { useLegacyThemes: true })
config = themes.config

store.dispatch({
type: `SET_RESOLVED_THEMES`,
payload: themes.themes,
})
} else if (config) {
const plugins = await loadThemes(config, { useLegacyThemes: false })
config = plugins.config
}

if (config && config.polyfill) {
Expand Down
29 changes: 21 additions & 8 deletions packages/gatsby/src/bootstrap/load-themes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ const getConfigFile = require(`../get-config-file`)
// get the gatsby-config file for a theme
const resolveTheme = async themeSpec => {
const themeName = themeSpec.resolve || themeSpec
const themeDir = path.dirname(require.resolve(themeName))
let themeDir
try {
themeDir = path.dirname(require.resolve(themeName))
} catch (e) {
// this can be local plugin, and require.resolve will throw
// in this case - let's return partial entry
return { themeName, themeSpec }
}
const theme = await preferDefault(getConfigFile(themeDir, `gatsby-config`))
// if theme is a function, call it with the themeConfig
let themeConfig = theme
Expand All @@ -26,16 +33,22 @@ const resolveTheme = async themeSpec => {
// Theoretically, there could be an infinite loop here but in practice there is
// no use case for a loop so I expect that to only happen if someone is very
// off track and creating their own set of themes
const processTheme = ({ themeName, themeConfig, themeSpec, themeDir }) => {
const processTheme = (
{ themeName, themeConfig, themeSpec, themeDir },
{ useLegacyThemes }
) => {
const themesList = useLegacyThemes
? themeConfig && themeConfig.__experimentalThemes
: themeConfig && themeConfig.plugins
// gatsby themes don't have to specify a gatsby-config.js (they might only use gatsby-node, etc)
// in this case they're technically plugins, but we should support it anyway
// because we can't guarantee which files theme creators create first
if (themeConfig && themeConfig.__experimentalThemes) {
if (themeConfig && themesList) {
// for every parent theme a theme defines, resolve the parent's
// gatsby config and return it in order [parentA, parentB, child]
return Promise.mapSeries(themeConfig.__experimentalThemes, async spec => {
return Promise.mapSeries(themesList, async spec => {
const themeObj = await resolveTheme(spec)
return processTheme(themeObj)
return processTheme(themeObj, { useLegacyThemes })
}).then(arr =>
arr.concat([{ themeName, themeConfig, themeSpec, themeDir }])
)
Expand All @@ -45,12 +58,12 @@ const processTheme = ({ themeName, themeConfig, themeSpec, themeDir }) => {
}
}

module.exports = async config => {
module.exports = async (config, { useLegacyThemes = false }) => {
const themesA = await Promise.mapSeries(
config.__experimentalThemes,
useLegacyThemes ? config.__experimentalThemes : config.plugins,
async themeSpec => {
const themeObj = await resolveTheme(themeSpec)
return processTheme(themeObj)
return processTheme(themeObj, { useLegacyThemes })
}
).then(arr => _.flattenDeep(arr))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ exports.onCreateWebpackConfig = (
{ store, stage, getConfig, rules, loaders, actions },
pluginOptions
) => {
const { program, themes } = store.getState()
const { themes, flattenedPlugins } = store.getState()

if (themes.themes) {
actions.setWebpackConfig({
resolve: {
plugins: [
new GatsbyThemeComponentShadowingResolverPlugin({
themes: themes.themes,
projectRoot: program.directory,
}),
],
},
})
}
actions.setWebpackConfig({
resolve: {
plugins: [
new GatsbyThemeComponentShadowingResolverPlugin({
themes: themes.themes
? themes.themes
: flattenedPlugins.map(plugin => {
return {
themeDir: plugin.pluginFilepath,
themeName: plugin.name,
}
}),
}),
],
},
})
}
12 changes: 10 additions & 2 deletions packages/gatsby/src/query/query-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,19 @@ export { Runner, resolveThemes }

export default async function compile(): Promise<Map<string, RootQuery>> {
// TODO: swap plugins to themes
const { program, schema, themes } = store.getState()
const { program, schema, themes, flattenedPlugins } = store.getState()

const runner = new Runner(
program.directory,
resolveThemes(themes.themes),
resolveThemes(
themes.themes
? themes.themes
: flattenedPlugins.map(plugin => {
return {
themeDir: plugin.pluginFilepath,
}
})
),
schema
)

Expand Down
31 changes: 17 additions & 14 deletions packages/gatsby/src/utils/get-static-dir.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,24 @@ const { store } = require(`../redux`)
*/
exports.copyStaticDirs = () => {
// access the store to get themes
const { themes } = store.getState() // ensure there are themes
const { themes, flattenedPlugins } = store.getState()
// if there are legacy themes, only use them. Otherwise proceed with plugins
const themesSet = themes.themes
? themes.themes
: flattenedPlugins.map(plugin => {
return {
themeDir: plugin.pluginFilepath,
themeName: plugin.name,
}
})

if (themes && themes.themes) {
themes.themes
// create an array of potential theme static folders
.map(theme => nodePath.resolve(theme.themeDir, `static`))
// filter out the static folders that don't exist
.filter(themeStaticPath => fs.existsSync(themeStaticPath))
// copy the files for each folder into the user's build
.map(folder =>
fs.copySync(folder, nodePath.join(process.cwd(), `public`), {
dereference: true,
})
)
}
themesSet
// create an array of potential theme static folders
.map(theme => nodePath.resolve(theme.themeDir, `static`))
// filter out the static folders that don't exist
.filter(themeStaticPath => fs.existsSync(themeStaticPath))
// copy the files for each folder into the user's build
.map(folder => fs.copySync(folder, nodePath.join(process.cwd(), `public`)))

const staticDir = nodePath.join(process.cwd(), `static`)
if (!fs.existsSync(staticDir)) return Promise.resolve()
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/src/utils/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ module.exports = async (program, directory, suppliedStage) => {
})
)
}

switch (stage) {
case `develop`: {
// get schema to pass to eslint config and program for directory
Expand Down

0 comments on commit 3dce8cb

Please sign in to comment.