2020-11-16 10:20:16 -05:00
/ * *
* Copyright ( c ) Facebook , Inc . and its affiliates .
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree .
* /
2022-05-23 03:40:53 -04:00
// @ts-check
2022-01-07 23:59:28 -05:00
import fs from 'fs-extra' ;
import shell from 'shelljs' ;
2020-11-16 10:20:16 -05:00
2022-05-23 03:40:53 -04:00
const NODE _MAJOR _VERSION = parseInt (
/** @type {string} */ ( process . versions . node . split ( '.' ) [ 0 ] ) ,
10 ,
) ;
2021-12-21 11:49:39 -05:00
if ( NODE _MAJOR _VERSION < 16 ) {
throw new Error (
'This generateExamples Docusaurus script requires at least Node.js 16 and npm 7. See why here: https://github.com/facebook/docusaurus/pull/5722#issuecomment-948847891' ,
) ;
}
2022-05-23 03:40:53 -04:00
/ * *
* Generate one example per init template
* We use those generated examples as CodeSandbox projects
* See https : //github.com/facebook/docusaurus/issues/1699
* @ param { string } template
* /
2022-01-07 23:59:28 -05:00
async function generateTemplateExample ( template ) {
2020-11-16 10:20:16 -05:00
try {
console . log (
` generating ${ template } template for codesandbox in the examples folder... ` ,
) ;
2022-04-17 04:39:11 -04:00
// Run the docusaurus script to create the template in the examples folder
2021-08-06 13:11:36 -04:00
const command = template . endsWith ( '-typescript' )
2021-10-20 06:45:06 -04:00
? template . replace ( '-typescript' , ' -- --typescript' )
2021-08-06 13:11:36 -04:00
: template ;
2022-01-07 23:59:28 -05:00
shell . exec (
2022-04-17 04:39:11 -04:00
// We use the published init script on purpose, because the local init is
// too new and could generate upcoming/unavailable config options.
// Remember CodeSandbox templates will use the published version,
// not the repo version.
2021-10-07 10:06:42 -04:00
` npm init docusaurus@latest examples/ ${ template } ${ command } ` ,
2020-11-16 10:20:16 -05:00
) ;
2022-05-24 07:19:24 -04:00
const templatePackageJson =
await /** @type {Promise<import("../../packages/create-docusaurus/templates/classic/package.json") & { scripts: { [name: string]: string }; description: string }>} */ (
fs . readJSON ( ` examples/ ${ template } /package.json ` )
) ;
2020-11-16 10:20:16 -05:00
2022-04-17 04:39:11 -04:00
// Attach the dev script which would be used in code sandbox by default
2020-11-16 10:20:16 -05:00
templatePackageJson . scripts . dev = 'docusaurus start' ;
2022-04-17 04:39:11 -04:00
// These example projects are not meant to be published to npm
2021-01-20 07:29:45 -05:00
templatePackageJson . private = true ;
2022-01-30 21:31:24 -05:00
// Make sure package.json name is not "examples-classic". The package.json
// name appears in CodeSandbox UI so let's display a good name!
// Unfortunately we can't use uppercase or spaces... See also
// https://github.com/codesandbox/codesandbox-client/pull/5136#issuecomment-763521662
2021-01-20 07:29:45 -05:00
templatePackageJson . name =
template === 'classic' ? 'docusaurus' : ` docusaurus- ${ template } ` ;
templatePackageJson . description =
template === 'classic'
? 'Docusaurus example project'
: ` Docusaurus example project ( ${ template } template) ` ;
2022-01-07 23:59:28 -05:00
await fs . writeFile (
2020-11-16 10:20:16 -05:00
` ./examples/ ${ template } /package.json ` ,
2021-12-24 09:11:35 -05:00
` ${ JSON . stringify ( templatePackageJson , null , 2 ) } \n ` ,
2020-11-16 10:20:16 -05:00
) ;
2022-04-17 04:39:11 -04:00
// Create sandbox/stackblitz config file at the root of template
2022-01-13 01:36:53 -05:00
const codeSandboxConfig = {
2020-11-16 10:20:16 -05:00
infiniteLoopProtection : true ,
hardReloadOnChange : true ,
view : 'browser' ,
2021-01-19 10:13:14 -05:00
template : 'docusaurus' ,
2021-04-07 12:28:06 -04:00
node : '14' ,
container : {
node : '14' ,
} ,
2020-11-16 10:20:16 -05:00
} ;
2022-01-07 23:59:28 -05:00
await fs . writeFile (
2020-11-16 10:20:16 -05:00
` ./examples/ ${ template } /sandbox.config.json ` ,
2022-01-13 01:36:53 -05:00
` ${ JSON . stringify ( codeSandboxConfig , null , 2 ) } \n ` ,
2021-07-28 13:27:58 -04:00
) ;
const stackBlitzConfig = {
installDependencies : true ,
startCommand : 'npm start' ,
} ;
2022-01-07 23:59:28 -05:00
await fs . writeFile (
2021-07-28 13:27:58 -04:00
` ./examples/ ${ template } /.stackblitzrc ` ,
2021-12-24 09:11:35 -05:00
` ${ JSON . stringify ( stackBlitzConfig , null , 2 ) } \n ` ,
2020-11-16 10:20:16 -05:00
) ;
console . log ( ` Generated example for template ${ template } ` ) ;
2022-02-25 02:07:13 -05:00
} catch ( err ) {
2020-11-16 10:20:16 -05:00
console . error ( ` Failed to generated example for template ${ template } ` ) ;
2022-02-25 02:07:13 -05:00
throw err ;
2020-11-16 10:20:16 -05:00
}
}
2022-01-30 21:31:24 -05:00
/ * *
* Starters are repositories / branches that only contains a newly initialized
* Docusaurus site . Those are useful for users to inspect ( may be more
* convenient than " examples / classic ) Also some tools like Netlify deploy button
* currently require using the main branch of a dedicated repo .
* See https : //github.com/jamstack/jamstack.org/pull/609
* Button visible here : https : //jamstack.org/generators/
2021-07-22 11:55:04 -04:00
* /
function updateStarters ( ) {
2022-05-23 03:40:53 -04:00
/ * *
* @ param { Object } param0
* @ param { string } param0 . subfolder
* @ param { string } param0 . remote
* @ param { string } param0 . remoteBranch
* /
2021-09-03 10:54:06 -04:00
function forcePushGitSubtree ( { subfolder , remote , remoteBranch } ) {
console . log ( '' ) ;
// See https://stackoverflow.com/questions/33172857/how-do-i-force-a-subtree-push-to-overwrite-remote-changes
const command = ` git push ${ remote } \` git subtree split --prefix ${ subfolder } \` : ${ remoteBranch } --force ` ;
try {
console . log ( ` forcePushGitSubtree command: ${ command } ` ) ;
2022-01-07 23:59:28 -05:00
shell . exec ( command ) ;
2021-09-03 10:54:06 -04:00
console . log ( 'forcePushGitSubtree success!' ) ;
2022-02-25 02:07:13 -05:00
} catch ( err ) {
2021-09-03 10:54:06 -04:00
console . error (
` Can't force push to git subtree with command ' ${ command } ' ` ,
) ;
console . error ( ` If it's a permission problem, ask @slorber ` ) ;
2022-02-25 02:07:13 -05:00
console . error ( err ) ;
2021-09-03 10:54:06 -04:00
}
console . log ( '' ) ;
2021-07-22 11:55:04 -04:00
}
2021-09-03 10:54:06 -04:00
console . log ( '' ) ;
console . log ( 'Updating https://github.com/facebook/docusaurus/tree/starter' ) ;
forcePushGitSubtree ( {
subfolder : 'examples/classic' ,
remote : 'origin' ,
remoteBranch : 'starter' ,
} ) ;
console . log ( '' ) ;
console . log ( '' ) ;
// TODO replace by starter repo in Docusaurus-community org (if we get it)
console . log ( 'Updating https://github.com/slorber/docusaurus-starter' ) ;
forcePushGitSubtree ( {
subfolder : 'examples/classic' ,
remote : 'git@github.com:slorber/docusaurus-starter.git' ,
remoteBranch : 'main' ,
} ) ;
console . log ( '' ) ;
2021-07-22 11:55:04 -04:00
}
2022-01-07 23:59:28 -05:00
const branch = shell . exec ( 'git rev-parse --abbrev-ref HEAD' ) . stdout ;
if ( branch === 'main' ) {
throw new Error (
"Please don't generate Docusaurus examples from the main branch!\nWe are going to commit during this process!" ,
) ;
}
if ( shell . exec ( 'git diff --exit-code' ) . code !== 0 ) {
throw new Error (
'Please run the generate examples command with a clean Git state and no uncommitted local changes. git diff should display nothing!' ,
) ;
2021-07-28 13:27:58 -04:00
}
2022-01-07 23:59:28 -05:00
console . log ( `
# Generate examples start !
` );
2022-04-17 04:39:11 -04:00
// Delete the examples directories if they exist
2022-01-07 23:59:28 -05:00
console . log ( ` -------
# # Removing example folders ...
` );
await fs . rm ( './examples/classic' , { recursive : true , force : true } ) ;
await fs . rm ( './examples/classic-typescript' , { recursive : true , force : true } ) ;
await fs . rm ( './examples/facebook' , { recursive : true , force : true } ) ;
2022-04-17 04:39:11 -04:00
// Get the list of all available templates
2022-01-07 23:59:28 -05:00
console . log ( `
-- -- -- -
# # Generate example folders ...
` );
const excludes = [ 'README.md' , 'shared' ] ;
const templates = (
await fs . readdir ( './packages/create-docusaurus/templates' )
) . filter ( ( name ) => ! excludes . includes ( name ) ) ;
console . log ( ` Will generate examples for templates: ${ templates . join ( ',' ) } ` ) ;
for ( const template of templates ) {
await generateTemplateExample ( template ) ;
}
2022-01-13 01:36:53 -05:00
console . log ( 'Committing changes' ) ;
2022-01-07 23:59:28 -05:00
shell . exec ( 'git add examples' ) ;
shell . exec ( "git commit -am 'update examples' --allow-empty" ) ;
2022-04-17 04:39:11 -04:00
// Update starters
2022-01-07 23:59:28 -05:00
console . log ( `
-- -- -- -
# Updating starter repos and branches ...
It can take some time ... please wait until done ...
` );
updateStarters ( ) ;
console . log ( `
-- -- -- -
Generate examples end !
Don ' t forget to push and merge your pull request !
` );