11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
16.95k stars 491 forks source link

Add `page.filePathStem` variable for permalink usage #244

Closed zachleat closed 6 years ago

zachleat commented 6 years ago

While page.fileSlug is great for permalinks, when using the data cascade with permalinks it may be useful to reuse the full directory structure without the filename too.

/first/second/2018-08-02-mypost.md

fileSlug: mypost fileDir: first/second/

I wonder if page.originalPermalink would be useful too.

This feature would allow respecting directory structure with a directory data file setting a permalink higher in the directory structure, for example in first/first.11tydata.json.

zachleat commented 6 years ago

This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.

The enhancement backlog can be found here: https://github.com/11ty/eleventy/issues?utf8=%E2%9C%93&q=label%3Aneeds-votes+sort%3Areactions-%2B1-desc+

Don’t forget to upvote the top comment with πŸ‘!

zachleat commented 5 years ago

Rather than fileDir here, during implementation I thought it would be more useful to provide page.filePathStem. So, switching this up here. page.filePathStem provides the full input path to the file without the file extension.

This easily allows for /dir/dir2/myTemplate.11ty.js with a filePathStem of /dir/dir2/myTemplate to be used in a permalink (${page.filePathStem}.html) to output to /dir/dir2/myTemplate.html

zachleat commented 5 years ago

Docs at https://www.11ty.io/docs/data/#filepathstem (after deploy finishes)

zachleat commented 5 years ago

Some more background around this https://twitter.com/matthewcp/status/1166034748998922240

https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/

nhoizey commented 4 years ago

@zachleat I'm trying to use filePathStem but I'm not sure why I get an error.

Here's a very reduced test case:

mkdir filePathStemTest
cd filePathStemTest
mkdir folder
echo "---\npermalink: {{ page.filePathStem }}.html\n---\n\nhello" > ./folder/file.njk
npx @11ty/eleventy build

As a result, I get an error, which I'm not able to understand:

Problem writing Eleventy templates: (more in DEBUG output)
> can not read a block mapping entry; a multiline key may not be an implicit key at line 3, column 1:

    ^

`YAMLException` was thrown:
    YAMLException: can not read a block mapping entry; a multiline key may not be an implicit key at line 3, column 1:

        ^
        at generateError (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:167:10)
        at throwError (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:173:9)
        at readBlockMapping (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1073:9)
        at composeNode (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1359:12)
        at readDocument (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1519:3)
        at loadDocuments (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1575:5)
        at load (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1596:19)
        at Object.safeLoad (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1618:10)
        at module.exports (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/gray-matter/lib/parse.js:12:17)
        at parseMatter (/Users/nhoizey/.npm/_npx/24475/lib/node_modules/@11ty/eleventy/node_modules/gray-matter/index.js:109:17)
Processed 0 files in 0.17 seconds (v0.9.0)

