From ca3f9baa7850a206a57481d481db70c309990823 Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 10:40:00 +1200 Subject: [PATCH 1/7] Add some basic build/output suggestions --- src/ssgs/astro.js | 29 +++++++++++++++++++++++++++++ src/ssgs/gatsby.js | 29 +++++++++++++++++++++++++++++ src/ssgs/hugo.js | 7 ++++++- src/ssgs/next-js.js | 22 ++++++++++++++++++++++ src/ssgs/nuxt-js.js | 29 +++++++++++++++++++++++++++++ src/ssgs/ssgs.js | 9 ++++++--- src/ssgs/sveltekit.js | 28 ++++++++++++++++++++++++++++ 7 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 src/ssgs/astro.js create mode 100644 src/ssgs/gatsby.js create mode 100644 src/ssgs/nuxt-js.js diff --git a/src/ssgs/astro.js b/src/ssgs/astro.js new file mode 100644 index 0000000..00103c6 --- /dev/null +++ b/src/ssgs/astro.js @@ -0,0 +1,29 @@ +import Ssg from './ssg.js'; + +export default class Astro extends Ssg { + constructor() { + super('astro'); + } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.push({ + value: 'npx astro build', + attribution: 'default for Astro sites' + }) + commands.output.push({ + value: 'dist', + attribution: 'default for Astro sites' + }) + + return commands; + } +} diff --git a/src/ssgs/gatsby.js b/src/ssgs/gatsby.js new file mode 100644 index 0000000..22c64c8 --- /dev/null +++ b/src/ssgs/gatsby.js @@ -0,0 +1,29 @@ +import Ssg from './ssg.js'; + +export default class Gatsby extends Ssg { + constructor() { + super('gatsby'); + } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.unshift({ + value: 'npx gatsby build', + attribution: 'default for Gatsby sites' + }); + commands.output.unshift({ + value: 'public', + attribution: 'default for Gatsby sites' + }); + + return commands; + } +} diff --git a/src/ssgs/hugo.js b/src/ssgs/hugo.js index 7bc5f39..cf5b3b1 100644 --- a/src/ssgs/hugo.js +++ b/src/ssgs/hugo.js @@ -225,8 +225,13 @@ export default class Hugo extends Ssg { async generateBuildCommands(filePaths, options) { const commands = await super.generateBuildCommands(filePaths, options); + commands.install.unshift({ + value: 'export NODE_PATH=`pwd`/node_modules:$NODE_PATH', + attribution: 'workaround for a Hugo issue ' // https://github.com/gohugoio/hugo/issues/9800 + }); + commands.build.unshift({ - value: 'hugo', + value: 'hugo -b /', attribution: 'most common for Hugo sites', }); commands.output.unshift({ diff --git a/src/ssgs/next-js.js b/src/ssgs/next-js.js index 48c3465..adab51a 100644 --- a/src/ssgs/next-js.js +++ b/src/ssgs/next-js.js @@ -20,4 +20,26 @@ export default class NextJs extends Ssg { 'public/', // static assets ]); } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.unshift({ + value: 'npx next build && npx next export', + attribution: 'most common for Next.js sites' + }); + commands.output.unshift({ + value: 'out', + attribution: 'default for Next.js sites' + }); + + return commands; + } } diff --git a/src/ssgs/nuxt-js.js b/src/ssgs/nuxt-js.js new file mode 100644 index 0000000..a73acc6 --- /dev/null +++ b/src/ssgs/nuxt-js.js @@ -0,0 +1,29 @@ +import Ssg from './ssg.js'; + +export default class NuxtJs extends Ssg { + constructor() { + super('nuxtjs'); + } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.push({ + value: 'npx nuxt generate', + attribution: 'default for Nuxt sites' + }); + commands.output.unshift({ + value: 'dist', + attribution: 'most common for Nuxt sites', + }); + + return commands; + } +} diff --git a/src/ssgs/ssgs.js b/src/ssgs/ssgs.js index 00c4d1c..b589b5c 100644 --- a/src/ssgs/ssgs.js +++ b/src/ssgs/ssgs.js @@ -6,6 +6,9 @@ import NextJs from './next-js.js'; import Ssg from './ssg.js'; import Sveltekit from './sveltekit.js'; import Static from './static.js'; +import Astro from './astro.js'; +import NuxtJs from './nuxt-js.js'; +import Gatsby from './gatsby.js'; /** @type {Record} */ export const ssgs = { @@ -13,15 +16,15 @@ export const ssgs = { jekyll: new Jekyll(), eleventy: new Eleventy(), nextjs: new NextJs(), - astro: new Ssg('astro'), + astro: new Astro(), sveltekit: new Sveltekit(), bridgetown: new Bridgetown(), lume: new Ssg('lume'), mkdocs: new Ssg('mkdocs'), docusaurus: new Ssg('docusaurus'), - gatsby: new Ssg('gatsby'), + gatsby: new Gatsby(), hexo: new Ssg('hexo'), - nuxtjs: new Ssg('nuxtjs'), + nuxtjs: new NuxtJs(), sphinx: new Ssg('sphinx'), static: new Static(), legacy: new Ssg('legacy'), diff --git a/src/ssgs/sveltekit.js b/src/ssgs/sveltekit.js index 578ee9b..6bed43b 100644 --- a/src/ssgs/sveltekit.js +++ b/src/ssgs/sveltekit.js @@ -1,3 +1,4 @@ +import { joinPaths } from '../utility.js'; import Ssg from './ssg.js'; export default class Sveltekit extends Ssg { @@ -24,4 +25,31 @@ export default class Sveltekit extends Ssg { 'static/', // static assets ]); } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + const viteConfigPath = joinPaths([options.source, 'vite.config.js']); + + if (filePaths.includes(viteConfigPath)) { + commands.build.push({ + value: 'npx vite build', + attribution: 'because of your `vite.config.js` file', + }) + } + + commands.output.push({ + value: 'build', + attribution: 'most common for SvelteKit sites', + }) + + + return commands; + } } From 282c64afce61eaef5f0d43de1ed46827d2f598db Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 10:40:07 +1200 Subject: [PATCH 2/7] Update snapshot --- .../jekyll/single-page-in-subfolder.toolproof.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/toolproof_tests/jekyll/single-page-in-subfolder.toolproof.yml b/toolproof_tests/jekyll/single-page-in-subfolder.toolproof.yml index d448d50..c6d94a9 100644 --- a/toolproof_tests/jekyll/single-page-in-subfolder.toolproof.yml +++ b/toolproof_tests/jekyll/single-page-in-subfolder.toolproof.yml @@ -26,6 +26,14 @@ steps: ╎ "gfm": false, ╎ "breaks": false, ╎ "typographer": false, + ╎ "attributes": true, + ╎ "attribute_elements": { + ╎ "inline": "right", + ╎ "block": "below", + ╎ "tr": "none", + ╎ "td": "none", + ╎ "li": "right-of-prefix" + ╎ }, ╎ "treat_indentation_as_code": true ╎ } ╎ } From 99a39fc5f3a3e3bb8efd24a514c0467c07980541 Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 13:37:05 +1200 Subject: [PATCH 3/7] More build suggestions and tests --- src/ssgs/bridgetown.js | 38 ++++++++++++++++++++ src/ssgs/jekyll.js | 7 ++++ src/ssgs/ssg.js | 69 +++++++++++++++++++++++++++++++++---- test/build-commands.test.js | 69 +++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 test/build-commands.test.js diff --git a/src/ssgs/bridgetown.js b/src/ssgs/bridgetown.js index b008c64..ee57c1f 100644 --- a/src/ssgs/bridgetown.js +++ b/src/ssgs/bridgetown.js @@ -1,3 +1,4 @@ +import { joinPaths } from '../utility.js'; import Ssg from './ssg.js'; export default class Bridgetown extends Ssg { @@ -12,4 +13,41 @@ export default class Bridgetown extends Ssg { templateExtensions() { return super.templateExtensions().concat(['.liquid']); } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + if (filePaths.includes(joinPaths([options.source, 'Gemfile']))) { + commands.install.unshift({ + value: 'bundle install', + attribution: 'because of your Gemfile', + }); + + if (options.source) { + commands.environment['BUNDLE_GEMFILE'] = { + value: joinPaths([options.source, 'Gemfile']), + attribution: 'because of your Gemfile', + }; + } + } + + commands.build.unshift({ + value: 'bin/bridgetown deploy', + attribution: 'most common for Bridgetown sites' + }) + + commands.output.unshift({ + value: 'output', + attribution: 'most common for Bridgetown sites' + }) + + return commands; + } } diff --git a/src/ssgs/jekyll.js b/src/ssgs/jekyll.js index 8136ca2..cbc70e0 100644 --- a/src/ssgs/jekyll.js +++ b/src/ssgs/jekyll.js @@ -346,6 +346,13 @@ export default class Jekyll extends Ssg { value: 'bundle exec jekyll build', attribution: 'because of your Gemfile', }); + + if (options.source) { + commands.environment['BUNDLE_GEMFILE'] = { + value: joinPaths([options.source, 'Gemfile']), + attribution: 'because of your Gemfile', + }; + } } else { commands.build.unshift({ value: 'jekyll build', diff --git a/src/ssgs/ssg.js b/src/ssgs/ssg.js index a595f74..fde13b7 100644 --- a/src/ssgs/ssg.js +++ b/src/ssgs/ssg.js @@ -444,16 +444,71 @@ export default class Ssg { }); try { - const raw = options.readFile ? await options.readFile(packageJsonPath) : undefined; - const parsed = raw ? JSON.parse(raw) : undefined; + if (options.readFile) { + const parsed = await parseDataFile(packageJsonPath, options.readFile); + if (parsed?.scripts?.build) { + commands.build.push({ + value: 'npm run build', + attribution: 'found in your `package.json` file', + }); + } + } + } catch (_e) {} + } - if (parsed?.scripts?.build) { - commands.build.push({ - value: 'npm run build', - attribution: 'found in your `package.json` file', + /** + * Check a value from a settings file and add to build commands. + * + * @param value {unknown} + * @param filename {string} + * @param type {keyof import('../types').BuildCommands} + */ + const validateAndAddCommandFromSettings = (value, filename, type) => { + if (value && typeof value === 'string') { + if (type === 'environment') { + commands[type].value = { + + value, + attribution: `found in your \`${filename}\` file`, + } + } else { + commands[type].push({ + value, + attribution: `found in your \`${filename}\` file`, }); } - } catch (_e) {} + } + } + + if (options.readFile) { + const forestrySettingsPath = '.forestry/settings.yml'; + if (filePaths.includes(forestrySettingsPath)) { + try { + const parsed = await parseDataFile(forestrySettingsPath, options.readFile); + validateAndAddCommandFromSettings(parsed?.build?.install_dependencies_command, forestrySettingsPath, 'install'); + } catch (_e) {} + } + + const netlifySettingsPath = 'netlify.toml'; + if (filePaths.includes(netlifySettingsPath)) { + // https://docs.netlify.com/configure-builds/file-based-configuration/ + try { + const parsed = await parseDataFile(netlifySettingsPath, options.readFile); + validateAndAddCommandFromSettings(parsed?.build?.command, netlifySettingsPath, 'build'); + validateAndAddCommandFromSettings(parsed?.build?.publish, netlifySettingsPath, 'output'); + } catch (_e) {} + } + + const vercelSettingsPath = 'vercel.json'; + if (filePaths.includes(vercelSettingsPath)) { + // https://vercel.com/docs/projects/project-configuration + try { + const parsed = await parseDataFile(vercelSettingsPath, options.readFile); + validateAndAddCommandFromSettings(parsed?.installCommand, vercelSettingsPath, 'install'); + validateAndAddCommandFromSettings(parsed?.buildCommand, vercelSettingsPath, 'build'); + validateAndAddCommandFromSettings(parsed?.outputDirectory, vercelSettingsPath, 'output'); + } catch (_e) {} + } } return commands; diff --git a/test/build-commands.test.js b/test/build-commands.test.js new file mode 100644 index 0000000..b73a58b --- /dev/null +++ b/test/build-commands.test.js @@ -0,0 +1,69 @@ +import test from 'ava'; +import Ssg from '../src/ssgs/ssg.js'; + +const readFileMock = async (path) => { + if (path.endsWith('package.json')) { + return `{ "scripts": { "build": "webpack" } }`; + } + if (path.endsWith('.forestry/settings.yml')) { + return `build:\n install_dependencies_command: npm i` + } + if (path.endsWith('netlify.toml')) { + return `[build]\npublish = "out"\ncommand = "webpack"` + } + if (path.endsWith('vercel.json')) { + return `{ + "buildCommand": "webpack", + "installCommand": "npm i", + "outputDirectory": "out" + }`; + } + + return ''; +}; + +test('Look at package.json', async (t) => { + const ssg = new Ssg(); + const filePaths = ['package.json']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.install?.[0]?.value, 'npm i'); + t.is(buildCommands?.build?.[0]?.value, 'npm run build'); + t.is(buildCommands?.preserved?.[0]?.value, 'node_modules/'); +}); + +test('Read forestry settings', async (t) => { + const ssg = new Ssg(); + const filePaths = ['.forestry/settings.yml']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.install?.[0]?.value, 'npm i'); +}); + +test('Read netlify settings', async (t) => { + const ssg = new Ssg(); + const filePaths = ['netlify.toml']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.build?.[0]?.value, 'webpack'); + t.is(buildCommands?.output?.[0]?.value, 'out'); +}); + +test('Read vercel settings', async (t) => { + const ssg = new Ssg(); + const filePaths = ['vercel.json']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.install?.[0]?.value, 'npm i'); + t.is(buildCommands?.build?.[0]?.value, 'webpack'); + t.is(buildCommands?.output?.[0]?.value, 'out'); +}); + +test('Avoid misconfigurations in settings files', async (t) => { + const ssg = new Ssg(); + const readWeirdFile = () => `{ + "buildCommand": ["webpack"], + "installCommand": true, + "outputDirectory": 5 + }`; + const buildCommands = await ssg.generateBuildCommands(['vercel.json'], {readFile: readWeirdFile}) + t.falsy(buildCommands?.install?.length); + t.falsy(buildCommands?.build?.length); + t.falsy(buildCommands?.output?.length); +}) From 1dd03760c4b14f2c66e0d77bfe276a29be96c389 Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 14:51:16 +1200 Subject: [PATCH 4/7] Potentially suggest yarn install --- src/ssgs/hugo.js | 2 +- src/ssgs/ssg.js | 16 ++++++++++++---- test/build-commands.test.js | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/ssgs/hugo.js b/src/ssgs/hugo.js index cf5b3b1..e0999a0 100644 --- a/src/ssgs/hugo.js +++ b/src/ssgs/hugo.js @@ -227,7 +227,7 @@ export default class Hugo extends Ssg { commands.install.unshift({ value: 'export NODE_PATH=`pwd`/node_modules:$NODE_PATH', - attribution: 'workaround for a Hugo issue ' // https://github.com/gohugoio/hugo/issues/9800 + attribution: 'workaround for a Hugo issue' // https://github.com/gohugoio/hugo/issues/9800 }); commands.build.unshift({ diff --git a/src/ssgs/ssg.js b/src/ssgs/ssg.js index fde13b7..f0deb62 100644 --- a/src/ssgs/ssg.js +++ b/src/ssgs/ssg.js @@ -433,10 +433,18 @@ export default class Ssg { const packageJsonPath = joinPaths([options.source, 'package.json']); if (filePaths.includes(packageJsonPath)) { - commands.install.push({ - value: 'npm i', - attribution: 'because of your `package.json` file', - }); + const useYarn = filePaths.includes(joinPaths([options.source, 'yarn.lock'])) && !filePaths.includes(joinPaths([options.source, 'package-lock.json'])); + if (useYarn) { + commands.install.push({ + value: 'yarn', + attribution: 'because of your `yarn.lock` file', + }); + } else { + commands.install.push({ + value: 'npm i', + attribution: 'because of your `package.json` file', + }); + } commands.preserved.push({ value: 'node_modules/', diff --git a/test/build-commands.test.js b/test/build-commands.test.js index b73a58b..b09aff8 100644 --- a/test/build-commands.test.js +++ b/test/build-commands.test.js @@ -31,6 +31,20 @@ test('Look at package.json', async (t) => { t.is(buildCommands?.preserved?.[0]?.value, 'node_modules/'); }); +test('Look at yarn.lock', async (t) => { + const ssg = new Ssg(); + const filePaths = ['package.json', 'yarn.lock']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.install?.[0]?.value, 'yarn'); +}); + +test('Don\'t prefer yarn over npm', async (t) => { + const ssg = new Ssg(); + const filePaths = ['package.json', 'package-lock.json', 'yarn.lock']; + const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + t.is(buildCommands?.install?.[0]?.value, 'npm i'); +}); + test('Read forestry settings', async (t) => { const ssg = new Ssg(); const filePaths = ['.forestry/settings.yml']; @@ -66,4 +80,11 @@ test('Avoid misconfigurations in settings files', async (t) => { t.falsy(buildCommands?.install?.length); t.falsy(buildCommands?.build?.length); t.falsy(buildCommands?.output?.length); -}) +}); + +// test('Recommend .sh files to build or install', async (t) => { +// const files = ['build.sh', 'install.sh']; +// const buildCommands = await new Ssg().generateBuildCommands(files) +// t.is(buildCommands?.build?.[0]?.value, 'sh build.sh'); +// t.is(buildCommands?.install?.[0]?.value, 'sh install.sh'); +// }); From 6970bbdb697d29047288c1c7effe388534b50259 Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 14:57:28 +1200 Subject: [PATCH 5/7] Remove comment (do we want that?) --- test/build-commands.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/build-commands.test.js b/test/build-commands.test.js index b09aff8..f69927f 100644 --- a/test/build-commands.test.js +++ b/test/build-commands.test.js @@ -81,10 +81,3 @@ test('Avoid misconfigurations in settings files', async (t) => { t.falsy(buildCommands?.build?.length); t.falsy(buildCommands?.output?.length); }); - -// test('Recommend .sh files to build or install', async (t) => { -// const files = ['build.sh', 'install.sh']; -// const buildCommands = await new Ssg().generateBuildCommands(files) -// t.is(buildCommands?.build?.[0]?.value, 'sh build.sh'); -// t.is(buildCommands?.install?.[0]?.value, 'sh install.sh'); -// }); From 9ebf8078225b941c6e3da03163ccbc1ecf97284d Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 15:22:46 +1200 Subject: [PATCH 6/7] Suggestions for MkDocs and Lume --- src/ssgs/lume.js | 29 +++++++++++++++++++++++++++++ src/ssgs/mkdocs.js | 29 +++++++++++++++++++++++++++++ src/ssgs/ssgs.js | 6 ++++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/ssgs/lume.js create mode 100644 src/ssgs/mkdocs.js diff --git a/src/ssgs/lume.js b/src/ssgs/lume.js new file mode 100644 index 0000000..f818a8f --- /dev/null +++ b/src/ssgs/lume.js @@ -0,0 +1,29 @@ +import Ssg from './ssg.js'; + +export default class Lume extends Ssg { + constructor() { + super('lume'); + } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.push({ + value: 'deno task lume', + attribution: 'default for Lume sites' + }); + commands.output.unshift({ + value: '_site', + attribution: 'most common for Lume sites', + }); + + return commands; + } +} diff --git a/src/ssgs/mkdocs.js b/src/ssgs/mkdocs.js new file mode 100644 index 0000000..d39491e --- /dev/null +++ b/src/ssgs/mkdocs.js @@ -0,0 +1,29 @@ +import Ssg from './ssg.js'; + +export default class MkDocs extends Ssg { + constructor() { + super('mkdocs'); + } + + /** + * Generates a list of build suggestions. + * + * @param filePaths {string[]} List of input file paths. + * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} + * @returns {Promise} + */ + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); + + commands.build.push({ + value: 'npx mkdocs build', + attribution: 'default for MkDocs sites' + }); + commands.output.unshift({ + value: 'site', + attribution: 'most common for MkDocs sites', + }); + + return commands; + } +} diff --git a/src/ssgs/ssgs.js b/src/ssgs/ssgs.js index b589b5c..ace22e6 100644 --- a/src/ssgs/ssgs.js +++ b/src/ssgs/ssgs.js @@ -9,6 +9,8 @@ import Static from './static.js'; import Astro from './astro.js'; import NuxtJs from './nuxt-js.js'; import Gatsby from './gatsby.js'; +import MkDocs from './mkdocs.js'; +import Lume from './lume.js'; /** @type {Record} */ export const ssgs = { @@ -19,8 +21,8 @@ export const ssgs = { astro: new Astro(), sveltekit: new Sveltekit(), bridgetown: new Bridgetown(), - lume: new Ssg('lume'), - mkdocs: new Ssg('mkdocs'), + lume: new Lume(), + mkdocs: new MkDocs(), docusaurus: new Ssg('docusaurus'), gatsby: new Gatsby(), hexo: new Ssg('hexo'), From 67799888cef86783b31c16054bee20e0a7a00656 Mon Sep 17 00:00:00 2001 From: Ryan Collins Date: Wed, 4 Sep 2024 15:32:52 +1200 Subject: [PATCH 7/7] Check bridgetown script and run fix:format --- src/defaults.js | 30 ++-- src/ssgs/astro.js | 10 +- src/ssgs/bridgetown.js | 16 +- src/ssgs/gatsby.js | 26 ++-- src/ssgs/hugo.js | 7 +- src/ssgs/jekyll.js | 1 - src/ssgs/lume.js | 6 +- src/ssgs/mkdocs.js | 6 +- src/ssgs/next-js.js | 4 +- src/ssgs/nuxt-js.js | 6 +- src/ssgs/ssg.js | 21 ++- src/ssgs/sveltekit.js | 11 +- test/build-commands.test.js | 28 ++-- test/markdown.test.js | 286 ++++++++++++++++++------------------ 14 files changed, 232 insertions(+), 226 deletions(-) diff --git a/src/defaults.js b/src/defaults.js index 83eda22..0c1f4d8 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -1,20 +1,20 @@ /** @type {import('@cloudcannon/configuration-types').MarkdownAttributeElementOptions} */ export const commonmarkAttributeElementOptions = { - inline: 'none', - block: 'space right', - img: 'right', - ul: 'below', - ol: 'below', - li: 'space right', - table: 'newline below', - blockquote: 'below', -} + inline: 'none', + block: 'space right', + img: 'right', + ul: 'below', + ol: 'below', + li: 'space right', + table: 'newline below', + blockquote: 'below', +}; /** @type {import('@cloudcannon/configuration-types').MarkdownAttributeElementOptions} */ export const kramdownAttributeElementOptions = { - inline: 'right', - block: 'below', - tr: 'none', - td: 'none', - li: 'right-of-prefix', -} \ No newline at end of file + inline: 'right', + block: 'below', + tr: 'none', + td: 'none', + li: 'right-of-prefix', +}; diff --git a/src/ssgs/astro.js b/src/ssgs/astro.js index 00103c6..94a9507 100644 --- a/src/ssgs/astro.js +++ b/src/ssgs/astro.js @@ -5,7 +5,7 @@ export default class Astro extends Ssg { super('astro'); } - /** + /** * Generates a list of build suggestions. * * @param filePaths {string[]} List of input file paths. @@ -17,12 +17,12 @@ export default class Astro extends Ssg { commands.build.push({ value: 'npx astro build', - attribution: 'default for Astro sites' - }) + attribution: 'default for Astro sites', + }); commands.output.push({ value: 'dist', - attribution: 'default for Astro sites' - }) + attribution: 'default for Astro sites', + }); return commands; } diff --git a/src/ssgs/bridgetown.js b/src/ssgs/bridgetown.js index ee57c1f..1f87e29 100644 --- a/src/ssgs/bridgetown.js +++ b/src/ssgs/bridgetown.js @@ -38,15 +38,17 @@ export default class Bridgetown extends Ssg { } } - commands.build.unshift({ - value: 'bin/bridgetown deploy', - attribution: 'most common for Bridgetown sites' - }) - + if (filePaths.includes('bin/bridgetown')) { + commands.build.unshift({ + value: 'bin/bridgetown deploy', + attribution: 'most common for Bridgetown sites', + }); + } + commands.output.unshift({ value: 'output', - attribution: 'most common for Bridgetown sites' - }) + attribution: 'most common for Bridgetown sites', + }); return commands; } diff --git a/src/ssgs/gatsby.js b/src/ssgs/gatsby.js index 22c64c8..e1e19a3 100644 --- a/src/ssgs/gatsby.js +++ b/src/ssgs/gatsby.js @@ -5,25 +5,25 @@ export default class Gatsby extends Ssg { super('gatsby'); } - /** + /** * Generates a list of build suggestions. * * @param filePaths {string[]} List of input file paths. * @param options {{ config?: Record; source?: string; readFile?: (path: string) => Promise; }} * @returns {Promise} */ - async generateBuildCommands(filePaths, options) { - const commands = await super.generateBuildCommands(filePaths, options); + async generateBuildCommands(filePaths, options) { + const commands = await super.generateBuildCommands(filePaths, options); - commands.build.unshift({ - value: 'npx gatsby build', - attribution: 'default for Gatsby sites' - }); - commands.output.unshift({ - value: 'public', - attribution: 'default for Gatsby sites' - }); + commands.build.unshift({ + value: 'npx gatsby build', + attribution: 'default for Gatsby sites', + }); + commands.output.unshift({ + value: 'public', + attribution: 'default for Gatsby sites', + }); - return commands; - } + return commands; + } } diff --git a/src/ssgs/hugo.js b/src/ssgs/hugo.js index e0999a0..7b502e3 100644 --- a/src/ssgs/hugo.js +++ b/src/ssgs/hugo.js @@ -196,14 +196,15 @@ export default class Hugo extends Ssg { headingTags.forEach((tag) => { attribute_elements[tag] = !!parser?.attribute?.title ? 'space right' : 'none'; }); - + /** @type {(keyof HTMLElementTagNameMap)[]} */ const otherTags = ['blockquote', 'hr', 'ol', 'ul', 'p', 'table']; otherTags.forEach((tag) => { attribute_elements[tag] = !!parser?.attribute?.block ? 'below' : 'none'; }); - const imgAttrsAllowed = !!parser?.attribute?.block && parser?.wrapStandAloneImageWithinParagraph === false; + const imgAttrsAllowed = + !!parser?.attribute?.block && parser?.wrapStandAloneImageWithinParagraph === false; attribute_elements.img = imgAttrsAllowed ? 'below' : 'none'; options.attribute_elements = attribute_elements; @@ -227,7 +228,7 @@ export default class Hugo extends Ssg { commands.install.unshift({ value: 'export NODE_PATH=`pwd`/node_modules:$NODE_PATH', - attribution: 'workaround for a Hugo issue' // https://github.com/gohugoio/hugo/issues/9800 + attribution: 'workaround for a Hugo issue', // https://github.com/gohugoio/hugo/issues/9800 }); commands.build.unshift({ diff --git a/src/ssgs/jekyll.js b/src/ssgs/jekyll.js index cbc70e0..7b0af33 100644 --- a/src/ssgs/jekyll.js +++ b/src/ssgs/jekyll.js @@ -290,7 +290,6 @@ export default class Jekyll extends Ssg { options.attributes = true; options.attribute_elements = kramdownAttributeElementOptions; - } else if (config) { const commonmarkConfig = config?.['commonmark'] || {}; diff --git a/src/ssgs/lume.js b/src/ssgs/lume.js index f818a8f..ac7373c 100644 --- a/src/ssgs/lume.js +++ b/src/ssgs/lume.js @@ -5,7 +5,7 @@ export default class Lume extends Ssg { super('lume'); } - /** + /** * Generates a list of build suggestions. * * @param filePaths {string[]} List of input file paths. @@ -17,9 +17,9 @@ export default class Lume extends Ssg { commands.build.push({ value: 'deno task lume', - attribution: 'default for Lume sites' + attribution: 'default for Lume sites', }); - commands.output.unshift({ + commands.output.unshift({ value: '_site', attribution: 'most common for Lume sites', }); diff --git a/src/ssgs/mkdocs.js b/src/ssgs/mkdocs.js index d39491e..cf1f0a2 100644 --- a/src/ssgs/mkdocs.js +++ b/src/ssgs/mkdocs.js @@ -5,7 +5,7 @@ export default class MkDocs extends Ssg { super('mkdocs'); } - /** + /** * Generates a list of build suggestions. * * @param filePaths {string[]} List of input file paths. @@ -17,9 +17,9 @@ export default class MkDocs extends Ssg { commands.build.push({ value: 'npx mkdocs build', - attribution: 'default for MkDocs sites' + attribution: 'default for MkDocs sites', }); - commands.output.unshift({ + commands.output.unshift({ value: 'site', attribution: 'most common for MkDocs sites', }); diff --git a/src/ssgs/next-js.js b/src/ssgs/next-js.js index adab51a..7fbd784 100644 --- a/src/ssgs/next-js.js +++ b/src/ssgs/next-js.js @@ -33,11 +33,11 @@ export default class NextJs extends Ssg { commands.build.unshift({ value: 'npx next build && npx next export', - attribution: 'most common for Next.js sites' + attribution: 'most common for Next.js sites', }); commands.output.unshift({ value: 'out', - attribution: 'default for Next.js sites' + attribution: 'default for Next.js sites', }); return commands; diff --git a/src/ssgs/nuxt-js.js b/src/ssgs/nuxt-js.js index a73acc6..74ba430 100644 --- a/src/ssgs/nuxt-js.js +++ b/src/ssgs/nuxt-js.js @@ -5,7 +5,7 @@ export default class NuxtJs extends Ssg { super('nuxtjs'); } - /** + /** * Generates a list of build suggestions. * * @param filePaths {string[]} List of input file paths. @@ -17,9 +17,9 @@ export default class NuxtJs extends Ssg { commands.build.push({ value: 'npx nuxt generate', - attribution: 'default for Nuxt sites' + attribution: 'default for Nuxt sites', }); - commands.output.unshift({ + commands.output.unshift({ value: 'dist', attribution: 'most common for Nuxt sites', }); diff --git a/src/ssgs/ssg.js b/src/ssgs/ssg.js index f0deb62..558dcf0 100644 --- a/src/ssgs/ssg.js +++ b/src/ssgs/ssg.js @@ -433,7 +433,9 @@ export default class Ssg { const packageJsonPath = joinPaths([options.source, 'package.json']); if (filePaths.includes(packageJsonPath)) { - const useYarn = filePaths.includes(joinPaths([options.source, 'yarn.lock'])) && !filePaths.includes(joinPaths([options.source, 'package-lock.json'])); + const useYarn = + filePaths.includes(joinPaths([options.source, 'yarn.lock'])) && + !filePaths.includes(joinPaths([options.source, 'package-lock.json'])); if (useYarn) { commands.install.push({ value: 'yarn', @@ -475,10 +477,9 @@ export default class Ssg { if (value && typeof value === 'string') { if (type === 'environment') { commands[type].value = { - - value, - attribution: `found in your \`${filename}\` file`, - } + value, + attribution: `found in your \`${filename}\` file`, + }; } else { commands[type].push({ value, @@ -486,17 +487,21 @@ export default class Ssg { }); } } - } + }; if (options.readFile) { const forestrySettingsPath = '.forestry/settings.yml'; if (filePaths.includes(forestrySettingsPath)) { try { const parsed = await parseDataFile(forestrySettingsPath, options.readFile); - validateAndAddCommandFromSettings(parsed?.build?.install_dependencies_command, forestrySettingsPath, 'install'); + validateAndAddCommandFromSettings( + parsed?.build?.install_dependencies_command, + forestrySettingsPath, + 'install', + ); } catch (_e) {} } - + const netlifySettingsPath = 'netlify.toml'; if (filePaths.includes(netlifySettingsPath)) { // https://docs.netlify.com/configure-builds/file-based-configuration/ diff --git a/src/ssgs/sveltekit.js b/src/ssgs/sveltekit.js index 6bed43b..4ec6d2a 100644 --- a/src/ssgs/sveltekit.js +++ b/src/ssgs/sveltekit.js @@ -37,18 +37,17 @@ export default class Sveltekit extends Ssg { const commands = await super.generateBuildCommands(filePaths, options); const viteConfigPath = joinPaths([options.source, 'vite.config.js']); - if (filePaths.includes(viteConfigPath)) { + if (filePaths.includes(viteConfigPath)) { commands.build.push({ value: 'npx vite build', attribution: 'because of your `vite.config.js` file', - }) - } - + }); + } + commands.output.push({ value: 'build', attribution: 'most common for SvelteKit sites', - }) - + }); return commands; } diff --git a/test/build-commands.test.js b/test/build-commands.test.js index f69927f..4421d96 100644 --- a/test/build-commands.test.js +++ b/test/build-commands.test.js @@ -6,13 +6,13 @@ const readFileMock = async (path) => { return `{ "scripts": { "build": "webpack" } }`; } if (path.endsWith('.forestry/settings.yml')) { - return `build:\n install_dependencies_command: npm i` + return `build:\n install_dependencies_command: npm i`; } if (path.endsWith('netlify.toml')) { - return `[build]\npublish = "out"\ncommand = "webpack"` + return `[build]\npublish = "out"\ncommand = "webpack"`; } if (path.endsWith('vercel.json')) { - return `{ + return `{ "buildCommand": "webpack", "installCommand": "npm i", "outputDirectory": "out" @@ -25,7 +25,7 @@ const readFileMock = async (path) => { test('Look at package.json', async (t) => { const ssg = new Ssg(); const filePaths = ['package.json']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.install?.[0]?.value, 'npm i'); t.is(buildCommands?.build?.[0]?.value, 'npm run build'); t.is(buildCommands?.preserved?.[0]?.value, 'node_modules/'); @@ -34,28 +34,28 @@ test('Look at package.json', async (t) => { test('Look at yarn.lock', async (t) => { const ssg = new Ssg(); const filePaths = ['package.json', 'yarn.lock']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.install?.[0]?.value, 'yarn'); }); -test('Don\'t prefer yarn over npm', async (t) => { +test("Don't prefer yarn over npm", async (t) => { const ssg = new Ssg(); const filePaths = ['package.json', 'package-lock.json', 'yarn.lock']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.install?.[0]?.value, 'npm i'); }); test('Read forestry settings', async (t) => { const ssg = new Ssg(); const filePaths = ['.forestry/settings.yml']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.install?.[0]?.value, 'npm i'); }); test('Read netlify settings', async (t) => { const ssg = new Ssg(); const filePaths = ['netlify.toml']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.build?.[0]?.value, 'webpack'); t.is(buildCommands?.output?.[0]?.value, 'out'); }); @@ -63,7 +63,7 @@ test('Read netlify settings', async (t) => { test('Read vercel settings', async (t) => { const ssg = new Ssg(); const filePaths = ['vercel.json']; - const buildCommands = await ssg.generateBuildCommands(filePaths, {readFile: readFileMock}) + const buildCommands = await ssg.generateBuildCommands(filePaths, { readFile: readFileMock }); t.is(buildCommands?.install?.[0]?.value, 'npm i'); t.is(buildCommands?.build?.[0]?.value, 'webpack'); t.is(buildCommands?.output?.[0]?.value, 'out'); @@ -71,13 +71,15 @@ test('Read vercel settings', async (t) => { test('Avoid misconfigurations in settings files', async (t) => { const ssg = new Ssg(); - const readWeirdFile = () => `{ + const readWeirdFile = () => `{ "buildCommand": ["webpack"], "installCommand": true, "outputDirectory": 5 }`; - const buildCommands = await ssg.generateBuildCommands(['vercel.json'], {readFile: readWeirdFile}) + const buildCommands = await ssg.generateBuildCommands(['vercel.json'], { + readFile: readWeirdFile, + }); t.falsy(buildCommands?.install?.length); t.falsy(buildCommands?.build?.length); - t.falsy(buildCommands?.output?.length); + t.falsy(buildCommands?.output?.length); }); diff --git a/test/markdown.test.js b/test/markdown.test.js index 15cc8bd..ef0128d 100644 --- a/test/markdown.test.js +++ b/test/markdown.test.js @@ -4,8 +4,6 @@ import Hugo from '../src/ssgs/hugo.js'; import Jekyll from '../src/ssgs/jekyll.js'; import Ssg from '../src/ssgs/ssg.js'; - - test('Defaults to CommonMark', (t) => { t.deepEqual(new Ssg().generateMarkdown({}), { engine: 'commonmark', @@ -14,169 +12,169 @@ test('Defaults to CommonMark', (t) => { }); test('Respects Jekyll Kramdown options enabled', (t) => { - const markdown = new Jekyll().generateMarkdown({ - kramdown: { - input: 'GFM', - hard_wrap: true, - gfm_quirks: [], - auto_ids: true, - smart_quotes: 'lsquo,rsquo,ldquo,rdquo', - }, - }); - t.is(markdown.engine, 'kramdown'); - t.is(markdown.options.quotes, '‘’“”'); - t.true(markdown.options.breaks); - t.true(markdown.options.gfm); - t.true(markdown.options.heading_ids); - t.true(markdown.options.typographer); - t.true(markdown.options.treat_indentation_as_code); + const markdown = new Jekyll().generateMarkdown({ + kramdown: { + input: 'GFM', + hard_wrap: true, + gfm_quirks: [], + auto_ids: true, + smart_quotes: 'lsquo,rsquo,ldquo,rdquo', + }, + }); + t.is(markdown.engine, 'kramdown'); + t.is(markdown.options.quotes, '‘’“”'); + t.true(markdown.options.breaks); + t.true(markdown.options.gfm); + t.true(markdown.options.heading_ids); + t.true(markdown.options.typographer); + t.true(markdown.options.treat_indentation_as_code); }); test('Respects Jekyll Kramdown options disabled', (t) => { - const markdown = new Jekyll().generateMarkdown({ - kramdown: { - input: 'not_gfm', - hard_wrap: false, - gfm_quirks: ['no_auto_typographic'], - auto_ids: false, - }, - }); - t.is(markdown.engine, 'kramdown'); - t.false(markdown.options.breaks); - t.false(markdown.options.gfm); - t.false(markdown.options.heading_ids); - t.false(markdown.options.typographer); - t.true(markdown.options.treat_indentation_as_code); + const markdown = new Jekyll().generateMarkdown({ + kramdown: { + input: 'not_gfm', + hard_wrap: false, + gfm_quirks: ['no_auto_typographic'], + auto_ids: false, + }, + }); + t.is(markdown.engine, 'kramdown'); + t.false(markdown.options.breaks); + t.false(markdown.options.gfm); + t.false(markdown.options.heading_ids); + t.false(markdown.options.typographer); + t.true(markdown.options.treat_indentation_as_code); }); test('Respects Jekyll CommonMark options', (t) => { - const markdown = new Jekyll().generateMarkdown({ - markdown: 'CommonMark', - commonmark: { - options: ['HARDBREAKS', 'GFM_QUIRKS'], - extensions: ['strikethrough', 'table', 'autolink', 'superscript', 'header_ids'], - }, - }); - t.is(markdown.engine, 'commonmark'); - t.true(markdown.options.breaks); - t.true(markdown.options.gfm); - t.true(markdown.options.strikethrough); - t.true(markdown.options.superscript); - t.true(markdown.options.linkify); - t.true(markdown.options.heading_ids); - t.true(markdown.options.table); - t.true(markdown.options.treat_indentation_as_code); + const markdown = new Jekyll().generateMarkdown({ + markdown: 'CommonMark', + commonmark: { + options: ['HARDBREAKS', 'GFM_QUIRKS'], + extensions: ['strikethrough', 'table', 'autolink', 'superscript', 'header_ids'], + }, + }); + t.is(markdown.engine, 'commonmark'); + t.true(markdown.options.breaks); + t.true(markdown.options.gfm); + t.true(markdown.options.strikethrough); + t.true(markdown.options.superscript); + t.true(markdown.options.linkify); + t.true(markdown.options.heading_ids); + t.true(markdown.options.table); + t.true(markdown.options.treat_indentation_as_code); }); test('Respects Hugo options', (t) => { - const markdown = new Hugo().generateMarkdown({ - markup: { - goldmark: { - extensions: { - linkify: true, - strikethrough: true, - table: true, - extras: { - delete: { enable: true }, - subscript: { enable: true }, - superscript: { enable: true }, - }, - typographer: { - disable: false, - leftDoubleQuote: '“', - leftSingleQuote: '‘', - rightDoubleQuote: '”', - rightSingleQuote: '’', - }, - }, - parser: { - autoHeadingID: true, - attribute: { block: false, title: true }, - }, - renderer: { hardWraps: true, xhtml: true }, - }, - }, - }); - t.is(markdown.engine, 'commonmark'); - t.is(markdown.options.quotes, '‘’“”'); - t.true(markdown.options.attributes); - t.true(markdown.options.linkify); - t.true(markdown.options.strikethrough); - t.true(markdown.options.table); - t.true(markdown.options.treat_indentation_as_code); - t.true(markdown.options.typographer); - t.true(markdown.options.breaks); - t.true(markdown.options.gfm); - t.true(markdown.options.subscript); - t.true(markdown.options.superscript); - t.true(markdown.options.heading_ids); - t.true(markdown.options.xhtml); + const markdown = new Hugo().generateMarkdown({ + markup: { + goldmark: { + extensions: { + linkify: true, + strikethrough: true, + table: true, + extras: { + delete: { enable: true }, + subscript: { enable: true }, + superscript: { enable: true }, + }, + typographer: { + disable: false, + leftDoubleQuote: '“', + leftSingleQuote: '‘', + rightDoubleQuote: '”', + rightSingleQuote: '’', + }, + }, + parser: { + autoHeadingID: true, + attribute: { block: false, title: true }, + }, + renderer: { hardWraps: true, xhtml: true }, + }, + }, + }); + t.is(markdown.engine, 'commonmark'); + t.is(markdown.options.quotes, '‘’“”'); + t.true(markdown.options.attributes); + t.true(markdown.options.linkify); + t.true(markdown.options.strikethrough); + t.true(markdown.options.table); + t.true(markdown.options.treat_indentation_as_code); + t.true(markdown.options.typographer); + t.true(markdown.options.breaks); + t.true(markdown.options.gfm); + t.true(markdown.options.subscript); + t.true(markdown.options.superscript); + t.true(markdown.options.heading_ids); + t.true(markdown.options.xhtml); }); test('Respects Hugo options with attributes disabled', (t) => { - const noAttrConfig = new Hugo().generateMarkdown( - { "markup": { - "goldmark": { - "parser": { - "attribute": { "block": false, "title": false } - }, - } - }} - ); - t.false(noAttrConfig.options.attributes); - t.is(noAttrConfig.options.attribute_elements, undefined); + const noAttrConfig = new Hugo().generateMarkdown({ + markup: { + goldmark: { + parser: { + attribute: { block: false, title: false }, + }, + }, + }, + }); + t.false(noAttrConfig.options.attributes); + t.is(noAttrConfig.options.attribute_elements, undefined); }); test('Respects Hugo options with heading attributes enabled', (t) => { - const noAttrConfig = new Hugo().generateMarkdown( - { "markup": { - "goldmark": { - "parser": { - "attribute": { "block": false, "title": true }, - }, - } - }} - ); - t.true(noAttrConfig.options.attributes); - t.is(noAttrConfig.options.attribute_elements.h1, 'space right'); - t.is(noAttrConfig.options.attribute_elements.h6, 'space right'); - t.is(noAttrConfig.options.attribute_elements.blockquote, 'none'); - t.is(noAttrConfig.options.attribute_elements.table, 'none'); + const noAttrConfig = new Hugo().generateMarkdown({ + markup: { + goldmark: { + parser: { + attribute: { block: false, title: true }, + }, + }, + }, + }); + t.true(noAttrConfig.options.attributes); + t.is(noAttrConfig.options.attribute_elements.h1, 'space right'); + t.is(noAttrConfig.options.attribute_elements.h6, 'space right'); + t.is(noAttrConfig.options.attribute_elements.blockquote, 'none'); + t.is(noAttrConfig.options.attribute_elements.table, 'none'); }); test('Respects Hugo options with block attributes enabled', (t) => { - const noAttrConfig = new Hugo().generateMarkdown( - { "markup": { - "goldmark": { - "parser": { - "attribute": { "block": true, "title": false }, - }, - } - }} - ); - t.true(noAttrConfig.options.attributes); - t.is(noAttrConfig.options.attribute_elements.h1, 'none'); - t.is(noAttrConfig.options.attribute_elements.img, 'none'); - t.is(noAttrConfig.options.attribute_elements.blockquote, 'below'); - t.is(noAttrConfig.options.attribute_elements.ul, 'below'); - t.is(noAttrConfig.options.attribute_elements.ol, 'below'); - t.is(noAttrConfig.options.attribute_elements.table, 'below'); - t.is(noAttrConfig.options.attribute_elements.p, 'below'); + const noAttrConfig = new Hugo().generateMarkdown({ + markup: { + goldmark: { + parser: { + attribute: { block: true, title: false }, + }, + }, + }, + }); + t.true(noAttrConfig.options.attributes); + t.is(noAttrConfig.options.attribute_elements.h1, 'none'); + t.is(noAttrConfig.options.attribute_elements.img, 'none'); + t.is(noAttrConfig.options.attribute_elements.blockquote, 'below'); + t.is(noAttrConfig.options.attribute_elements.ul, 'below'); + t.is(noAttrConfig.options.attribute_elements.ol, 'below'); + t.is(noAttrConfig.options.attribute_elements.table, 'below'); + t.is(noAttrConfig.options.attribute_elements.p, 'below'); }); test('Respects Hugo options to enable attributes on standalone image', (t) => { - const noAttrConfig = new Hugo().generateMarkdown( - { "markup": { - "goldmark": { - "parser": { - "attribute": { "block": true }, - "wrapStandAloneImageWithinParagraph": false - }, - } - }} - ); - t.true(noAttrConfig.options.attributes); - t.is(noAttrConfig.options.attribute_elements.img, 'below'); + const noAttrConfig = new Hugo().generateMarkdown({ + markup: { + goldmark: { + parser: { + attribute: { block: true }, + wrapStandAloneImageWithinParagraph: false, + }, + }, + }, + }); + t.true(noAttrConfig.options.attributes); + t.is(noAttrConfig.options.attribute_elements.img, 'below'); }); test('Has good 11ty defaults', (t) => {