eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Is there an attribute for a collection item's generated HTML for one or more njk layouts?

Open stevenmilstein opened this issue 4 years ago • 7 comments
trafficstars

Based on https://www.11ty.dev/docs/layout-chaining/. If I understand correctly:

  1. Markdown has "content"
  2. It gets rendered in the markdown's layout.
  3. If that layout is chained then its content is finally rendered in the last one in the chain.

Example

my-markdown.md

---
layout: layouts/myLayout1.njk
title: My Markdown
---

# Hello from {{title}}

layouts/myLayout1.njk

Note: This layout adds it's Global Data to its own content

---
layout: layouts/myLayout2.njk
title: My Layout 1
---

<h2> {{ title }}  in Layout 1</h2>

{{ content | safe }}

<h3>My Data</h3>
<pre>
{
    myData.myKey: {{ myData.myKey }}
}
</pre>

layouts/myLayout2.njk

---
title: My Layout 2
---

<h3> {{ title }} in Layout 2</h3>

{{ content | safe }} 

Generated HTML


<h3> My Markdown in Layout 2</h3>

<h2> My Markdown  in Layout 1</h2>

<h1>Hello from My Markdown</h1>

<h4>My Data</h4>
<pre>
 {
  myData.myKey: My Value
 }
</pre>

Everything works as designed.

my-markdown.md console.log

{
  template: Template {
    inputPath: './src/ocas/my-markdown.md',
    inputDir: './src',
    parsed: {
      root: '',
      dir: './src/ocas',
      base: 'my-markdown.md',
      ext: '.md',
      name: 'my-markdown',
      extname: '.md',
      basename: 'my-markdown.md',
      dirname: './src/ocas',
      stem: 'my-markdown',
      path: './src/ocas/my-markdown.md',
      absolute: [Getter/Setter],
      isAbsolute: [Getter/Setter]
    },
    extraOutputSubdirectory: '',
    outputDir: './_site',
    _extensionMap: EleventyExtensionMap {
      formatKeys: [Array],
      unfilteredFormatKeys: [Array],
      _extensionToKeyMap: [Object],
      validTemplateLanguageKeys: [Array],
      passthroughCopyKeys: [],
      configOverride: [Object],
      _engineManager: [TemplateEngineManager]
    },
    linters: [],
    transforms: [],
    plugins: {},
    templateData: TemplateData {
      config: [Object],
      dataTemplateEngine: 'liquid',
      inputDirNeedsCheck: true,
      inputDir: './src',
      dataDir: 'src/_data',
      rawImports: [Object],
      globalData: [Object],
      _extensionMap: [EleventyExtensionMap],
      pathCache: [Array]
    },
    paginationData: {},
    isVerbose: true,
    isDryRun: false,
    writeCount: 0,
    skippedCount: 0,
    wrapWithLayouts: true,
    fileSlug: TemplateFileSlug {
      inputPath: 'ocas/my-markdown.md',
      cleanInputPath: 'ocas/my-markdown.md',
      dirs: [Array],
      parsed: [Object],
      filenameNoExt: 'my-markdown'
    },
    fileSlugStr: 'my-markdown',
    filePathStem: '/ocas/my-markdown',
    _templateRender: TemplateRender {
      engineNameOrPath: './src/ocas/my-markdown.md',
      inputDir: './src',
      _config: [Object],
      includesDir: 'src/_includes',
      parseMarkdownWith: 'njk',
      parseHtmlWith: 'liquid',
      _extensionMap: [EleventyExtensionMap],
      _engineName: 'md',
      _engine: [Markdown],
      useMarkdown: true
    },
    inputContent: '---\n' +
      'layout: layouts/myLayout1.njk\n' +
      'title: My Markdown\n' +
      '---\n' +
      '\n' +
      '# Hello from {{title}}\n',
    _config: {
      templateFormats: [Array],
      pathPrefix: '/',
      markdownTemplateEngine: 'njk',
      htmlTemplateEngine: 'liquid',
      dataTemplateEngine: 'liquid',
      passthroughFileCopy: true,
      htmlOutputSuffix: '-o',
      jsDataFileSuffix: '.11tydata',
      keys: [Object],
      dir: [Object],
      filters: {},
      handlebarsHelpers: [Object],
      nunjucksFilters: [Object],
      linters: {},
      layoutAliases: {},
      passthroughCopies: [Object],
      liquidOptions: {},
      liquidTags: {},
      liquidFilters: [Object],
      liquidShortcodes: [Object],
      liquidPairedShortcodes: [Object],
      nunjucksAsyncFilters: [Object],
      nunjucksTags: {},
      nunjucksAsyncShortcodes: [Object],
      nunjucksShortcodes: [Object],
      nunjucksAsyncPairedShortcodes: [Object],
      nunjucksPairedShortcodes: [Object],
      handlebarsShortcodes: [Object],
      handlebarsPairedShortcodes: [Object],
      javascriptFunctions: [Object],
      pugOptions: {},
      ejsOptions: {},
      markdownHighlighter: null,
      libraryOverrides: {},
      dynamicPermalinks: true,
      useGitIgnore: true,
      dataDeepMerge: true,
      watchJavaScriptDependencies: true,
      additionalWatchTargets: [],
      browserSyncConfig: {},
      chokidarConfig: {},
      watchThrottleWaitTime: 0,
      frontMatterParsingOptions: undefined,
      dataExtensions: Map {},
      extensionMap: Set {},
      quietMode: false,
      events: [EventEmitter],
      inputDir: './src'
    },
    frontMatter: {
      content: '\n# Hello from {{title}}\n',
      data: [Object],
      isEmpty: false,
      excerpt: ''
    },
    _layoutKey: 'layouts/myLayout1.njk',
    _layout: TemplateLayout {
      inputPath: './src/_includes/layouts/myLayout1.njk',
      inputDir: './src',
      _extensionMap: [EleventyExtensionMap],
      dataKeyLayoutPath: 'layouts/myLayout1.njk',
      _config: [Object],
      _templateRender: [TemplateRender],
      inputContent: '---\n' +
        'layout: layouts/myLayout2.njk\n' +
        'title: My Layout 1\n' +
        '---\n' +
        '\n' +
        '<h2> {{ title }}  in Layout 1</h2>\n' +
        '\n' +
        '{{ content | safe }}\n' +
        '\n' +
        '<h3>My Data</h3>\n' +
        '<pre>\n' +
        '{\n' +
        '    myData.myKey: {{ myData.myKey }}\n' +
        '}\n' +
        '</pre>',
      frontMatter: [Object],
      mapCache: [Array],
      layoutChain: [Array],
      dataCache: [Object]
    },
    dataCache: {
...
   title: 'My Markdown',
      page: [Object]
    },
    computedData: ComputedData {
      computed: [Object],
      templateStringKeyLookup: [Object],
      computedKeys: [Set],
      declaredDependencies: [Object],
      queue: [ComputedDataQueue]
    }
  },
  inputPath: './src/ocas/my-markdown.md',
  fileSlug: 'my-markdown',
  filePathStem: '/ocas/my-markdown',
  data: {
    myData: { myKey: 'My Value' },
...
   },
  ...
    layout: 'layouts/myLayout1.njk',
    tags: [ 'ocas' ],
    parent: 'OCAs',
    stage: 'concept',
    state: 'open',
    type: 'component',
    date: 'Last Modified',
    eleventyComputed: { eleventyNavigation: [Object] },
    title: 'My Markdown',
    page: {
      date: 2020-12-10T23:28:08.018Z,
      inputPath: './src/ocas/my-markdown.md',
      fileSlug: 'my-markdown',
      filePathStem: '/ocas/my-markdown',
      url: '/ocas/my-markdown/',
      outputPath: './_site/ocas/my-markdown/index.html'
    },
    collections: {
 ...
  },
    eleventyNavigation: { key: 'My Markdown', parent: 'OCAs' }
  },
  date: 2020-12-10T23:28:08.018Z,
  outputPath: './_site/ocas/my-markdown/index.html',
  url: '/ocas/my-markdown/',
  templateContent: [Getter/Setter]
}