With debug, it doesn't look like there are more informations:

  Eleventy:UserConfig Resetting EleventyConfig to initial values. +0ms
  Eleventy:Config Setting up global TemplateConfig. +0ms
  Eleventy:UserConfig Adding universal filter 'slug' +4ms
  Eleventy:UserConfig Adding universal filter 'url' +1ms
  Eleventy:TemplateConfig rootConfig { templateFormats: [ 'liquid',   'ejs', 'md',       'hbs', 'mustache', 'haml', 'pug',      'njk', 'html',     'jstl', '11ty.js' ], pathPrefix: '/', markdownTemplateEngine: 'liquid', htmlTemplateEngine: 'liquid', dataTemplateEngine: 'liquid', passthroughFileCopy: true, htmlOutputSuffix: '-o', jsDataFileSuffix: '.11tydata', keys: { package: 'pkg', layout: 'layout', permalink: 'permalink', permalinkRoot: 'permalinkBypassOutputDir', engineOverride: 'templateEngineOverride' }, dir: { input: '.', includes: '_includes', data: '_data', output: '_site' }, filters: {}, handlebarsHelpers: {}, nunjucksFilters: {} } +0ms
  Eleventy:TemplateConfig Merging config with /Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/.eleventy.js +3ms
  Eleventy:TemplateConfig Eleventy local project config file not found, skipping. +0ms
  Eleventy:TemplateConfig localConfig: { templateFormats: undefined, filters: {}, linters: {}, layoutAliases: {}, passthroughCopies: {}, liquidOptions: {}, liquidTags: {}, liquidFilters: { slug: [Function], url: [Function] }, liquidShortcodes: {}, liquidPairedShortcodes: {}, nunjucksFilters: { slug: [Function], url: [Function] }, nunjucksAsyncFilters: {}, nunjucksTags: {}, nunjucksShortcodes: {}, nunjucksPairedShortcodes: {}, handlebarsHelpers: { slug: [Function], url: [Function] }, handlebarsShortcodes: {}, handlebarsPairedShortcodes: {}, javascriptFunctions: { slug: [Function], url: [Function] }, pugOptions: {}, ejsOptions: {}, markdownHighlighter: null, libraryOverrides: {}, dynamicPermalinks: true, useGitIgnore: true, dataDeepMerge: false, experiments: Set {}, watchJavaScriptDependencies: true, browserSyncConfig: {}, frontMatterParsingOptions: undefined } +2ms
  Eleventy:TemplateConfig overrides: {} +1ms
  Eleventy:TemplateConfig Current configuration: { templateFormats: [ 'liquid',   'ejs', 'md',       'hbs', 'mustache', 'haml', 'pug',      'njk', 'html',     'jstl', '11ty.js' ], pathPrefix: '/', markdownTemplateEngine: 'liquid', htmlTemplateEngine: 'liquid', dataTemplateEngine: 'liquid', passthroughFileCopy: true, htmlOutputSuffix: '-o', jsDataFileSuffix: '.11tydata', keys: { package: 'pkg', layout: 'layout', permalink: 'permalink', permalinkRoot: 'permalinkBypassOutputDir', engineOverride: 'templateEngineOverride' }, dir: { input: '.', includes: '_includes', data: '_data', output: '_site' }, filters: {}, handlebarsHelpers: { slug: [Function], url: [Function] }, nunjucksFilters: { slug: [Function], url: [Function] }, linters: {}, layoutAliases: {}, passthroughCopies: {}, liquidOptions: {}, liquidTags: {}, liquidFilters: { slug: [Function], url: [Function] }, liquidShortcodes: {}, liquidPairedShortcodes: {}, nunjucksAsyncFilters: {}, nunjucksTags: {}, nunjucksShortcodes: {}, nunjucksPairedShortcodes: {}, handlebarsShortcodes: {}, handlebarsPairedShortcodes: {}, javascriptFunctions: { slug: [Function], url: [Function] }, pugOptions: {}, ejsOptions: {}, markdownHighlighter: null, libraryOverrides: {}, dynamicPermalinks: true, useGitIgnore: true, dataDeepMerge: false, experiments: Set {}, watchJavaScriptDependencies: true, browserSyncConfig: {}, frontMatterParsingOptions: undefined } +1ms
  Eleventy:CommandCheck command: eleventy   +0ms
  Eleventy:TemplatePassthroughManager Resetting counts to 0 +0ms
  Eleventy:EleventyFiles /Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/.gitignore,.gitignore ignoring: !./node_modules/** +0ms
  Eleventy:EleventyFiles /Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/.gitignore,.gitignore ignoring: !/Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/node_modules/** +0ms
  Eleventy:EleventyFiles /Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/.gitignore,.gitignore ignoring: !./node_modules/** +0ms
  Eleventy Directories:
  Eleventy Input: .
  Eleventy Data: _data
  Eleventy Includes: _includes
  Eleventy Layouts: undefined
  Eleventy Output: _site
  Eleventy Template Formats: liquid,ejs,md,hbs,mustache,haml,pug,njk,html,jstl,11ty.js +0ms
  Eleventy:TemplateData Could not find and/or require package.json for data preprocessing at '/Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/package.json' +0ms
  Eleventy:TemplateData Could not find and/or require package.json for data preprocessing at '/Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/package.json' +0ms
  Eleventy:EleventyFiles Searching for: [ './**/*.liquid', './**/*.ejs', './**/*.md', './**/*.hbs', './**/*.mustache', './**/*.haml', './**/*.pug', './**/*.njk', './**/*.html', './**/*.jstl', './**/*.11ty.js', '!./node_modules/**', '!/Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/node_modules/**', '!./node_modules/**', '!./_site/**', '!./_includes/**', '!./_data/**' ] +10ms
  Eleventy:TemplateWriter Found: [ './folder/file.njk' ] +0ms
  Eleventy:TemplatePassthroughManager TemplatePassthrough copy started. +16ms
  Eleventy:TemplatePassthroughManager `passthroughFileCopy` config paths: {} +0ms
  Eleventy:TemplatePassthroughManager `passthroughFileCopy` config normalized paths: [] +0ms
  Eleventy:TemplateData Using '.11tydata' to find data files. +15ms
  Eleventy:TemplateData getLocalDataPaths('./folder/file.njk'): [ './folder/file.11tydata.js', './folder/file.11tydata.json', './folder/file.json', './folder/folder.11tydata.js', './folder/folder.11tydata.json', './folder/folder.json' ] +0ms
  Eleventy:TemplatePassthroughManager TemplatePassthrough copy finished. Current count: 0 +2ms
  Eleventy:TemplateData Could not find and/or require package.json for data preprocessing at '/Users/nhoizey/Dropbox/Personnel/Devs/_bac_a_sable/filePathStemTest/package.json' +3ms
  Eleventy:EleventyErrorHandler Problem writing Eleventy templates: +0ms
  Eleventy:EleventyErrorHandler can not read a block mapping entry; a multiline key may not be an implicit key at line 3, column 1:
  Eleventy:EleventyErrorHandler
  Eleventy:EleventyErrorHandler     ^
  Eleventy:EleventyErrorHandler
  Eleventy:EleventyErrorHandler `YAMLException` was thrown: +1ms
  Eleventy:EleventyErrorHandler (error stack): YAMLException: can not read a block mapping entry; a multiline key may not be an implicit key at line 3, column 1:
  Eleventy:EleventyErrorHandler
  Eleventy:EleventyErrorHandler     ^
  Eleventy:EleventyErrorHandler     at generateError (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:167:10)
  Eleventy:EleventyErrorHandler     at throwError (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:173:9)
  Eleventy:EleventyErrorHandler     at readBlockMapping (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1073:9)
  Eleventy:EleventyErrorHandler     at composeNode (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1359:12)
  Eleventy:EleventyErrorHandler     at readDocument (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1519:3)
  Eleventy:EleventyErrorHandler     at loadDocuments (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1575:5)
  Eleventy:EleventyErrorHandler     at load (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1596:19)
  Eleventy:EleventyErrorHandler     at Object.safeLoad (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/js-yaml/lib/js-yaml/loader.js:1618:10)
  Eleventy:EleventyErrorHandler     at module.exports (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/gray-matter/lib/parse.js:12:17)
  Eleventy:EleventyErrorHandler     at parseMatter (/Users/nhoizey/.npm/_npx/25182/lib/node_modules/@11ty/eleventy/node_modules/gray-matter/index.js:109:17) +0ms
Processed 0 files in 0.19 seconds (v0.9.0)
  Eleventy Finished writing templates. +187ms
  Eleventy
  Eleventy Getting frustrated? Have a suggestion/feature request/feedback?
  Eleventy I want to hear it! Open an issue: https://github.com/11ty/eleventy/issues/new +0ms

Start time: (2019-11-14 20:54:20 UTC) [treshold=1%]
 #  module                                                     time  %
 1  ./TemplatePath (../../../.....venty/src/TemplatePath.js)   26ms  β–‡ 1%
 2  fast-glob (../../../../../....es/fast-glob/out/index.js)   27ms  β–‡ 1%
 3  detective-postcss (../../.....ive-postcss/dist/index.js)   26ms  β–‡ 1%
 4  typescript (../../../../../...escript/lib/typescript.js)  146ms  β–‡β–‡β–‡β–‡ 6%
 5  @typescript-eslint/typescri...ipt-estree/dist/parser.js)  186ms  β–‡β–‡β–‡β–‡ 7%
 6  detective-typescript (../.....ctive-typescript/index.js)  187ms  β–‡β–‡β–‡β–‡β–‡ 7%
 7  precinct (../../../../../.n...modules/precinct/index.js)  247ms  β–‡β–‡β–‡β–‡β–‡β–‡ 10%
 8  dependency-tree (../../../..../dependency-tree/index.js)  252ms  β–‡β–‡β–‡β–‡β–‡β–‡ 10%
 9  ./TemplateConfig (../../../...nty/src/TemplateConfig.js)  271ms  β–‡β–‡β–‡β–‡β–‡β–‡ 11%
10  ./Config (../../../../../.n...ty/eleventy/src/Config.js)  283ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 11%
11  ../EleventyExtensionMap (.....c/EleventyExtensionMap.js)  284ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 11%
12  ./Engines/TemplateEngine (....Engines/TemplateEngine.js)  284ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 11%
13  ./TemplateRender (../../../...nty/src/TemplateRender.js)  284ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 11%
14  ./TemplateData (../../../.....venty/src/TemplateData.js)  330ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 13%
15  ./Template (../../../../../.../eleventy/src/Template.js)   30ms  β–‡ 1%
16  ./TemplateWriter (../../../...nty/src/TemplateWriter.js)   54ms  β–‡β–‡ 2%
17  ./src/Eleventy (../../../...../eleventy/src/Eleventy.js)  411ms  β–‡β–‡β–‡β–‡β–‡β–‡β–‡β–‡β–‡ 16%
18  base (../../../../../.npm/_...ode_modules/base/index.js)   31ms  β–‡ 1%
19  snapdragon (../../../../../...dules/snapdragon/index.js)   46ms  β–‡ 2%
20  ./lib/braces (../../../../....ules/braces/lib/braces.js)   47ms  β–‡β–‡ 2%
21  braces (../../../../../.npm...e_modules/braces/index.js)   70ms  β–‡β–‡ 3%
22  micromatch (../../../../../...dules/micromatch/index.js)   89ms  β–‡β–‡ 3%
23  anymatch (../../../../../.n...modules/anymatch/index.js)   89ms  β–‡β–‡ 3%
24  node-pre-gyp (../../../../....e-gyp/lib/node-pre-gyp.js)   35ms  β–‡ 1%
25  fsevents (../../../../../.n...ules/fsevents/fsevents.js)   45ms  β–‡ 2%
26  ./lib/fsevents-handler (../...r/lib/fsevents-handler.js)   46ms  β–‡ 2%
27  chokidar (../../../../../.n...modules/chokidar/index.js)  146ms  β–‡β–‡β–‡β–‡ 6%
28  ./node-loaders (../../../.....jucks/src/node-loaders.js)  148ms  β–‡β–‡β–‡β–‡ 6%
29  ./loaders (../../../../../....s/nunjucks/src/loaders.js)  149ms  β–‡β–‡β–‡β–‡ 6%
30  ./src/environment (../../.....njucks/src/environment.js)  158ms  β–‡β–‡β–‡β–‡ 6%
31  nunjucks (../../../../../.n...modules/nunjucks/index.js)  160ms  β–‡β–‡β–‡β–‡ 6%
32  ./Nunjucks (../../../../../...y/src/Engines/Nunjucks.js)  160ms  β–‡β–‡β–‡β–‡ 6%
Total require(): 1716
Total time: 2.6s
zachleat commented 4 years ago

@nhoizey you kinda hit an edge case there. I’ve documented this https://www.11ty.io/docs/permalinks/#warning-about-yaml-objects and added it to common pitfalls, and also changed all the docs to use explicit strings on permalink to avoid this in the future!

In summary, put quotes around your permalink and it will work.

permalink: "{{ page.filePathStem }}.html"
nhoizey commented 4 years ago

@zachleat good to know, I don't have this issue anymore with quotes, indeed!

You say this variable "is useful if you’ve inherited a project that doesn’t use clean permalinks", but I think it's useful even from new project, for some pages that can be in the same folder hierarchy in src and dist, as I've been able to do here: https://github.com/nhoizey/nicolas-hoizey.com/commit/ac73dac926b009dc8850ea2f1b0dd0af2bc67137

zachleat commented 4 years ago

@nhoizey hm? not sure I understand what you mean. Folder hierarchy is preserved without using permalink?

nhoizey commented 4 years ago

@nhoizey hm? not sure I understand what you mean. Folder hierarchy is preserved without using permalink?

@zachleat yes, indeed.

(just saw your question, sorry for the laaaate answer… πŸ˜…)