Question: Is it possible to get the collection item's rendered content (generated output) of each or, any of these:

  1. my-markdown.md
  2. my-layout1.njk
  3. my-layout2.njk

In my case, there's one more final layout for the base page navigation, headers, footers, etc. So looking in _site may not be the best answer since I'd prefer to capture the "content" after a layout is processed.

Thanks in advance for any insight!

stevenmilstein avatar Dec 11 '20 01:12 stevenmilstein

@stevenmilstein Hmm. What are you planning on doing with the captured content?

binyamin avatar Dec 11 '20 12:12 binyamin

@binyamin I use/embed it in other Content.

stevenmilstein avatar Dec 11 '20 13:12 stevenmilstein

Here's what I found.

  1. yes, use templateContent
  2. Not sure. I did some peeking around. It's possible that there's something buried in template._layout.
  3. Same as above

binyamin avatar Dec 11 '20 13:12 binyamin

Pay attention, that variables starting with _ (such as _layout) are usually an indicator, that it should be considered „private”. As in: it can change without any prior notice.

Perhaps worth to fill an issue (like here) if you feel the need for a defined API to that.

Ryuno-Ki avatar Dec 11 '20 14:12 Ryuno-Ki

@binyamin Yup! That's what I found too. I was hoping there was some hidden attribute [object] that could be parsed.

Thanks for looking

stevenmilstein avatar Dec 11 '20 15:12 stevenmilstein

@Ryuno-Ki I suspected the underscore had some special meaning and use _templateContent as a fallback sometimes when it's there. Thanks for the heads-up!

I'm not it's worth creating an Issue for defining an API since I haven't been able to find any remotely related Issues. I created this one hoping there was something like a built-in filter or, eleventyConfig option I was missing out on.

Thanks for your input

stevenmilstein avatar Dec 11 '20 15:12 stevenmilstein

@stevenmilstein Hmm. What are you planning on doing with the captured content?

This would also be useful for passing generated HTML to our RSS feeds when part of that HTML generation comes from plugins like eleventy-plugin-embed-everything.

Currently, things like lines with YouTube URLs are transformed into YouTube embed HTML in _site, but that transformation is not reflected in collection.item.templateContent, so an RSS feed that uses that property still shows the unprocessed YouTube URL.

It would be handy to be able to be able to access something like collection.item.generatedHTML instead so the RSS feed content HTML could match the _site HTML exactly.

ooloth avatar Jun 27 '23 02:06 ooloth