Showing preview only (1,715K chars total). Download the full file or copy to clipboard to get everything.
Repository: 11ty/eleventy
Branch: main
Commit: 0e8c596c63c8
Files: 997
Total size: 1.5 MB
Directory structure:
gitextract__ua1mjth/
├── .editorconfig
├── .git-blame-ignore-revs
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE/
│ │ ├── config.yml
│ │ └── possible-bug.yml
│ ├── dependabot.yml
│ ├── opencollective.yml
│ └── workflows/
│ ├── ci.yml
│ ├── codeql.yml
│ ├── release.yml
│ └── scorecard.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SECURITY.md
├── cmd.cjs
├── docs/
│ ├── coverage.md
│ ├── coverage.njk
│ ├── eleventy.coverage.js
│ └── release-instructions.md
├── eslint.config.js
├── package.json
├── packages/
│ └── client/
│ ├── README.md
│ ├── generate-bundle.js
│ ├── package.json
│ ├── src/
│ │ ├── BundleCore.js
│ │ ├── BundleEleventy.js
│ │ ├── BundleI18nPlugin.js
│ │ ├── BundleLiquid.js
│ │ ├── BundleMarkdown.js
│ │ ├── BundleNunjucks.js
│ │ └── shims/
│ │ ├── process.cjs
│ │ └── shim-core.js
│ ├── test/
│ │ ├── client-core.test.js
│ │ ├── client-eleventy.test.js
│ │ └── shared-tests.js
│ ├── update-package-json.js
│ └── vitest.config.js
├── scripts/
│ ├── release-dryrun.sh
│ └── release.sh
├── src/
│ ├── Adapters/
│ │ ├── Engines/
│ │ │ ├── Liquid.core.js
│ │ │ ├── Liquid.js
│ │ │ ├── Markdown.core.js
│ │ │ ├── Markdown.js
│ │ │ ├── Nunjucks.core.js
│ │ │ └── Nunjucks.js
│ │ ├── Packages/
│ │ │ ├── chalk.client.js
│ │ │ ├── chalk.js
│ │ │ ├── inspect.core.js
│ │ │ ├── inspect.js
│ │ │ ├── semver.client.js
│ │ │ ├── semver.js
│ │ │ ├── url.core.js
│ │ │ └── url.js
│ │ ├── getDefaultConfig.core.js
│ │ └── getDefaultConfig.js
│ ├── Benchmark/
│ │ ├── Benchmark.js
│ │ ├── BenchmarkGroup.js
│ │ └── BenchmarkManager.js
│ ├── Core.js
│ ├── CoreMinimal.js
│ ├── Data/
│ │ ├── ComputedData.js
│ │ ├── ComputedDataProxy.js
│ │ ├── ComputedDataQueue.js
│ │ ├── ComputedDataTemplateString.js
│ │ ├── TemplateData.js
│ │ └── TemplateDataInitialGlobalData.js
│ ├── Eleventy.js
│ ├── EleventyCommonJs.cjs
│ ├── EleventyExtensionMap.js
│ ├── EleventyFiles.js
│ ├── EleventyServe.js
│ ├── Engines/
│ │ ├── Custom.js
│ │ ├── FrontMatter/
│ │ │ └── JavaScript.js
│ │ ├── Html.js
│ │ ├── JavaScript.js
│ │ ├── Liquid.js
│ │ ├── Markdown.js
│ │ ├── Nunjucks.js
│ │ ├── TemplateEngine.js
│ │ ├── TemplateEngineManager.js
│ │ └── Util/
│ │ └── ContextAugmenter.js
│ ├── Errors/
│ │ ├── DuplicatePermalinkOutputError.js
│ │ ├── EleventyBaseError.js
│ │ ├── EleventyErrorHandler.js
│ │ ├── EleventyErrorUtil.js
│ │ ├── TemplateContentPrematureUseError.js
│ │ ├── TemplateContentUnrenderedTemplateError.js
│ │ └── UsingCircularTemplateContentReferenceError.js
│ ├── EventBus.js
│ ├── FileSystemSearch.js
│ ├── Filters/
│ │ ├── GetCollectionItem.js
│ │ ├── GetCollectionItemIndex.js
│ │ ├── GetLocaleCollectionItem.js
│ │ └── Url.js
│ ├── GlobalDependencyMap.js
│ ├── LayoutCache.js
│ ├── Plugins/
│ │ ├── HtmlBasePlugin.js
│ │ ├── HtmlRelativeCopyPlugin.js
│ │ ├── I18nPlugin.js
│ │ ├── IdAttributePlugin.js
│ │ ├── InputPathToUrl.js
│ │ ├── Pagination.js
│ │ ├── PreserveClosingTagsPlugin.js
│ │ └── RenderPlugin.js
│ ├── Template.js
│ ├── TemplateBehavior.js
│ ├── TemplateCollection.js
│ ├── TemplateConfig.js
│ ├── TemplateContent.js
│ ├── TemplateFileSlug.js
│ ├── TemplateGlob.js
│ ├── TemplateLayout.js
│ ├── TemplateLayoutPathResolver.js
│ ├── TemplateMap.js
│ ├── TemplatePassthrough.js
│ ├── TemplatePassthroughManager.js
│ ├── TemplatePermalink.js
│ ├── TemplatePreprocessors.js
│ ├── TemplateRender.js
│ ├── TemplateWriter.js
│ ├── UserConfig.js
│ ├── Util/
│ │ ├── ArrayUtil.js
│ │ ├── AsyncEventEmitter.js
│ │ ├── Compatibility.js
│ │ ├── ConsoleLogger.js
│ │ ├── DateParse.js
│ │ ├── DirContains.js
│ │ ├── EsmResolver.js
│ │ ├── EsmResolverPortAdapter.core.js
│ │ ├── EsmResolverPortAdapter.js
│ │ ├── EventBusUtil.js
│ │ ├── ExistsCache.js
│ │ ├── FeatureTests.cjs
│ │ ├── FeatureTests.core.cjs
│ │ ├── FilePathUtil.js
│ │ ├── FileSize.js
│ │ ├── FileSystemManager.js
│ │ ├── GetJavaScriptData.js
│ │ ├── Git.js
│ │ ├── GlobMatcher.client.js
│ │ ├── GlobMatcher.js
│ │ ├── GlobRemap.js
│ │ ├── GlobStripper.js
│ │ ├── HtmlRelativeCopy.js
│ │ ├── HtmlTransformer.js
│ │ ├── ImportJsonSync.js
│ │ ├── IsAsyncFunction.js
│ │ ├── JavaScriptDependencies.core.js
│ │ ├── JavaScriptDependencies.js
│ │ ├── MemoizeFunction.js
│ │ ├── NewLineAdapter.core.js
│ │ ├── NewLineAdapter.js
│ │ ├── Objects/
│ │ │ ├── DeepFreeze.js
│ │ │ ├── ObjectFilter.js
│ │ │ ├── ProxyWrap.js
│ │ │ ├── SampleModule.mjs
│ │ │ ├── Sortable.js
│ │ │ └── Unique.js
│ │ ├── PassthroughCopyBehaviorCheck.js
│ │ ├── PathNormalizer.js
│ │ ├── PathPrefixer.js
│ │ ├── Pluralize.js
│ │ ├── ProjectDirectories.js
│ │ ├── ProjectTemplateFormats.js
│ │ ├── PromiseUtil.js
│ │ ├── Require.js
│ │ ├── RequireUtils.core.js
│ │ ├── RequireUtils.js
│ │ ├── ReservedData.js
│ │ ├── ResolvePlugin.client.js
│ │ ├── ResolvePlugin.js
│ │ ├── RetrieveGlobals.client.js
│ │ ├── RetrieveGlobals.core.js
│ │ ├── RetrieveGlobals.js
│ │ ├── SemverCoerce.js
│ │ ├── SetUtil.js
│ │ ├── TemplateDepGraph.js
│ │ ├── TransformsUtil.js
│ │ ├── TypeScript/
│ │ │ └── TypeScriptSample.cts
│ │ ├── UrlUtil.js
│ │ ├── importer.client.js
│ │ ├── importer.core.js
│ │ ├── importer.js
│ │ ├── spawn.core.js
│ │ └── spawn.js
│ ├── Watch.js
│ ├── WatchQueue.js
│ ├── WatchTargets.js
│ ├── defaultConfig.js
│ ├── defaultConfigExtended.client.js
│ └── defaultConfigExtended.js
├── test/
│ ├── ArrayUtilTest.js
│ ├── BenchmarkTest.js
│ ├── BundlePluginTest.js
│ ├── CompatibilityTest.js
│ ├── ComputedDataProxyTest.js
│ ├── ComputedDataQueueTest.js
│ ├── ComputedDataTemplateStringTest.js
│ ├── ComputedDataTest.js
│ ├── ConsoleLoggerTest.js
│ ├── DependencyGraphTest.js
│ ├── DirContainsTest.js
│ ├── EleventyAddGlobalDataTest.js
│ ├── EleventyErrorHandlerTest.js
│ ├── EleventyErrorUtilTest.js
│ ├── EleventyExtensionMapTest.js
│ ├── EleventyFilesGitIgnoreEleventyIgnoreTest.js
│ ├── EleventyFilesTest.js
│ ├── EleventyImgTransformTest.js
│ ├── EleventyMarkdownTest.js
│ ├── EleventyNunjucksTest.js
│ ├── EleventyServeTest.js
│ ├── EleventyTest-CustomDateParsing.js
│ ├── EleventyTest-PageData.js
│ ├── EleventyTest-Preprocessors.js
│ ├── EleventyTest-Shortcodes.js
│ ├── EleventyTest.js
│ ├── EleventyVirtualTemplatesTest.js
│ ├── ExistsCacheTest.js
│ ├── FileSystemSearchTest.js
│ ├── GetCollectionItemIndexTest.js
│ ├── GetCollectionItemTest.js
│ ├── GlobRemapTest.js
│ ├── GlobStripperTest.js
│ ├── GlobalDependencyMapTest.js
│ ├── HtmlBasePluginTest.js
│ ├── HtmlRelativeCopyTest.js
│ ├── I18nPluginTest.js
│ ├── IdAttributePluginTest.js
│ ├── ImportJsonSyncTest.js
│ ├── InputPathToUrlPluginTest.js
│ ├── Issue3467Test.js
│ ├── Issue3788Test.js
│ ├── Issue3797Test.js
│ ├── Issue3808Test.js
│ ├── Issue3809Test.js
│ ├── Issue3816Test.js
│ ├── Issue3818Test.js
│ ├── Issue3823Test.js
│ ├── Issue3825Test.js
│ ├── Issue3831Test.js
│ ├── Issue3833Test.js
│ ├── Issue3850Test.js
│ ├── Issue3853Test.js
│ ├── Issue3854Test.js
│ ├── Issue3860Test.js
│ ├── Issue3870IncrementalTest.js
│ ├── Issue3870Test.js
│ ├── Issue3875Test.js
│ ├── Issue434Test.js
│ ├── Issue775Test.js
│ ├── JavaScriptDependenciesTest.js
│ ├── JavaScriptFrontMatterTest.js
│ ├── LayoutCacheTest.js
│ ├── LodashTest.js
│ ├── PaginationTest.js
│ ├── PassthroughCopyBehaviorTest.js
│ ├── PathNormalizerTest.js
│ ├── PathPrefixer.js
│ ├── PluralizeTest.js
│ ├── PreserveClosingTagsPluginTest.js
│ ├── ProjectDirectoriesTest.js
│ ├── ProjectTemplateFormatsTest.js
│ ├── ProxyWrapTest.js
│ ├── ReservedDataTest.js
│ ├── SemverCheckTest.js
│ ├── SortableTest.js
│ ├── TemplateCollectionTest.js
│ ├── TemplateConfigTest.js
│ ├── TemplateDataTest.js
│ ├── TemplateDepGraphTest.js
│ ├── TemplateEngineManagerTest.js
│ ├── TemplateEngineTest.js
│ ├── TemplateFileSlugTest.js
│ ├── TemplateGlobTest.js
│ ├── TemplateLayoutPathResolverTest.js
│ ├── TemplateLayoutTest.js
│ ├── TemplateMapTest-ComputedData.js
│ ├── TemplateMapTest.js
│ ├── TemplatePassthroughManagerTest.js
│ ├── TemplatePassthroughTest.js
│ ├── TemplatePermalinkTest.js
│ ├── TemplateRenderCustomTest.js
│ ├── TemplateRenderHTMLTest.js
│ ├── TemplateRenderJavaScriptTest.js
│ ├── TemplateRenderLiquidTest.js
│ ├── TemplateRenderMarkdownPluginTest.js
│ ├── TemplateRenderMarkdownTest.js
│ ├── TemplateRenderNunjucksTest.js
│ ├── TemplateRenderPluginTest.js
│ ├── TemplateRenderTest.js
│ ├── TemplateTest-CompileOptions.js
│ ├── TemplateTest-ComputedData.js
│ ├── TemplateTest-CustomExtensions.js
│ ├── TemplateTest-DataCascade.js
│ ├── TemplateTest-Dates.js
│ ├── TemplateTest-JavaScript.js
│ ├── TemplateTest.js
│ ├── TemplateTest_Permalink.js
│ ├── TemplateWriterTest.js
│ ├── TestUtilityTest.js
│ ├── TransformsUtilTest.js
│ ├── UrlTest.js
│ ├── UserConfigTest.js
│ ├── UserDataExtensionsTest.js
│ ├── Util/
│ │ ├── normalizeNewLines.js
│ │ └── normalizeSeparators.js
│ ├── UtilSetUnionTest.js
│ ├── WatchQueueTest.js
│ ├── WatchTargetsTest.js
│ ├── _getNewTemplateForTests.js
│ ├── _getRenderedTemplates.js
│ ├── _issues/
│ │ ├── 0/
│ │ │ ├── content/
│ │ │ │ └── index.html
│ │ │ ├── eleventy.config.js
│ │ │ └── issue-0-test.js
│ │ ├── 2250/
│ │ │ ├── 2250-test.js
│ │ │ ├── javascript.11ty.cjs
│ │ │ ├── liquid.liquid
│ │ │ └── nunjucks.njk
│ │ ├── 3697/
│ │ │ ├── 3697-test.js
│ │ │ └── _data/
│ │ │ └── folder/
│ │ │ ├── 0.json
│ │ │ └── 3.json
│ │ ├── 3809/
│ │ │ ├── .app/
│ │ │ │ ├── .eleventy.js
│ │ │ │ └── _data/
│ │ │ │ └── app.json
│ │ │ └── index.njk
│ │ ├── 3853/
│ │ │ └── deeper/
│ │ │ └── index.njk
│ │ ├── 3854/
│ │ │ ├── app/
│ │ │ │ ├── .eleventy.js
│ │ │ │ └── index.njk
│ │ │ └── index.njk
│ │ ├── 3896/
│ │ │ ├── eleventy-input-folder/
│ │ │ │ ├── 3896.html
│ │ │ │ └── _archive/
│ │ │ │ └── ignored.html
│ │ │ └── test-files/
│ │ │ ├── eleventy.config.js
│ │ │ └── issue3896-test.js
│ │ ├── 3932/
│ │ │ ├── 1/
│ │ │ │ └── 2025.html
│ │ │ ├── eleventy.config.js
│ │ │ └── issue-3932-test.js
│ │ └── 975/
│ │ ├── 975-test.js
│ │ ├── another-post.md
│ │ ├── index.md
│ │ └── post.md
│ ├── _testHelpers.js
│ ├── cmdTest.js
│ ├── file-system-search/
│ │ └── file.txt
│ ├── noop/
│ │ └── .gitkeep
│ ├── noop2/
│ │ └── .gitkeep
│ ├── proxy-pagination-globaldata/
│ │ ├── _data/
│ │ │ └── banner.js
│ │ ├── tmpl.liquid
│ │ ├── tmpl2.njk
│ │ └── tmpl4.11ty.js
│ ├── semverCoerceTest.js
│ ├── slugify-filter/
│ │ ├── comma.njk
│ │ ├── multibyte.njk
│ │ ├── slug-number.njk
│ │ ├── slug-options.njk
│ │ ├── slugify-number.njk
│ │ ├── slugify-options.njk
│ │ └── test.njk
│ ├── stubs/
│ │ ├── .eleventyignore
│ │ ├── 2016-02-01-permalinkdate.liquid
│ │ ├── _data/
│ │ │ ├── globalData.json
│ │ │ ├── globalData2.cjs
│ │ │ ├── globalDataFn.js
│ │ │ ├── globalDataFnCJS.cjs
│ │ │ ├── subdir/
│ │ │ │ └── testDataSubdir.json
│ │ │ ├── testData.json
│ │ │ └── testDataLiquid.json
│ │ ├── _includes/
│ │ │ ├── base.njk
│ │ │ ├── custom-filter.liquid
│ │ │ ├── default.liquid
│ │ │ ├── defaultLayout.liquid
│ │ │ ├── defaultLayoutLayoutContent.liquid
│ │ │ ├── imports.njk
│ │ │ ├── included-data.html
│ │ │ ├── included-relative.njk
│ │ │ ├── included.html
│ │ │ ├── included.liquid
│ │ │ ├── included.njk
│ │ │ ├── included.nunj
│ │ │ ├── layout-a.liquid
│ │ │ ├── layout-b.liquid
│ │ │ ├── layoutLiquid.liquid
│ │ │ ├── layouts/
│ │ │ │ ├── div-wrapper-layout.njk
│ │ │ │ ├── engineOverrides.njk
│ │ │ │ ├── engineOverridesMd.njk
│ │ │ │ ├── inasubdir.njk
│ │ │ │ ├── issue-115.liquid
│ │ │ │ ├── layout-contentdump.njk
│ │ │ │ ├── layout-inherit-a.njk
│ │ │ │ ├── layout-inherit-b.njk
│ │ │ │ ├── layout-inherit-c.njk
│ │ │ │ ├── post.liquid
│ │ │ │ └── templateMapCollection.njk
│ │ │ ├── multiple.liquid
│ │ │ ├── multiple.md
│ │ │ ├── mylocallayout.njk
│ │ │ ├── permalink-data-layout.njk
│ │ │ ├── permalink-in-layout/
│ │ │ │ ├── layout-fileslug.liquid
│ │ │ │ └── layout.liquid
│ │ │ ├── scopeleak.liquid
│ │ │ ├── subfolder/
│ │ │ │ ├── included.html
│ │ │ │ ├── included.liquid
│ │ │ │ └── included.nunj
│ │ │ └── test.js
│ │ ├── _layouts/
│ │ │ └── layoutsdefault.liquid
│ │ ├── add-extension/
│ │ │ ├── test.njk
│ │ │ └── test.txt
│ │ ├── broken-config.cjs
│ │ ├── buffer.11ty.cjs
│ │ ├── cfg-directories-export/
│ │ │ ├── eleventy.config.js
│ │ │ └── src/
│ │ │ └── .gitkeep
│ │ ├── cfg-directories-export-cjs/
│ │ │ ├── eleventy.config.cjs
│ │ │ └── src/
│ │ │ └── .gitkeep
│ │ ├── class-async-data-fn.11ty.cjs
│ │ ├── class-async-filter.11ty.cjs
│ │ ├── class-async.11ty.cjs
│ │ ├── class-buffer.11ty.cjs
│ │ ├── class-data-filter.11ty.cjs
│ │ ├── class-data-fn-filter.11ty.cjs
│ │ ├── class-data-fn-shorthand.11ty.cjs
│ │ ├── class-data-fn.11ty.cjs
│ │ ├── class-data-permalink-async-fn.11ty.cjs
│ │ ├── class-data-permalink-buffer.11ty.cjs
│ │ ├── class-data-permalink-fn-buffer.11ty.cjs
│ │ ├── class-data-permalink-fn-filter.11ty.cjs
│ │ ├── class-data-permalink-fn.11ty.cjs
│ │ ├── class-data-permalink.11ty.cjs
│ │ ├── class-data.11ty.cjs
│ │ ├── class-filter.11ty.cjs
│ │ ├── class-fns-has-page.11ty.cjs
│ │ ├── class-fns.11ty.cjs
│ │ ├── class-norender.11ty.cjs
│ │ ├── class-with-dep-upstream.js
│ │ ├── class-with-dep.11ty.cjs
│ │ ├── class.11ty.cjs
│ │ ├── classfields-data.11ty.cjs
│ │ ├── cmd-help-processing/
│ │ │ └── _data/
│ │ │ └── test.js
│ │ ├── collection/
│ │ │ ├── test1.md
│ │ │ ├── test10.md
│ │ │ ├── test2.md
│ │ │ ├── test3.md
│ │ │ ├── test4.md
│ │ │ ├── test5.md
│ │ │ ├── test6.html
│ │ │ ├── test7.njk
│ │ │ ├── test8.md
│ │ │ └── test9.md
│ │ ├── collection-layout/
│ │ │ ├── _includes/
│ │ │ │ └── layout.liquid
│ │ │ ├── dog1.liquid
│ │ │ └── template.liquid
│ │ ├── collection-layout-wrap.njk
│ │ ├── collection-slug/
│ │ │ ├── dog1.njk
│ │ │ └── template.njk
│ │ ├── collection-template/
│ │ │ ├── _includes/
│ │ │ │ └── layout.liquid
│ │ │ ├── dog1.liquid
│ │ │ └── template.liquid
│ │ ├── collection2/
│ │ │ ├── test1.md
│ │ │ └── test2.md
│ │ ├── component/
│ │ │ ├── component.11tydata.cjs
│ │ │ ├── component.11tydata.js
│ │ │ ├── component.11tydata.json
│ │ │ ├── component.json
│ │ │ └── component.njk
│ │ ├── component-async/
│ │ │ ├── component.11tydata.cjs
│ │ │ ├── component.11tydata.js
│ │ │ └── component.njk
│ │ ├── config-deps-upstream.cjs
│ │ ├── config-deps.cjs
│ │ ├── config-empty-pathprefix.cjs
│ │ ├── config-promise.js
│ │ ├── config.cjs
│ │ ├── custom-extension-no-permalink.txt
│ │ ├── custom-extension.txt
│ │ ├── custom-frontmatter/
│ │ │ ├── template-excerpt-comment.njk
│ │ │ ├── template-newline1.njk
│ │ │ ├── template-newline2.njk
│ │ │ ├── template-newline3.njk
│ │ │ ├── template-nonewline.njk
│ │ │ ├── template-toml.njk
│ │ │ └── template.njk
│ │ ├── data-cascade/
│ │ │ ├── template.11tydata.cjs
│ │ │ └── template.njk
│ │ ├── datafiledoesnotexist/
│ │ │ └── template.njk
│ │ ├── dates/
│ │ │ ├── 2018-01-01-file5.md
│ │ │ ├── 2019-01-01-folder/
│ │ │ │ └── 2020-01-01-file.md
│ │ │ ├── file1.md
│ │ │ ├── file2.md
│ │ │ ├── file2b.md
│ │ │ ├── file3.md
│ │ │ └── file4.md
│ │ ├── default-class-export-and-others.11ty.js
│ │ ├── default-export-and-others.11ty.js
│ │ ├── default-frontmatter.txt
│ │ ├── default-function-export-and-named-data.11ty.cjs
│ │ ├── default-function-export-and-named-data.11ty.js
│ │ ├── default-no-liquid.md
│ │ ├── default.liquid
│ │ ├── default.md
│ │ ├── dependencies/
│ │ │ ├── dep1.cjs
│ │ │ ├── dep2.cjs
│ │ │ └── two-deps.11ty.cjs
│ │ ├── deps/
│ │ │ ├── dep1.cjs
│ │ │ └── dep2.cjs
│ │ ├── dynamic-permalink/
│ │ │ └── test.njk
│ │ ├── eleventyComputed/
│ │ │ ├── first.njk
│ │ │ ├── override-reuse.njk
│ │ │ ├── override.njk
│ │ │ ├── permalink-simple.njk
│ │ │ ├── permalink-slug.njk
│ │ │ ├── permalink.njk
│ │ │ ├── second.njk
│ │ │ ├── third.njk
│ │ │ ├── true.njk
│ │ │ └── use-global-data.njk
│ │ ├── eleventyExcludeFromCollections.njk
│ │ ├── eleventyExcludeFromCollectionsPermalinkFalse.njk
│ │ ├── engine-singletons/
│ │ │ ├── first.njk
│ │ │ └── second.njk
│ │ ├── exitCode/
│ │ │ └── failure.njk
│ │ ├── exitCode_globalData/
│ │ │ ├── _data/
│ │ │ │ └── test.js
│ │ │ └── test.liquid
│ │ ├── exitCode_success/
│ │ │ └── success.njk
│ │ ├── exports-flatdata.11ty.cjs
│ │ ├── fileslug.11ty.cjs
│ │ ├── firstdir/
│ │ │ └── seconddir/
│ │ │ └── component.njk
│ │ ├── formatTest.liquid
│ │ ├── frontmatter-date/
│ │ │ ├── test.liquid
│ │ │ └── test.njk
│ │ ├── function-arrow.11ty.cjs
│ │ ├── function-async-filter.11ty.cjs
│ │ ├── function-async.11ty.cjs
│ │ ├── function-buffer.11ty.cjs
│ │ ├── function-filter.11ty.cjs
│ │ ├── function-fns.11ty.cjs
│ │ ├── function-markdown.11ty.cjs
│ │ ├── function-prototype.11ty.cjs
│ │ ├── function-throws-async.11ty.cjs
│ │ ├── function-throws.11ty.cjs
│ │ ├── function.11ty.cjs
│ │ ├── glob-pages/
│ │ │ ├── about.md
│ │ │ ├── contact.md
│ │ │ └── home.md
│ │ ├── global-dash-variable.liquid
│ │ ├── globby/
│ │ │ ├── _includes/
│ │ │ │ └── include.html
│ │ │ └── test.html
│ │ ├── ignore-dedupe/
│ │ │ └── .gitignore
│ │ ├── ignore1/
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignore2/
│ │ │ ├── .gitignore
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignore3/
│ │ │ ├── .eleventyignore
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignore4/
│ │ │ ├── .eleventyignore
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignore5/
│ │ │ ├── .gitignore
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignore6/
│ │ │ ├── .eleventyignore
│ │ │ ├── .gitignore
│ │ │ └── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignoredFolder/
│ │ │ └── ignored.md
│ │ ├── ignorelocalroot/
│ │ │ └── .eleventyignore
│ │ ├── ignorelocalrootgitignore/
│ │ │ ├── .eleventyignore
│ │ │ └── .gitignore
│ │ ├── img/
│ │ │ └── stub.md
│ │ ├── included.liquid
│ │ ├── includer.liquid
│ │ ├── includesemptystring.liquid
│ │ ├── index.html
│ │ ├── index.liquid
│ │ ├── issue-115/
│ │ │ ├── index-with-layout.liquid
│ │ │ ├── index.liquid
│ │ │ ├── template-bars.liquid
│ │ │ └── template-foos.liquid
│ │ ├── issue-135/
│ │ │ ├── template.json
│ │ │ └── template.njk
│ │ ├── issue-522/
│ │ │ ├── excluded.md
│ │ │ └── template.md
│ │ ├── issue-95/
│ │ │ ├── cat.md
│ │ │ └── notacat.md
│ │ ├── layout-permalink-difflang/
│ │ │ ├── _includes/
│ │ │ │ └── test.njk
│ │ │ └── test.md
│ │ ├── layoutsemptystring.liquid
│ │ ├── local-data-tags/
│ │ │ ├── component.11tydata.cjs
│ │ │ └── component.njk
│ │ ├── multiple-ignores/
│ │ │ ├── .eleventyignore
│ │ │ ├── ignoredFolder/
│ │ │ │ └── ignored.md
│ │ │ └── subfolder/
│ │ │ ├── .eleventyignore
│ │ │ └── ignoredFolder2/
│ │ │ └── ignored2.md
│ │ ├── multipleexports-promises.11ty.cjs
│ │ ├── multipleexports.11ty.cjs
│ │ ├── njk-relative/
│ │ │ └── dir/
│ │ │ ├── base.njk
│ │ │ ├── imports.njk
│ │ │ ├── included.njk
│ │ │ └── unique-include-123.njk
│ │ ├── object-norender.11ty.cjs
│ │ ├── object.11ty.cjs
│ │ ├── oneinstance.11ty.cjs
│ │ ├── overrides/
│ │ │ ├── layout.njk
│ │ │ ├── layoutfalse.njk
│ │ │ ├── page-templatesyntax.md
│ │ │ ├── test-bypass.md
│ │ │ ├── test-empty.html
│ │ │ ├── test-empty.md
│ │ │ ├── test-error.njk
│ │ │ ├── test-md.liquid
│ │ │ ├── test-multiple.md
│ │ │ ├── test-multiple2.njk
│ │ │ ├── test-njk.liquid
│ │ │ ├── test.html
│ │ │ ├── test.liquid
│ │ │ └── test.md
│ │ ├── page-target-collections/
│ │ │ ├── paginateall.njk
│ │ │ ├── tagpages.njk
│ │ │ └── tagpagesall.njk
│ │ ├── paged/
│ │ │ ├── cfg-collection-tag-cfg-collection/
│ │ │ │ ├── consumer.njk
│ │ │ │ ├── paged-downstream.njk
│ │ │ │ ├── paged-main.njk
│ │ │ │ ├── test1.njk
│ │ │ │ ├── test2.njk
│ │ │ │ └── test3.njk
│ │ │ ├── collection/
│ │ │ │ ├── consumer.njk
│ │ │ │ ├── main.njk
│ │ │ │ ├── test1.njk
│ │ │ │ ├── test2.njk
│ │ │ │ └── test3.njk
│ │ │ ├── collection-apply-to-all/
│ │ │ │ ├── consumer.njk
│ │ │ │ ├── main.njk
│ │ │ │ ├── test1.njk
│ │ │ │ ├── test2.njk
│ │ │ │ └── test3.njk
│ │ │ ├── notpaged.njk
│ │ │ ├── paged-before-and-reverse.njk
│ │ │ ├── paged-before-filter.njk
│ │ │ ├── paged-before-metadata.njk
│ │ │ ├── paged-before.njk
│ │ │ ├── paged-empty-pageonemptydata.njk
│ │ │ ├── paged-empty.njk
│ │ │ ├── paged.json
│ │ │ ├── paged.njk
│ │ │ ├── pagedalias.njk
│ │ │ ├── pagedaliassize2.njk
│ │ │ ├── pagedinlinedata-reverse.njk
│ │ │ ├── pagedinlinedata.njk
│ │ │ ├── pagedobject.njk
│ │ │ ├── pagedobjectfilterarray.njk
│ │ │ ├── pagedobjectfilterstring.njk
│ │ │ ├── pagedobjectvalues.njk
│ │ │ ├── pagedpermalink.njk
│ │ │ ├── pagedpermalinkif.liquid
│ │ │ ├── pagedpermalinkif.njk
│ │ │ ├── pagedpermalinknumeric.njk
│ │ │ ├── pagedpermalinknumericoneindexed.njk
│ │ │ └── pagedresolve.njk
│ │ ├── paged-global-data-mutable/
│ │ │ ├── _data/
│ │ │ │ └── testdata.cjs
│ │ │ └── paged-differing-data-set.njk
│ │ ├── pagedate.liquid
│ │ ├── pagedate.njk
│ │ ├── pagedateutc.njk
│ │ ├── pagination-eleventycomputed-permalink.liquid
│ │ ├── pagination-eleventycomputed-title.liquid
│ │ ├── pagination-templatecontent/
│ │ │ ├── index.njk
│ │ │ ├── post-1.md
│ │ │ └── post-2.md
│ │ ├── permalink-build/
│ │ │ └── permalink-build.md
│ │ ├── permalink-conflicts/
│ │ │ ├── test1.md
│ │ │ ├── test2.md
│ │ │ └── test3.md
│ │ ├── permalink-conflicts-false/
│ │ │ ├── test1.md
│ │ │ └── test2.md
│ │ ├── permalink-data-layout/
│ │ │ ├── test.json
│ │ │ └── test.njk
│ │ ├── permalink-empty-object/
│ │ │ └── empty-object.md
│ │ ├── permalink-false/
│ │ │ └── test.md
│ │ ├── permalink-false-computed/
│ │ │ └── test.md
│ │ ├── permalink-in-layout-fileslug.liquid
│ │ ├── permalink-in-layout.liquid
│ │ ├── permalink-markdown-override.md
│ │ ├── permalink-markdown-var.md
│ │ ├── permalink-markdown.md
│ │ ├── permalink-nobuild/
│ │ │ └── permalink-nobuild.md
│ │ ├── permalink-true/
│ │ │ └── permalink-true.md
│ │ ├── permalinkdata-jsfn.njk
│ │ ├── permalinkdata-jspermalinkfn.njk
│ │ ├── permalinkdata.njk
│ │ ├── permalinkdate.liquid
│ │ ├── permalinked.liquid
│ │ ├── posts/
│ │ │ ├── post1.njk
│ │ │ ├── posts.json
│ │ │ └── posts.njk
│ │ ├── prematureTemplateContent/
│ │ │ ├── test.11ty.cjs
│ │ │ ├── test.liquid
│ │ │ ├── test.md
│ │ │ └── test.njk
│ │ ├── promise.11ty.cjs
│ │ ├── public/
│ │ │ └── test.css
│ │ ├── relative-liquid/
│ │ │ └── dir/
│ │ │ └── included.liquid
│ │ ├── reuse-permalink/
│ │ │ ├── reuse-permalink.json
│ │ │ └── test1.liquid
│ │ ├── script-frontmatter/
│ │ │ ├── test-default.njk
│ │ │ ├── test-js.njk
│ │ │ └── test.njk
│ │ ├── string.11ty.cjs
│ │ ├── string.11ty.custom
│ │ ├── string.11ty.possum
│ │ ├── stubs-1541/
│ │ │ └── _includes/
│ │ │ └── render-source.liquid
│ │ ├── stubs-computed-permalink/
│ │ │ ├── eleventycomputed-nested-object.11ty.cjs
│ │ │ ├── eleventycomputed-object-replace.11ty.cjs
│ │ │ └── eleventycomputed-object.11ty.cjs
│ │ ├── stubs-virtual-conflict/
│ │ │ └── virtual.md
│ │ ├── subdir/
│ │ │ ├── img/
│ │ │ │ └── .gitkeep
│ │ │ └── index.html
│ │ ├── subfolder/
│ │ │ ├── index.html
│ │ │ ├── subfolder/
│ │ │ │ └── subfolder.liquid
│ │ │ └── subfolder.liquid
│ │ ├── tagged-pagination-multiples/
│ │ │ └── test.njk
│ │ ├── tagged-pagination-multiples-layout/
│ │ │ └── test.njk
│ │ ├── template-passthrough/
│ │ │ ├── .htaccess
│ │ │ └── static/
│ │ │ ├── nested/
│ │ │ │ └── test-nested.css
│ │ │ ├── test.css
│ │ │ └── test.js
│ │ ├── template-passthrough2/
│ │ │ ├── .htaccess
│ │ │ └── static/
│ │ │ ├── nested/
│ │ │ │ └── test-nested.css
│ │ │ ├── test.css
│ │ │ └── test.js
│ │ ├── template.liquid
│ │ ├── templateFrontMatter.liquid
│ │ ├── templateFrontMatterJs.njk
│ │ ├── templateFrontMatterJson.liquid
│ │ ├── templateLayoutCacheDuplicates/
│ │ │ └── _includes/
│ │ │ └── layout.njk
│ │ ├── templateLayoutCacheDuplicates-b/
│ │ │ └── _includes/
│ │ │ └── layout.njk
│ │ ├── templateMapCollection/
│ │ │ ├── paged-cfg-permalink.md
│ │ │ ├── paged-cfg-tagged-apply-to-all.md
│ │ │ ├── paged-cfg-tagged-permalink-apply-to-all.md
│ │ │ ├── paged-cfg-tagged-permalink.md
│ │ │ ├── paged-cfg-tagged.md
│ │ │ ├── paged-cfg.md
│ │ │ ├── paged-tag-dogs-templateContent-alias.md
│ │ │ ├── paged-tag-dogs-templateContent.md
│ │ │ ├── paged-tag.md
│ │ │ ├── templateContent.md
│ │ │ ├── test1.md
│ │ │ ├── test2.md
│ │ │ ├── test3.md
│ │ │ ├── test4.md
│ │ │ ├── test5.md
│ │ │ └── testWithLayout.md
│ │ ├── templateTwoLayouts.liquid
│ │ ├── templateWithLayout.liquid
│ │ ├── templateWithLayoutContent.liquid
│ │ ├── templateWithLayoutKey.liquid
│ │ ├── templatetest-frontmatter/
│ │ │ ├── multiple.njk
│ │ │ └── single.njk
│ │ ├── test-override-js-markdown.11ty.cjs
│ │ ├── testing.html
│ │ ├── transform-pages/
│ │ │ └── template.njk
│ │ ├── use-collection.11ty.cjs
│ │ ├── vue-layout.11ty.cjs
│ │ ├── vue.11ty.cjs
│ │ ├── writeTest/
│ │ │ └── test.md
│ │ ├── writeTestJS/
│ │ │ ├── sample.cjs
│ │ │ └── test.11ty.cjs
│ │ ├── writeTestJS-casesensitive/
│ │ │ ├── sample.Js
│ │ │ └── test.11Ty.js
│ │ ├── writeTestJS-passthrough/
│ │ │ ├── sample.js
│ │ │ └── test.11ty.js
│ │ └── writeTestMarkdown/
│ │ ├── sample.md
│ │ └── sample2.markdown
│ ├── stubs--to/
│ │ ├── test.md
│ │ └── test2.liquid
│ ├── stubs-1206/
│ │ ├── page1.njk
│ │ └── page2.njk
│ ├── stubs-1242/
│ │ ├── _data/
│ │ │ ├── xyz.dottest/
│ │ │ │ └── test.json
│ │ │ └── xyz.dottest.json
│ │ └── empty.md
│ ├── stubs-1325/
│ │ ├── test.11ty.js
│ │ └── test.js
│ ├── stubs-142/
│ │ └── index.njk
│ ├── stubs-1691/
│ │ ├── _data/
│ │ │ └── str.txt
│ │ ├── template.11tydata.txt
│ │ └── template.njk
│ ├── stubs-2145/
│ │ ├── _includes/
│ │ │ └── layout.njk
│ │ └── test.njk
│ ├── stubs-2167/
│ │ └── paginated.njk
│ ├── stubs-2224/
│ │ └── index.njk
│ ├── stubs-2258/
│ │ ├── _includes/
│ │ │ ├── _code.scss
│ │ │ └── layout.njk
│ │ ├── eleventy.config.cjs
│ │ └── style.scss
│ ├── stubs-2258-2830-skip-layouts/
│ │ ├── _includes/
│ │ │ └── layout.njk
│ │ ├── eleventy.config.cjs
│ │ └── style.scss
│ ├── stubs-2261/
│ │ ├── _includes/
│ │ │ └── block.njk
│ │ ├── eleventy.config.js
│ │ └── index.njk
│ ├── stubs-2367/
│ │ ├── _includes/
│ │ │ └── layout.liquid
│ │ ├── templateWithLiquidShortcodeMultipleArguments-template2.liquid
│ │ └── templateWithLiquidShortcodeMultipleArguments.liquid
│ ├── stubs-2602/
│ │ └── index.njk
│ ├── stubs-2753/
│ │ ├── _data/
│ │ │ └── global.js
│ │ ├── page1.njk
│ │ └── page2.njk
│ ├── stubs-2790/
│ │ └── page.11ty.cjs
│ ├── stubs-2851/
│ │ ├── content.njk
│ │ └── paginated.njk
│ ├── stubs-3013/
│ │ ├── html/
│ │ │ ├── _data/
│ │ │ │ └── books.json
│ │ │ ├── _includes/
│ │ │ │ └── base.html
│ │ │ └── book.html
│ │ ├── liquid/
│ │ │ ├── _data/
│ │ │ │ └── books.json
│ │ │ ├── _includes/
│ │ │ │ └── base.liquid
│ │ │ └── book.liquid
│ │ ├── md/
│ │ │ ├── _data/
│ │ │ │ └── books.json
│ │ │ ├── _includes/
│ │ │ │ └── base.md
│ │ │ └── book.md
│ │ └── njk/
│ │ ├── _data/
│ │ │ └── books.json
│ │ ├── _includes/
│ │ │ └── base.njk
│ │ └── book.njk
│ ├── stubs-3285/
│ │ └── src/
│ │ └── scripts/
│ │ └── hello-world.js
│ ├── stubs-3356/
│ │ └── .gitkeep
│ ├── stubs-337/
│ │ ├── data/
│ │ │ └── xyz.json
│ │ └── src/
│ │ └── empty.md
│ ├── stubs-3807/
│ │ ├── Issue3807test.js
│ │ ├── _layouts/
│ │ │ ├── base.html
│ │ │ └── home.html
│ │ ├── eleventy.config.js
│ │ └── index.md
│ ├── stubs-3810/
│ │ ├── _includes/
│ │ │ └── promo.njk
│ │ ├── eleventy.config.js
│ │ └── index.md
│ ├── stubs-403/
│ │ ├── .eleventyignore
│ │ ├── _includes/
│ │ │ └── include.liquid
│ │ └── template.liquid
│ ├── stubs-408-sass/
│ │ ├── _code.scss
│ │ └── style.scss
│ ├── stubs-413/
│ │ └── date-frontmatter.md
│ ├── stubs-434/
│ │ └── _includes/
│ │ ├── macros-filter.njk
│ │ └── macros.njk
│ ├── stubs-475/
│ │ ├── _includes/
│ │ │ └── layout.njk
│ │ └── transform-layout/
│ │ └── transform-layout.njk
│ ├── stubs-630/
│ │ ├── _data/
│ │ │ ├── globalData0.cjs
│ │ │ ├── globalData1.cjs
│ │ │ ├── globalData2.json
│ │ │ ├── globalData3.yaml
│ │ │ ├── globalData4.nosj
│ │ │ ├── mergingGlobalData.cjs
│ │ │ ├── mergingGlobalData.js
│ │ │ ├── mergingGlobalData.json
│ │ │ ├── mergingGlobalData.nosj
│ │ │ ├── mergingGlobalData.yaml
│ │ │ └── subdir/
│ │ │ └── globalDataSubdir.yaml
│ │ └── component-yaml/
│ │ ├── component.11tydata.cjs
│ │ ├── component.11tydata.json
│ │ ├── component.11tydata.nosj
│ │ ├── component.11tydata.yaml
│ │ ├── component.json
│ │ ├── component.njk
│ │ └── component.yaml
│ ├── stubs-670/
│ │ ├── content.njk
│ │ └── index.njk
│ ├── stubs-919/
│ │ ├── test.11tydata.cjs
│ │ ├── test.njk
│ │ └── test2.njk
│ ├── stubs-absolute/
│ │ └── test.md
│ ├── stubs-addglobaldata/
│ │ └── test.liquid
│ ├── stubs-addglobaldata-noop/
│ │ └── test.txt
│ ├── stubs-autocopy/
│ │ └── .gitkeep
│ ├── stubs-base/
│ │ └── index.njk
│ ├── stubs-base-case-sens/
│ │ └── index.njk
│ ├── stubs-circular-layout/
│ │ └── _includes/
│ │ ├── layout-cycle-a.njk
│ │ ├── layout-cycle-b.njk
│ │ ├── layout-cycle-c.njk
│ │ └── layout-cycle-self.njk
│ ├── stubs-computed-array/
│ │ └── test.liquid
│ ├── stubs-computed-collections/
│ │ ├── collections.njk
│ │ └── dog.njk
│ ├── stubs-computed-collections-filter/
│ │ ├── collections.njk
│ │ └── dog.njk
│ ├── stubs-computed-dirdata/
│ │ └── dir/
│ │ ├── dir.11tydata.cjs
│ │ ├── first.11ty.cjs
│ │ └── second.11ty.cjs
│ ├── stubs-computed-global/
│ │ ├── _data/
│ │ │ └── eleventyComputed.cjs
│ │ └── intermix.njk
│ ├── stubs-computed-pagination/
│ │ ├── child.11ty.cjs
│ │ └── paginated.njk
│ ├── stubs-computed-symbolparse/
│ │ ├── test.liquid
│ │ └── test.njk
│ ├── stubs-custom-extension/
│ │ └── test.js1
│ ├── stubs-data-cascade/
│ │ ├── global-versus-layout/
│ │ │ ├── _data/
│ │ │ │ └── cascade.cjs
│ │ │ ├── _includes/
│ │ │ │ └── base.njk
│ │ │ └── test.njk
│ │ ├── layout-data-files/
│ │ │ ├── _includes/
│ │ │ │ └── base.njk
│ │ │ ├── test.11tydata.cjs
│ │ │ └── test.njk
│ │ ├── layout-versus-dirdatafile/
│ │ │ └── src/
│ │ │ ├── _includes/
│ │ │ │ └── base.njk
│ │ │ ├── src.11tydata.cjs
│ │ │ └── test.njk
│ │ └── layout-versus-tmpldatafile/
│ │ ├── _includes/
│ │ │ └── base.njk
│ │ ├── test.11tydata.cjs
│ │ └── test.njk
│ ├── stubs-data-esm/
│ │ └── _data/
│ │ ├── commonjs.cjs
│ │ └── module.mjs
│ ├── stubs-dependency-tree/
│ │ ├── child.cjs
│ │ ├── grandchild.cjs
│ │ └── index.cjs
│ ├── stubs-empty/
│ │ └── .gitkeep
│ ├── stubs-empty-json-data/
│ │ └── _data/
│ │ └── empty.json
│ ├── stubs-fancyjs/
│ │ ├── test.11ty.tsx
│ │ └── test.mdx
│ ├── stubs-freeze/
│ │ ├── eleventy/
│ │ │ └── _data/
│ │ │ └── eleventy.js
│ │ └── page/
│ │ └── _data/
│ │ └── page.js
│ ├── stubs-global-data-config-api/
│ │ └── empty.txt
│ ├── stubs-global-data-config-api-nested/
│ │ └── _data/
│ │ └── deep.cjs
│ ├── stubs-i18n/
│ │ ├── en/
│ │ │ └── index.liquid
│ │ ├── en-us/
│ │ │ └── index.11ty.cjs
│ │ ├── es/
│ │ │ └── index.njk
│ │ └── non-lang-file.njk
│ ├── stubs-img-transform/
│ │ ├── ignored.md
│ │ ├── missing-alt.md
│ │ ├── multiple.md
│ │ └── single.md
│ ├── stubs-incremental/
│ │ └── layout-chain/
│ │ ├── _includes/
│ │ │ ├── base.njk
│ │ │ └── parent.njk
│ │ └── test.njk
│ ├── stubs-layout-cache/
│ │ ├── _includes/
│ │ │ ├── layout.liquid
│ │ │ └── layout.njk
│ │ ├── test.liquid
│ │ └── test.njk
│ ├── stubs-layouts-event/
│ │ ├── _includes/
│ │ │ ├── first.liquid
│ │ │ ├── second.liquid
│ │ │ └── third.liquid
│ │ └── page.md
│ ├── stubs-njk-async/
│ │ └── _includes/
│ │ └── loop.njk
│ ├── stubs-pagination-computed-quotes/
│ │ ├── post.liquid
│ │ └── test.liquid
│ ├── stubs-pagination-computed-quotes-njk/
│ │ ├── post.njk
│ │ └── test.njk
│ ├── stubs-pathtourl/
│ │ ├── css.njk
│ │ ├── filter.njk
│ │ ├── tmpl.njk
│ │ └── transform.njk
│ ├── stubs-render-plugin/
│ │ ├── 11tyjs-file-override.njk
│ │ ├── 11tyjs-file.njk
│ │ ├── 11tyjs.liquid
│ │ ├── _includes/
│ │ │ ├── frontmatter.liquid
│ │ │ ├── include-js.txt
│ │ │ ├── include.11ty.cjs
│ │ │ ├── include.liquid
│ │ │ └── include.njk
│ │ ├── bad-data.njk
│ │ ├── capture-liquid.njk
│ │ ├── capture-njk.liquid
│ │ ├── data-no-templatelang.liquid
│ │ ├── false.liquid
│ │ ├── liquid-direct.njk
│ │ ├── liquid-eleventy.njk
│ │ ├── liquid-global.njk
│ │ ├── liquid-md.11ty.cjs
│ │ ├── liquid-md.liquid
│ │ ├── liquid-page.liquid
│ │ ├── liquid-page.njk
│ │ ├── liquid.njk
│ │ ├── md.liquid
│ │ ├── njk-eleventy.liquid
│ │ ├── njk-file-not-exist.liquid
│ │ ├── njk-file.liquid
│ │ ├── njk-file.njk
│ │ ├── njk-page.liquid
│ │ ├── nunjucks-frontmatter.njk
│ │ ├── nunjucks-global.liquid
│ │ ├── nunjucks.11ty.cjs
│ │ ├── nunjucks.liquid
│ │ ├── using-frontmatter.liquid
│ │ └── vue.liquid
│ ├── stubs-virtual/
│ │ ├── .gitkeep
│ │ └── eleventy.config.js
│ ├── stubs-virtual-nowrite/
│ │ └── .gitkeep
│ └── views/
│ └── .gitkeep
├── test_node/
│ ├── 3824/
│ │ ├── 3824-test.js
│ │ ├── _includes/
│ │ │ ├── head.tsx
│ │ │ └── view-props.tsx
│ │ ├── eleventy.config.js
│ │ ├── index.11ty.tsx
│ │ └── tsconfig-3824.json
│ ├── 3824-incremental/
│ │ ├── 3824-incremental-test.js
│ │ ├── _includes/
│ │ │ ├── head.tsx
│ │ │ └── view-props.tsx
│ │ ├── eleventy.config.js
│ │ ├── index.11ty.tsx
│ │ └── tsconfig-3824.json
│ ├── JsxTest.js
│ ├── MdxTest.js
│ ├── README.md
│ └── tests.js
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
indent_style = tab
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[*.yml]
indent_style = space
[/test/**/*]
indent_style = space
[/test/stubs*/**]
insert_final_newline = false
trim_trailing_whitespace = false
================================================
FILE: .git-blame-ignore-revs
================================================
# Switch the entire codebase to tabs, for accessibility #3098
358ec48f779fa34e14abef057cc1fa0c1a10aa45
================================================
FILE: .github/CODEOWNERS
================================================
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
* @zachleat
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
contact_links:
- name: I have a question about Eleventy
url: https://github.com/11ty/eleventy/discussions/
about: General education topics should be filed on our Discussions board e.g. “How do I do this in Eleventy?” or “Can Eleventy do this?” (Please search existing discussions first!)
- name: I have a feature request for Eleventy
url: https://github.com/11ty/eleventy/discussions/new?category=enhancement-queue
about: Enhancement or new Features. e.g. “I wish Eleventy did this.” Suggest an idea! (Please search existing discussions first!)
- name: I wish the docs were different!
url: https://github.com/11ty/11ty-website/issues/new/choose
about: Something missing from the documentation? Something wrong? Something confusing? You want the 11ty-website repo!
- name: Discord Community
url: https://discord.gg/GBkBy9u
about: Ask the community on Discord
================================================
FILE: .github/ISSUE_TEMPLATE/possible-bug.yml
================================================
name: I’m having trouble with Eleventy
description: Have a problem? It might be a bug! Create a report to help us improve.
labels: [needs-triage]
body:
- type: markdown
attributes:
value: |
Before opening a bug report, please search for the behavior in the existing issues.
---
Thank you for taking the time to file a bug report. To address this bug as fast as possible, we need some information.
- type: input
id: os
attributes:
label: Operating system
description: Which operating system do you use?
placeholder: macOS Big Sur 11.5.2
validations:
required: true
- type: input
id: eleventy
attributes:
label: Eleventy
description: Which version of Eleventy do you use?
placeholder: eleventy --version or npx @11ty/eleventy --version
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Describe the bug
description: A clear and concise description of how to reproduce the bug
value: |
1. I ran *this* command with *these* flags '...'
2. I used the following configuration and template syntax '....'
3. I got *this* error or I expected this to happen and it didn’t
validations:
required: true
- type: input
id: repro-url
attributes:
label: Reproduction Source Code URL
description: "Optional: The URL to the **public** repository for the reproduction. _[parser:url]_"
placeholder: e.g. https://github.com/zachleat/zachleat.com
validations:
required: false
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: "Optional: If applicable, add screenshots to help explain your problem."
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: weekly
cooldown:
default-days: 7
labels:
- "dependency-updates"
versioning-strategy: increase
allow:
- dependency-type: "production"
assignees: [zachleat]
- package-ecosystem: github-actions
directories: [".github/workflows/**"]
schedule:
interval: weekly
cooldown:
default-days: 7
assignees: [zachleat]
================================================
FILE: .github/opencollective.yml
================================================
collective: 11ty
tiers:
- tiers: '*'
labels: ["oc-supporter"]
message: "Hey <author>, thanks for supporting us on Open Collective!"
invitation: |
Hey <author> :wave:,
Thank you for opening an issue. We will get back to you as soon as we can.
Also, check out our [Open Collective](https://opencollective.com/11ty) and consider backing us—every little bit helps!
================================================
FILE: .github/workflows/ci.yml
================================================
name: Unit Tests
on: push
permissions: read-all
jobs:
server:
name: Node.js v${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
node: ["20", "22", "24"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- name: Setup node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # 6.2.0
with:
node-version: ${{ matrix.node }}
# cache: npm
- run: npm ci
- run: npm run test:server
client:
name: Vitest on ${{ matrix.os }} (Node.js v${{ matrix.node }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
node: ["22"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- name: Setup node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # 6.2.0
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npx playwright install
- run: npm run test:client
env:
YARN_GPG: no
================================================
FILE: .github/workflows/codeql.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '21 17 * * 5'
# Declare default permissions as read only.
permissions: read-all
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #4.31.9
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #4.31.9
with:
category: "/language:${{matrix.language}}"
================================================
FILE: .github/workflows/release.yml
================================================
name: Publish Release to npm
on:
release:
types: [published]
permissions: read-all
jobs:
release:
# see https://github.com/11ty/eleventy/settings/environments
environment: GitHub Publish
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # 6.2.0
with:
node-version: "22"
registry-url: 'https://registry.npmjs.org'
- run: npm install -g npm@latest
- if: ${{ github.event.release.tag_name != '' && env.NPM_PUBLISH_TAG != '' }}
# Also runs npm ci and npm test
run: ./scripts/release.sh
env:
NPM_PUBLISH_TAG: ${{ contains(github.event.release.tag_name, '-beta.') && 'beta' || contains(github.event.release.tag_name, '-alpha.') && 'canary' || 'latest' }}
================================================
FILE: .github/workflows/scorecard.yml
================================================
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '35 7 * * 2'
push:
branches: [ "main" ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
# - name: "Upload artifact"
# uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
# with:
# name: SARIF file
# path: results.sarif
# retention-days: 5
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
# - name: "Upload to code-scanning"
# uses: github/codeql-action/upload-sarif@v3
# with:
# sarif_file: results.sarif
================================================
FILE: .gitignore
================================================
# Generated files
dist/
packages/*/visualize/*
# Ignore installed npm modules
node_modules/
# Ignore build tool output, e.g. code coverage
.nyc_output/
coverage/
docs/_data/coverage.json
# Ignore API documentation
api-docs/
# Ignore folders from source code editors
.vscode
.idea
# Ignore eleventy output when doing manual tests
_site/
# Ignore test files
.cache
test/stubs-layout-cache/_includes/*.js
================================================
FILE: .npmignore
================================================
docs
docs-src
test
test_node
coverage
eslint.config.js
.*
packages/client/
================================================
FILE: .nvmrc
================================================
22
================================================
FILE: .prettierignore
================================================
test
================================================
FILE: .prettierrc.json
================================================
{
"useTabs": true,
"singleQuote": false,
"semi": true,
"endOfLine": "lf",
"arrowParens": "always",
"printWidth": 100
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Eleventy Community Code of Conduct
View the [Code of Conduct](https://www.11ty.dev/docs/code-of-conduct/) on 11ty.dev
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, chat messages, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at eleventy@zachleat.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017–2024 Zach Leatherman @zachleat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="eleventy Logo"></p>
# eleventy 🕚⚡️🎈🐀
A simpler static site generator. An alternative to Jekyll. Written in JavaScript. Transforms a directory of templates (of varying types) into HTML.
Works with HTML, Markdown, JavaScript, Liquid, Nunjucks, with addons for WebC, Sass, Vue, Svelte, TypeScript, JSX, and many others!
## ➡ [Documentation](https://www.11ty.dev/docs/)
- Star [this repo on GitHub](https://github.com/11ty/eleventy/)!
- Follow us [on Mastodon `@11ty@neighborhood.11ty.dev`](https://neighborhood.11ty.dev/@11ty)
- Follow us [on Bluesky `@11ty.dev`](https://bsky.app/profile/11ty.dev)
- Install [from npm](https://www.npmjs.com/org/11ty)
- Follow [on GitHub](https://github.com/11ty)
- Watch us [on YouTube](https://www.youtube.com/c/EleventyVideo)
- Chat on [Discord](https://www.11ty.dev/blog/discord/)
- Latest: [](https://www.npmjs.com/package/@11ty/eleventy)
## Installation
```
npm install @11ty/eleventy --save-dev
```
Read our [Getting Started guide](https://www.11ty.dev/docs/getting-started/).
## Tests
```
npm test
```
We have a few test suites, for various reasons:
- [ava JavaScript test runner](https://github.com/avajs/ava) ([assertions docs](https://github.com/avajs/ava/blob/main/docs/03-assertions.md)) (primary test suite in `test/`)
- [Node.js Test runner](https://nodejs.org/api/test.html) (secondary test suite in `test_node/`)
- [Vitest (in Browser Mode)](https://vitest.dev/guide/browser/) (client tests in `packages/client/test/`)
- [Benchmark for Performance Regressions](https://github.com/11ty/eleventy-benchmark)
These run in various environments:
- [Continuous Integration on GitHub Actions](https://github.com/11ty/eleventy/actions/workflows/ci.yml)
- [Code Coverage Statistics](https://github.com/11ty/eleventy/blob/master/docs/coverage.md)
## Community Roadmap
- [Top Feature Requests](https://github.com/11ty/eleventy/discussions/categories/enhancement-queue?discussions_q=is%3Aopen+category%3A%22Enhancement+Queue%22+sort%3Atop) (Vote for your favorites!)
- [Top Bugs 😱](https://github.com/11ty/eleventy/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Areactions) (Add your own votes using the 👍 reaction)
## Plugins
See the [official docs on plugins](https://www.11ty.dev/docs/plugins/).
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Reporting a Vulnerability
Privately report a security issue by navigating to https://github.com/11ty/eleventy/security and using the “Report a vulnerability” button.
Read more at: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability
Alternatively, you may report security issues via an email to `security@11ty.dev`.
================================================
FILE: cmd.cjs
================================================
#!/usr/bin/env node
// This file intentionally uses older code conventions to be as friendly
// as possible with error messaging to folks on older runtimes.
const pkg = require("./package.json");
require("@11ty/node-version-check")(pkg, {
message: function (requiredVersion) {
return (
"Eleventy " +
pkg.version +
" requires Node " +
requiredVersion +
". You will need to upgrade Node to use Eleventy!"
);
},
});
const minimist = require("minimist");
const debug = require("debug")("Eleventy:cmd");
class SimpleError extends Error {
constructor(...args) {
super(...args);
this.skipOriginalStack = true;
}
}
async function exec() {
// Notes about friendly error messaging with outdated Node versions: https://github.com/11ty/eleventy/issues/3761
const { EleventyErrorHandler } = await import("./src/Errors/EleventyErrorHandler.js");
// Defensive use of Node 22.8+ Module Compile Cache
if(!process.env?.ELEVENTY_SKIP_NODE_COMPILE_CACHE) {
try {
const nodeMod = await import('node:module').then(mod => mod.default);
nodeMod.enableCompileCache?.();
} catch(e) {
debug("Node compile cache error (optional API) %o", e);
}
}
try {
const argv = minimist(process.argv.slice(2), {
string: ["input", "output", "formats", "config", "pathprefix", "port", "to", "incremental", "loader"],
boolean: [
"quiet",
"version",
"watch",
"dryrun",
"help",
"serve",
"ignore-initial",
],
default: {
quiet: null,
"ignore-initial": false,
"to": "fs",
},
unknown: function (unknownArgument) {
throw new Error(
`We don’t know what '${unknownArgument}' is. Use --help to see the list of supported commands.`,
);
},
});
debug("command: eleventy %o", argv);
const { Eleventy } = await import("./src/Eleventy.js");
let ErrorHandler = new EleventyErrorHandler();
process.on("unhandledRejection", (error, promise) => {
ErrorHandler.fatal(error, "Unhandled rejection in promise");
});
process.on("uncaughtException", (error) => {
ErrorHandler.fatal(error, "Uncaught exception");
});
process.on("rejectionHandled", (promise) => {
ErrorHandler.warn(promise, "A promise rejection was handled asynchronously");
});
if (argv.version) {
console.log(Eleventy.getVersion());
return;
} else if (argv.help) {
console.log(Eleventy.getHelp());
return;
}
let elev = new Eleventy(argv.input, argv.output, {
source: "cli",
// --quiet and --quiet=true both resolve to true
quietMode: argv.quiet,
configPath: argv.config,
pathPrefix: argv.pathprefix,
runMode: argv.serve ? "serve" : argv.watch ? "watch" : "build",
dryRun: argv.dryrun,
loader: argv.loader,
});
// reuse ErrorHandler instance in Eleventy
ErrorHandler = elev.errorHandler;
// Before init
elev.setFormats(argv.formats);
await elev.init();
if (argv.to === "json") {
// override logging output
elev.setIsVerbose(false);
}
// Only relevant for watch/serve
elev.setIgnoreInitial(argv["ignore-initial"]);
if(argv.incremental) {
elev.setIncrementalFile(argv.incremental);
} else if(argv.incremental !== undefined) {
elev.setIncrementalBuild(argv.incremental === "" || argv.incremental);
}
if (argv.serve || argv.watch) {
if(argv.to === "json") {
throw new SimpleError("--to=json is not compatible with --serve or --watch.");
}
await elev.watch();
if (argv.serve) {
// TODO await here?
elev.serve(argv.port);
}
process.on("SIGINT", async () => {
await elev.stopWatch();
process.exitCode = 0;
});
} else {
// `fs:templates` will skip passthrough copy
if (!argv.to || argv.to === "fs" || argv.to.startsWith("fs:")) {
await elev.write(argv.to);
} else if (argv.to === "json") {
let result = await elev.toJSON()
console.log(JSON.stringify(result, null, 2));
} else {
throw new SimpleError(
`Invalid --to value: ${argv.to}. Supported values: \`fs\` (default), \`json\`.`,
);
}
}
} catch (error) {
if(typeof EleventyErrorHandler !== "undefined") {
let ErrorHandler = new EleventyErrorHandler();
ErrorHandler.fatal(error, "Eleventy Fatal Error (CLI)");
} else {
console.error(error);
process.exitCode = 1;
}
}
}
// await
exec();
================================================
FILE: docs/coverage.md
================================================
# Code Coverage for Eleventy v3.1.2
| Filename | % Lines | % Statements | % Functions | % Branches |
| ---------------------------------------------------------- | ------- | ------------ | ----------- | ---------- |
| `total` | 90.67% | 90.67% | 90.51% | 89.18% |
| `cmd.cjs` | 71.61% | 71.61% | 25% | 68.18% |
| `src/Eleventy.js` | 91.11% | 91.11% | 87.09% | 84.15% |
| `src/EleventyExtensionMap.js` | 97.18% | 97.18% | 96.15% | 94.31% |
| `src/EleventyFiles.js` | 95.39% | 95.39% | 95.74% | 90.99% |
| `src/EleventyServe.js` | 52.33% | 52.33% | 69.56% | 58.33% |
| `src/EleventyWatch.js` | 93.12% | 93.12% | 94.44% | 91.66% |
| `src/EleventyWatchTargets.js` | 93.29% | 93.29% | 90% | 90.47% |
| `src/EventBus.js` | 100% | 100% | 100% | 100% |
| `src/FileSystemSearch.js` | 100% | 100% | 100% | 100% |
| `src/GlobalDependencyMap.js` | 81.85% | 81.85% | 85% | 88.23% |
| `src/LayoutCache.js` | 77.55% | 77.55% | 87.5% | 87.5% |
| `src/Template.js` | 94.91% | 94.91% | 93.84% | 90.73% |
| `src/TemplateBehavior.js` | 90.58% | 90.58% | 100% | 84.21% |
| `src/TemplateCollection.js` | 94.8% | 94.8% | 87.5% | 95.23% |
| `src/TemplateConfig.js` | 91.85% | 91.85% | 82.35% | 92.66% |
| `src/TemplateContent.js` | 90.24% | 90.24% | 91.83% | 87.02% |
| `src/TemplateFileSlug.js` | 100% | 100% | 100% | 100% |
| `src/TemplateGlob.js` | 94.28% | 94.28% | 100% | 91.66% |
| `src/TemplateLayout.js` | 90.83% | 90.83% | 83.33% | 88.57% |
| `src/TemplateLayoutPathResolver.js` | 88.97% | 88.97% | 75% | 90.9% |
| `src/TemplateMap.js` | 95.17% | 95.17% | 94.87% | 94.65% |
| `src/TemplatePassthrough.js` | 92.8% | 92.8% | 100% | 90% |
| `src/TemplatePassthroughManager.js` | 86.95% | 86.95% | 96.29% | 83.52% |
| `src/TemplatePermalink.js` | 87.69% | 87.69% | 91.66% | 92.95% |
| `src/TemplateRender.js` | 90.06% | 90.06% | 100% | 91.5% |
| `src/TemplateWriter.js` | 84.64% | 84.64% | 83.33% | 74.69% |
| `src/UserConfig.js` | 90.96% | 90.96% | 78.57% | 87.36% |
| `src/defaultConfig.js` | 96.06% | 96.06% | 100% | 66.66% |
| `src/Benchmark/Benchmark.js` | 98.18% | 98.18% | 100% | 92.3% |
| `src/Benchmark/BenchmarkGroup.js` | 92.59% | 92.59% | 81.81% | 95.45% |
| `src/Benchmark/BenchmarkManager.js` | 90.41% | 90.41% | 77.77% | 87.5% |
| `src/Data/ComputedData.js` | 100% | 100% | 100% | 100% |
| `src/Data/ComputedDataProxy.js` | 97.7% | 97.7% | 100% | 94.44% |
| `src/Data/ComputedDataQueue.js` | 100% | 100% | 100% | 100% |
| `src/Data/ComputedDataTemplateString.js` | 95.71% | 95.71% | 100% | 85.71% |
| `src/Data/TemplateData.js` | 93.09% | 93.09% | 94.11% | 88.12% |
| `src/Data/TemplateDataInitialGlobalData.js` | 95% | 95% | 100% | 83.33% |
| `src/Engines/Custom.js` | 88.2% | 88.2% | 100% | 86.59% |
| `src/Engines/Html.js` | 100% | 100% | 100% | 100% |
| `src/Engines/JavaScript.js` | 81.25% | 81.25% | 93.75% | 86.44% |
| `src/Engines/Liquid.js` | 99.09% | 99.09% | 100% | 95.94% |
| `src/Engines/Markdown.js` | 96% | 96% | 85.71% | 92.59% |
| `src/Engines/Nunjucks.js` | 92.32% | 92.32% | 100% | 87.5% |
| `src/Engines/TemplateEngine.js` | 89.32% | 89.32% | 83.87% | 92.68% |
| `src/Engines/TemplateEngineManager.js` | 93.78% | 93.78% | 100% | 92.64% |
| `src/Engines/FrontMatter/JavaScript.js` | 100% | 100% | 100% | 100% |
| `src/Engines/Util/ContextAugmenter.js` | 91.04% | 91.04% | 50% | 88.23% |
| `src/Errors/DuplicatePermalinkOutputError.js` | 100% | 100% | 100% | 100% |
| `src/Errors/EleventyBaseError.js` | 100% | 100% | 100% | 100% |
| `src/Errors/EleventyErrorHandler.js` | 94.07% | 94.07% | 100% | 77.77% |
| `src/Errors/EleventyErrorUtil.js` | 100% | 100% | 100% | 100% |
| `src/Errors/TemplateContentPrematureUseError.js` | 100% | 100% | 100% | 100% |
| `src/Errors/TemplateContentUnrenderedTemplateError.js` | 100% | 100% | 100% | 100% |
| `src/Errors/UsingCircularTemplateContentReferenceError.js` | 100% | 100% | 100% | 100% |
| `src/Filters/GetCollectionItem.js` | 100% | 100% | 100% | 87.5% |
| `src/Filters/GetCollectionItemIndex.js` | 88.23% | 88.23% | 100% | 77.77% |
| `src/Filters/GetLocaleCollectionItem.js` | 12.76% | 12.76% | 0% | 100% |
| `src/Filters/Slug.js` | 100% | 100% | 100% | 100% |
| `src/Filters/Slugify.js` | 100% | 100% | 100% | 100% |
| `src/Filters/Url.js` | 88.57% | 88.57% | 100% | 93.75% |
| `src/Plugins/HtmlBasePlugin.js` | 85% | 85% | 100% | 86.95% |
| `src/Plugins/HtmlRelativeCopyPlugin.js` | 100% | 100% | 100% | 100% |
| `src/Plugins/I18nPlugin.js` | 82.96% | 82.96% | 100% | 80.55% |
| `src/Plugins/IdAttributePlugin.js` | 97.27% | 97.27% | 100% | 90% |
| `src/Plugins/InputPathToUrl.js` | 90.05% | 90.05% | 100% | 78.12% |
| `src/Plugins/Pagination.js` | 90.23% | 90.23% | 95% | 84% |
| `src/Plugins/RenderPlugin.js` | 87.69% | 87.69% | 86.36% | 77.77% |
| `src/Util/ArrayUtil.js` | 100% | 100% | 100% | 100% |
| `src/Util/AsyncEventEmitter.js` | 95.45% | 95.45% | 100% | 89.47% |
| `src/Util/Compatibility.js` | 79.66% | 79.66% | 75% | 77.77% |
| `src/Util/ConsoleLogger.js` | 100% | 100% | 95% | 100% |
| `src/Util/DateGitFirstAdded.js` | 100% | 100% | 100% | 100% |
| `src/Util/DateGitLastUpdated.js` | 100% | 100% | 100% | 100% |
| `src/Util/DirContains.js` | 100% | 100% | 100% | 100% |
| `src/Util/EsmResolver.js` | 84.9% | 84.9% | 100% | 85.71% |
| `src/Util/ExistsCache.js` | 96.77% | 96.77% | 85.71% | 100% |
| `src/Util/FilePathUtil.js` | 47.36% | 47.36% | 50% | 100% |
| `src/Util/FileSystemManager.js` | 72.91% | 72.91% | 66.66% | 87.5% |
| `src/Util/GetJavaScriptData.js` | 100% | 100% | 100% | 100% |
| `src/Util/GlobMatcher.js` | 90.9% | 90.9% | 100% | 66.66% |
| `src/Util/GlobRemap.js` | 97.64% | 97.64% | 90% | 100% |
| `src/Util/HtmlRelativeCopy.js` | 90.6% | 90.6% | 100% | 89.18% |
| `src/Util/HtmlTransformer.js` | 90.11% | 90.11% | 88.88% | 90.69% |
| `src/Util/ImportJsonSync.js` | 84.41% | 84.41% | 83.33% | 92.3% |
| `src/Util/IsAsyncFunction.js` | 100% | 100% | 50% | 100% |
| `src/Util/JavaScriptDependencies.js` | 89.09% | 89.09% | 50% | 85.71% |
| `src/Util/MemoizeFunction.js` | 100% | 100% | 100% | 100% |
| `src/Util/PassthroughCopyBehaviorCheck.js` | 100% | 100% | 100% | 100% |
| `src/Util/PathNormalizer.js` | 93.1% | 93.1% | 100% | 86.66% |
| `src/Util/PathPrefixer.js` | 100% | 100% | 100% | 100% |
| `src/Util/Pluralize.js` | 100% | 100% | 100% | 100% |
| `src/Util/ProjectDirectories.js` | 96.74% | 96.74% | 97.29% | 96.11% |
| `src/Util/ProjectTemplateFormats.js` | 94.02% | 94.02% | 90% | 94.73% |
| `src/Util/PromiseUtil.js` | 46.66% | 46.66% | 100% | 66.66% |
| `src/Util/Require.js` | 82.94% | 82.94% | 75% | 82.05% |
| `src/Util/ReservedData.js` | 97.1% | 97.1% | 100% | 92.85% |
| `src/Util/SetUnion.js` | 100% | 100% | 100% | 100% |
| `src/Util/SpawnAsync.js` | 96.55% | 96.55% | 100% | 87.5% |
| `src/Util/TemplateDepGraph.js` | 96.25% | 96.25% | 100% | 93.61% |
| `src/Util/TransformsUtil.js` | 94.28% | 94.28% | 100% | 83.33% |
| `src/Util/ValidUrl.js` | 100% | 100% | 100% | 100% |
| `src/Util/Objects/DeepFreeze.js` | 90% | 90% | 100% | 80% |
| `src/Util/Objects/ObjectFilter.js` | 100% | 100% | 100% | 80% |
| `src/Util/Objects/ProxyWrap.js` | 96.61% | 96.61% | 100% | 94.73% |
| `src/Util/Objects/Sortable.js` | 100% | 100% | 100% | 100% |
| `src/Util/Objects/Unique.js` | 100% | 100% | 100% | 100% |
================================================
FILE: docs/coverage.njk
================================================
---
permalink: coverage.md
---
# Code Coverage for Eleventy v{{ pkg.version }}
| Filename | % Lines | % Statements | % Functions | % Branches |
| --- | --- | --- | --- | --- |
{% for file, line in coverage -%}
| `{{ file | removeDir }}` | {{ line.lines.pct }}% | {{ line.statements.pct }}% | {{ line.functions.pct }}% | {{ line.branches.pct }}% |
{% endfor -%}
================================================
FILE: docs/eleventy.coverage.js
================================================
import { dirname } from "path";
import { fileURLToPath } from "url";
import { TemplatePath } from "@11ty/eleventy-utils";
const __dirname = dirname(fileURLToPath(import.meta.url));
export default function (eleventyConfig) {
eleventyConfig.addFilter("removeDir", function (str) {
return TemplatePath.stripLeadingSubPath(str, TemplatePath.join(__dirname, ".."));
});
return {
templateFormats: ["njk"],
dir: {
input: "docs/coverage.njk",
output: "docs/", // root relative
},
};
}
================================================
FILE: docs/release-instructions.md
================================================
# Dependency notes
- (dev dep only) `@iarna/toml` has a 3.0 that we have never been on but it was released the same day as the last 2.x https://github.com/BinaryMuse/toml-node/commits/master (needs more investigation)
# Release Procedure
1. (Optional) Update minor dependencies in package.json
- `npx npm-check-updates --target minor -u --dep prod`
- or `npm outdated` + `npm update --save`
1. Stable release only: make sure there aren’t any `@11ty/*` dependencies on pre-release versions alpha/beta/canary
1. If the minimum Node version changed, make sure you update `package.json` engines property.
- Make sure the error message works correctly for Node versions less than 10.
- 0.12.x+ requires Node 10+
- 1.x+ requires Node 12+
- 2.x+ requires Node 14+
- 3.x+ requires Node 18+
- 4.x+ requires Node 20+
1. `rm -rf node_modules && rm -f package-lock.json && npm install`
1. `npm audit --omit=dev`
1. Make sure `npm run check` (eslint) runs okay
1. Make sure `npm run test` (ava) runs okay
1. Update version in `package.json`
- (Alpha) Use `-alpha.1` suffix
- (Beta) Use `-beta.1` suffix
1. Run `npm run coverage`
1. Check it all in and commit
1. Tag new version
1. Wait for GitHub Actions to complete to know that the build did not fail.
1. Publish a release on GitHub at https://github.com/11ty/eleventy/releases pointing to the tag of the release. Hitting the publish button on this workflow will use GitHub Actions to publish the package to npm on the correct dist-tag and includes npm package provenance for the release.
- Main release: no version suffix publishes to `latest` (default) tag on npm
- Make sure to include OpenCollective usernames for release notes here https://www.11ty.dev/supporters-for-release-notes/
- Canary release: `-alpha.` version suffix in `package.json` publishes to `canary` tag on npm: https://github.com/11ty/eleventy/issues/2758
- Beta release: `-beta.` version suffix publishes to `beta` tag on npm
Unfortunate note about npm and tags (specifically `canary` here): if you push a 1.0.0-canary.x to `canary` (even though `2.0.0-canary.x` exists), it will use the last pushed tag when you npm install from `@canary` (not the highest version number)
# Docs/Website (Main releases only)
1. Maybe search for `-alpha.` (`-canary.`?) or `-beta.` in the docs copy to update to the stable release, if applicable.
1. Check in a new `11ty-website` site with updated `package.json` version.
1. Add version to `11ty-website` `versions.json`
1. Commit it
1. Create a new branch for branched version
1. (Main) Check out the previous version git branch and add `outdated: true` to `_data/config.json` and commit/push.
1. Go to https://app.netlify.com/sites/11ty/settings/domain and set up a subdomain for it.
# Downstream dependencies
1. Update `eleventy-base-blog` to use new version
1. Update `11ty-website` to use new version
================================================
FILE: eslint.config.js
================================================
import globals from "globals";
import pluginJs from "@eslint/js";
import stylisticJs from "@stylistic/eslint-plugin-js";
import prettier from "eslint-config-prettier";
export const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
export const GLOB_TESTS = [
`**/test/**/*.${GLOB_SRC_EXT}`,
`**/__tests__/**/*.${GLOB_SRC_EXT}`,
`**/*.spec.${GLOB_SRC_EXT}`,
`**/*.test.${GLOB_SRC_EXT}`,
`**/*.bench.${GLOB_SRC_EXT}`,
`**/*.benchmark.${GLOB_SRC_EXT}`,
];
export default [
{
name: "11ty/setup/js",
...pluginJs.configs.recommended,
},
{
name: "11ty/rules/project-specific",
plugins: {
"@stylistic/js": stylisticJs,
},
languageOptions: {
globals: {
...globals.node,
},
ecmaVersion: "latest",
sourceType: "module",
},
rules: {
"no-async-promise-executor": "warn",
"no-prototype-builtins": "warn",
"no-unused-vars": "warn",
"@stylistic/js/space-unary-ops": "error",
},
},
{
name: "11ty/ignores",
files: GLOB_TESTS,
rules: {
"no-unused-vars": "off",
},
},
{
name: "11ty/setup/prettier",
...prettier,
},
];
================================================
FILE: package.json
================================================
{
"name": "@11ty/eleventy",
"version": "4.0.0-alpha.6",
"description": "A simpler static site generator.",
"publishConfig": {
"access": "public",
"provenance": true
},
"type": "module",
"main": "./src/Eleventy.js",
"exports": {
".": {
"import": "./src/Eleventy.js",
"require": "./src/EleventyCommonJs.cjs"
},
"./UserConfig": {
"types": "./src/UserConfig.js"
},
"./utils/git": "./src/Util/Git.js"
},
"bin": {
"eleventy": "cmd.cjs"
},
"license": "MIT",
"engines": {
"node": ">=20.19"
},
"workspaces": [
"packages/client"
],
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/11ty"
},
"keywords": [
"static-site-generator",
"static-site",
"ssg",
"documentation",
"website",
"jekyll",
"blog",
"templates",
"generator",
"framework",
"eleventy",
"11ty",
"html",
"markdown",
"liquid",
"nunjucks"
],
"scripts": {
"default": "npm run test",
"test": "npm run test:server && npm run test:client",
"test:server": "npm run test:node && npm run test:ava",
"test:ava": "ava --verbose --timeout 20s",
"test:node": "node --test test_node/tests.js",
"test:client": "cross-env CI=true npm run test --workspaces",
"format": "prettier . --write",
"check": "eslint src",
"check-types": "tsc",
"nano-staged": "nano-staged",
"coverage": "npx c8 ava && npx c8 report --reporter=json-summary && cp coverage/coverage-summary.json docs/_data/coverage.json && node cmd.cjs --config=docs/eleventy.coverage.js",
"prepare": "simple-git-hooks"
},
"author": "Zach Leatherman <zachleatherman@gmail.com> (https://zachleat.com/)",
"repository": {
"type": "git",
"url": "git+https://github.com/11ty/eleventy.git"
},
"bugs": "https://github.com/11ty/eleventy/issues",
"homepage": "https://www.11ty.dev/",
"ava": {
"environmentVariables": {},
"failFast": true,
"files": [
"./test/*.js",
"./test/_issues/**/*test.js"
],
"watchMode": {
"ignoreChanges": [
"./test/stubs*/**/*",
"./test/**/_site/**/*",
".cache"
]
}
},
"nano-staged": {
"*.{js,css,md}": [
"prettier --write"
]
},
"simple-git-hooks": {
"pre-commit": "npm test && npm run nano-staged",
"pre-push": "npm test"
},
"devDependencies": {
"@11ty/eleventy-img": "^6.0.4",
"@11ty/eleventy-plugin-rss": "^2.0.4",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"@11ty/eleventy-plugin-webc": "^0.12.0-beta.7",
"@eslint/js": "^10.0.1",
"@iarna/toml": "^2.2.5",
"@mdx-js/node-loader": "^3.1.1",
"@stylistic/eslint-plugin-js": "^4.4.1",
"@types/node": "^25.5.0",
"@vue/server-renderer": "^3.5.30",
"@zachleat/noop": "^1.0.7",
"ava": "^6.4.1",
"c8": "^10.1.3",
"cross-env": "^10.1.0",
"eslint": "^10.0.3",
"eslint-config-prettier": "^10.1.8",
"globals": "^17.4.0",
"jsx-async-runtime": "^2.0.3",
"luxon": "^3.7.2",
"markdown-it-abbr": "^2.0.0",
"markdown-it-emoji": "^3.0.0",
"marked": "^17.0.4",
"nano-staged": "^0.9.0",
"prettier": "^3.8.1",
"pretty": "^2.0.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"sass": "^1.98.0",
"simple-git-hooks": "^2.13.1",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vue": "^3.5.30",
"zod": "^4.3.6",
"zod-validation-error": "^5.0.0"
},
"dependencies": {
"@11ty/dependency-tree": "^4.0.2",
"@11ty/dependency-tree-esm": "^2.0.4",
"@11ty/dependency-tree-typescript": "^1.0.0",
"@11ty/eleventy-dev-server": "^3.0.0-alpha.6",
"@11ty/eleventy-plugin-bundle": "^3.0.7",
"@11ty/eleventy-utils": "^2.0.7",
"@11ty/gray-matter": "^2.0.1",
"@11ty/lodash-custom": "^4.17.21",
"@11ty/node-version-check": "^1.0.1",
"@11ty/nunjucks": "^4.0.0-alpha.1",
"@11ty/parse-date-strings": "^2.0.6",
"@11ty/posthtml-urls": "^1.0.2",
"@11ty/recursive-copy": "^5.0.2",
"@sindresorhus/slugify": "^3.0.0",
"bcp-47-normalize": "^2.3.0",
"chokidar": "^5.0.0",
"debug": "^4.4.3",
"dependency-graph": "^1.0.0",
"entities": "^7.0.1",
"import-module-string": "^2.0.3",
"iso-639-1": "^3.1.5",
"kleur": "^4.1.5",
"liquidjs": "^10.25.0",
"markdown-it": "^14.1.1",
"minimist": "^1.2.8",
"moo": "0.5.2",
"node-retrieve-globals": "^6.0.1",
"picomatch": "^4.0.3",
"posthtml": "^0.16.7",
"posthtml-match-helper": "^2.0.3",
"semver": "^7.7.4",
"tinyglobby": "^0.2.15"
},
"overrides": {
"fdir": "6.4.6"
}
}
================================================
FILE: packages/client/README.md
================================================
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="eleventy Logo"></p>
# `@11ty/client`
The client (browser-friendly) version of `@11ty/eleventy` Eleventy, a simpler static site generator.
## ➡ [Documentation](https://www.11ty.dev/docs/)
- Star [this repo on GitHub](https://github.com/11ty/eleventy/)!
- Follow us [on Mastodon `@11ty@neighborhood.11ty.dev`](https://neighborhood.11ty.dev/@11ty)
- Follow us [on Bluesky `@11ty.dev`](https://bsky.app/profile/11ty.dev)
- Install [from npm](https://www.npmjs.com/org/11ty)
- Follow [on GitHub](https://github.com/11ty)
- Watch us [on YouTube](https://www.youtube.com/c/EleventyVideo)
- Chat on [Discord](https://www.11ty.dev/blog/discord/)
- Latest: [](https://www.npmjs.com/package/@11ty/client)
## Installation
```
npm install @11ty/client --save
```
With exports for:
- `@11ty/client`
- `@11ty/client/md` (Markdown Template Engine)
- `@11ty/client/njk` (Nunjucks Template Engine)
- `@11ty/client/liquid` (Liquid Template Engine)
- `@11ty/client/i18n` (i18n Plugin)
================================================
FILE: packages/client/generate-bundle.js
================================================
import fs from "node:fs";
import { default as bundleClient } from "@11ty/package-bundler";
import pkg from "../../package.json" with { type: "json" };
import { readableFileSize } from "../../src/Util/FileSize.js";
const PREFIX = `[11ty/bundle/client] `;
function size(filepath) {
return readableFileSize(fs.statSync(filepath).size);
}
await bundleClient("./src/BundleCore.js", "./dist/eleventy.core.js", {
name: `Eleventy v${pkg.version} (@11ty/client Bundle)`,
moduleRoot: "../../",
// No core-bundled plugins, reduced feature set
adapterSuffixes: [".client.js", ".core.js", ".core.cjs"],
external: ["node:fs", "node:crypto", "@sindresorhus/slugify"],
esbuild: {
keepNames: false,
// minify: true
},
});
console.log(`${PREFIX}Wrote dist/eleventy.core.js: ${size("./dist/eleventy.core.js")}`);
// Careful, this one is big!
await bundleClient("./src/BundleEleventy.js", `./dist/eleventy.js`, {
name: `Eleventy v${pkg.version} (@11ty/client/eleventy Bundle)`,
moduleRoot: "../../",
adapterSuffixes: [".core.js", ".core.cjs"],
// Adds named export FileSystem for using the file system in other packages
fileSystemMode: "publish",
});
console.log(`${PREFIX}Wrote dist/eleventy.js: ${size("./dist/eleventy.js")}`);
// fs.mkdirSync("./visualize/", { recursive: true });
// fs.writeFileSync("./visualize/meta.json", JSON.stringify(result.metafile));
// npx esbuild-visualizer --metadata ./packages/client/visualize/meta.json --filename packages/client/visualize/index.html
await bundleClient(
import.meta.resolve("./src/BundleLiquid.js"),
`./dist/formats/eleventy-liquid.js`,
{
name: `Eleventy v${pkg.version} (@11ty/client/liquid Engine Bundle)`,
moduleRoot: "../../",
adapterSuffixes: [".core.js", ".core.cjs"],
},
);
console.log(
`${PREFIX}Wrote dist/formats/eleventy-liquid.js: ${size("./dist/formats/eleventy-liquid.js")}`,
);
await bundleClient(
import.meta.resolve("./src/BundleNunjucks.js"),
`./dist/formats/eleventy-nunjucks.js`,
{
name: `Eleventy v${pkg.version} (@11ty/client/njk Engine Bundle)`,
moduleRoot: "../../",
},
);
console.log(
`${PREFIX}Wrote dist/formats/eleventy-nunjucks.js: ${size("./dist/formats/eleventy-nunjucks.js")}`,
);
await bundleClient(
import.meta.resolve("./src/BundleMarkdown.js"),
`./dist/formats/eleventy-markdown.js`,
{
name: `Eleventy v${pkg.version} (@11ty/client/md Engine Bundle)`,
moduleRoot: "../../",
adapterSuffixes: [".core.js", ".core.cjs"],
},
);
console.log(
`${PREFIX}Wrote dist/formats/eleventy-markdown.js: ${size("./dist/formats/eleventy-markdown.js")}`,
);
await bundleClient(
import.meta.resolve("./src/BundleI18nPlugin.js"),
`./dist/plugins/eleventy-plugin-i18n.js`,
{
name: `Eleventy v${pkg.version} (i18n Plugin)`,
moduleRoot: "../../",
adapterSuffixes: [".core.js", ".core.cjs"],
},
);
console.log(
`${PREFIX}Wrote dist/plugins/eleventy-plugin-i18n.js: ${size("./dist/plugins/eleventy-plugin-i18n.js")}`,
);
================================================
FILE: packages/client/package.json
================================================
{
"name": "@11ty/client",
"description": "Run Eleventy in your browser.",
"version": "PRIVATE",
"private": true,
"publishConfig": {
"access": "public",
"provenance": true
},
"type": "module",
"main": "./dist/eleventy.core.js",
"exports": {
".": "./dist/eleventy.core.js",
"./eleventy": "./dist/eleventy.js",
"./liquid": "./dist/formats/eleventy-liquid.js",
"./njk": "./dist/formats/eleventy-nunjucks.js",
"./md": "./dist/formats/eleventy-markdown.js",
"./i18n": "./dist/plugins/eleventy-plugin-i18n.js"
},
"files": [
"./dist/**/*.js"
],
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/11ty"
},
"scripts": {
"build": "node generate-bundle.js",
"test": "npm run build && npx vitest",
"prepare": "npm run build"
},
"author": "Zach Leatherman <zachleatherman@gmail.com> (https://zachleat.com/)",
"repository": {
"type": "git",
"url": "git://github.com/11ty/eleventy.git"
},
"bugs": "https://github.com/11ty/eleventy/issues",
"homepage": "https://www.11ty.dev/",
"devDependencies": {
"@11ty/package-bundler": "^0.5.5",
"@vitest/browser": "^4.0.5",
"@vitest/browser-playwright": "^4.0.5",
"playwright": "^1.56.1",
"vitest": "^4.0.5"
}
}
================================================
FILE: packages/client/src/BundleCore.js
================================================
// see BundleEleventy.js for Core WITH bundled Eleventy core plugins
import "./shims/shim-core.js";
export { MinimalCore as Eleventy } from "../../../src/CoreMinimal.js";
================================================
FILE: packages/client/src/BundleEleventy.js
================================================
import "./shims/shim-core.js";
// @11ty/eleventy-plugin-bundle is not exported here (differing from Node package) but *is* bundled (and exposed via Configuration API)
export { IdAttributePlugin } from "../../../src/Plugins/IdAttributePlugin.js";
export { default as HtmlBasePlugin } from "../../../src/Plugins/HtmlBasePlugin.js";
export { TransformPlugin as InputPathToUrlTransformPlugin } from "../../../src/Plugins/InputPathToUrl.js";
export { default as RenderPlugin } from "../../../src/Plugins/RenderPlugin.js";
// i18n Plugin is separate (see BundleI18nPlugin.js and @11ty/client/i18n)
// Note for future visitors, an attempt was made to separate these plugins the bundle (so that they could be exported separately)
// - HtmlBasePlugin and InputPathToUrl were moved to async in the ResolvePlugin.js adapter.
// - Extended configuration was removed from defaultConfig.js
// This saved ~400KB (unmin) from the bundle but the separate bundle was way larger than the savings (> 1MB)
export { Core as Eleventy } from "../../../src/Core.js";
export { default as FileSystem } from "node:fs";
================================================
FILE: packages/client/src/BundleI18nPlugin.js
================================================
export { default as I18nPlugin } from "../../../src/Plugins/I18nPlugin.js";
================================================
FILE: packages/client/src/BundleLiquid.js
================================================
export { default as Liquid } from "../../../src/Engines/Liquid.js";
================================================
FILE: packages/client/src/BundleMarkdown.js
================================================
export { default as Markdown } from "../../../src/Engines/Markdown.js";
================================================
FILE: packages/client/src/BundleNunjucks.js
================================================
export { default as Nunjucks } from "../../../src/Engines/Nunjucks.js";
================================================
FILE: packages/client/src/shims/process.cjs
================================================
// MIT Licensed
// https://github.com/defunctzombie/node-process/blob/master/browser.js
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
================================================
FILE: packages/client/src/shims/shim-core.js
================================================
import * as process from "./process.cjs";
// `path` polyfill needs this
window.process = globalThis.process = process;
// `recursive-copy` needs this (not necessary for Core.js)
window.global = globalThis || window;
// @11ty/eleventy needs this
class Buffer {
static [Symbol.hasInstance](instance) {
return this.isBuffer(instance);
}
static isBuffer() {
return false;
}
}
window.Buffer = globalThis.Buffer = Buffer;
================================================
FILE: packages/client/test/client-core.test.js
================================================
import { Eleventy } from "../dist/eleventy.core.js";
import sharedTests from "./shared-tests.js";
sharedTests(Eleventy);
================================================
FILE: packages/client/test/client-eleventy.test.js
================================================
import { Eleventy } from "../dist/eleventy.js";
import sharedTests from "./shared-tests.js";
sharedTests(Eleventy);
================================================
FILE: packages/client/test/shared-tests.js
================================================
import { assert, test } from "vitest";
import { Markdown } from "../dist/formats/eleventy-markdown.js";
import { Liquid } from "../dist/formats/eleventy-liquid.js";
import { Nunjucks } from "../dist/formats/eleventy-nunjucks.js";
import { I18nPlugin } from "../dist/plugins/eleventy-plugin-i18n.js";
export default function(Eleventy) {
test("Get version number", async () => {
assert.typeOf(Eleventy.getVersion(), "string");
});
test("Markdown (no preprocessor) template", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("md", Markdown);
eleventyConfig.setMarkdownTemplateEngine(false);
eleventyConfig.setHtmlTemplateEngine(false);
eleventyConfig.setTemplateFormats("md");
eleventyConfig.addTemplate("index.md", `# Heading`);
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `<h1>Heading</h1>`);
});
test("Markdown (via Liquid) template", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("md", Markdown);
eleventyConfig.addEngine("liquid", Liquid);
eleventyConfig.setTemplateFormats("md");
eleventyConfig.addTemplate("index.md", `# {{ title }}`, {
title: "Heading"
});
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `<h1>Heading</h1>`);
});
test("Liquid template", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("liquid", Liquid);
eleventyConfig.setTemplateFormats("liquid");
eleventyConfig.addTemplate("index.liquid", `<h1>{{ title }}</h1>`, { title: "Heading" });
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `<h1>Heading</h1>`);
});
test("Nunjucks template", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("njk", Nunjucks);
eleventyConfig.setTemplateFormats("njk");
eleventyConfig.addTemplate("index.njk", `<h1>{{ title }}</h1>`, { title: "Heading" });
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `<h1>Heading</h1>`);
});
test("i18n Plugin Use (with 11ty.js)", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addPlugin(I18nPlugin, {
defaultLanguage: "en"
});
eleventyConfig.addTemplate("./en/index.11ty.js", function (data) {
return `<a href="${this.locale_url("/")}">Home</a>`;
});
eleventyConfig.addTemplate("./es/index.11ty.js", function (data) {
return `<a href="${this.locale_url("/")}">Home</a>`;
});
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `<a href="/en/">Home</a>`);
assert.strictEqual(json[1].content.trim(), `<a href="/es/">Home</a>`);
});
// Careful, `@11ty/client` will resolve slugify via Vite instead of it bundled with the package
test("slugify Filter in Liquid", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("liquid", Liquid);
eleventyConfig.setTemplateFormats("liquid");
eleventyConfig.addTemplate("index.liquid", `{{ title | slugify }}`, { title: "This is a heading" });
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `this-is-a-heading`);
});
// Careful, `@11ty/client` will resolve slugify via Vite instead of it bundled with the package
test("slugify Filter in Nunjucks", async () => {
let elev = new Eleventy({
config(eleventyConfig) {
eleventyConfig.addEngine("njk", Nunjucks);
eleventyConfig.setTemplateFormats("njk");
eleventyConfig.addTemplate("index.njk", `{{ title | slugify }}`, { title: "This is a heading" });
}
});
let json = await elev.toJSON();
assert.strictEqual(json[0].content.trim(), `this-is-a-heading`);
});
}
================================================
FILE: packages/client/update-package-json.js
================================================
// Intended to run from repository root in release.sh script
import fs from "node:fs";
import corePkg from "../../package.json" with { type: "json" };
// assign new version in local package.json from core package.json
import clientPkg from "./package.json" with { type: "json" };
clientPkg.version = corePkg.version;
delete clientPkg.private; // allow publish
if (
corePkg.name !== "@11ty/eleventy" ||
clientPkg.name !== "@11ty/client" ||
!fs.existsSync("./packages/client/package.json")
) {
throw new Error("Did you run this script from the wrong directory?");
}
fs.writeFileSync("./packages/client/package.json", JSON.stringify(clientPkg, null, 2), "utf8");
console.log(`[11ty/bundle/client] Updated @11ty/client package version to ${corePkg.version}`);
================================================
FILE: packages/client/vitest.config.js
================================================
import { defineConfig } from "vitest/config";
import { playwright } from "@vitest/browser-playwright";
import os from "node:os";
let instances = [{ browser: "chromium" }, { browser: "firefox" }];
if (os.type() === "Darwin") {
instances.push({ browser: "webkit" });
}
export default defineConfig({
test: {
browser: {
enabled: true,
provider: playwright(),
headless: true,
screenshotFailures: false,
// https://vitest.dev/guide/browser/playwright
instances,
},
},
});
================================================
FILE: scripts/release-dryrun.sh
================================================
export NPM_PUBLISH_TAG="canary"
export DRY_RUN="--dry-run" # leave that space as-is
echo "Running @11ty/eleventy and @11ty/client publish dry run test"
./scripts/release.sh
================================================
FILE: scripts/release.sh
================================================
if ! npm ci; then
echo 'Release error: npm ci command failed.'
exit 1
fi
if ! npx playwright install; then
echo 'Release error: npx playwright install command failed (for Vitest Browser Mode).'
exit 1
fi
# This step includes running packages/ test suites
if ! npm test; then
echo 'Release error: npm test command failed.'
exit 1
fi
if [ -z "$NPM_PUBLISH_TAG" ]; then
echo 'Release error: missing NPM_PUBLISH_TAG environment variable'
exit 1
fi
node packages/client/update-package-json.js
# Will skip publishing root if publishing workspaces fails
if npm publish --workspaces --provenance --access=public --tag=$NPM_PUBLISH_TAG $DRY_RUN; then
npm publish --provenance --access=public --tag=$NPM_PUBLISH_TAG $DRY_RUN
fi
================================================
FILE: src/Adapters/Engines/Liquid.core.js
================================================
// Must load dynamically in standard core
export default undefined;
================================================
FILE: src/Adapters/Engines/Liquid.js
================================================
export { default } from "../../Engines/Liquid.js";
================================================
FILE: src/Adapters/Engines/Markdown.core.js
================================================
// Must load dynamically in standard core
export default undefined;
================================================
FILE: src/Adapters/Engines/Markdown.js
================================================
export { default } from "../../Engines/Markdown.js";
================================================
FILE: src/Adapters/Engines/Nunjucks.core.js
================================================
// Must load dynamically in standard core
export default undefined;
================================================
FILE: src/Adapters/Engines/Nunjucks.js
================================================
export { default } from "../../Engines/Nunjucks.js";
================================================
FILE: src/Adapters/Packages/chalk.client.js
================================================
function noop(arg) {
return arg;
}
export default {
bold: noop,
red: noop,
gray: noop,
cyan: noop,
yellow: noop,
};
================================================
FILE: src/Adapters/Packages/chalk.js
================================================
import chalk from "kleur";
export default chalk;
================================================
FILE: src/Adapters/Packages/inspect.core.js
================================================
export function inspect(target) {
return JSON.stringify(target, null, 2);
}
================================================
FILE: src/Adapters/Packages/inspect.js
================================================
import { inspect as nodeInspect } from "node:util";
export function inspect(target) {
return nodeInspect(target, { showHidden: false, depth: null });
}
================================================
FILE: src/Adapters/Packages/semver.client.js
================================================
export function satisfies(version, range) {
// Always return true
return true;
}
================================================
FILE: src/Adapters/Packages/semver.js
================================================
// Costs ~18 KB
import semverSatisfies from "semver/functions/satisfies.js";
export { semverSatisfies as satisfies };
================================================
FILE: src/Adapters/Packages/url.core.js
================================================
import path from "node:path";
// TODO move this into package-bundler as a shim?
// Thank you bare-url!
// Apache-2.0 LICENSE https://github.com/holepunchto/bare-url/blob/main/LICENSE
export function fileURLToPath(url) {
if (typeof url === "string") {
url = new URL(url);
}
if (url.protocol !== "file:") {
throw new Error("The URL must use the file: protocol");
}
if (url.hostname) {
throw new Error("The file: URL host must be 'localhost' or empty");
}
if (/%2f/i.test(url.pathname)) {
throw new Error("The file: URL path must not include encoded / characters");
}
return path.normalize(decodeURIComponent(url.pathname));
}
================================================
FILE: src/Adapters/Packages/url.js
================================================
export { fileURLToPath } from "node:url";
================================================
FILE: src/Adapters/getDefaultConfig.core.js
================================================
import defaultConfig from "../defaultConfig.js";
// Standard and minimal bundle import directly for bundling
export default async function () {
return defaultConfig;
}
================================================
FILE: src/Adapters/getDefaultConfig.js
================================================
// Standard
export default async function () {
return import("../defaultConfig.js").then((mod) => mod.default);
}
================================================
FILE: src/Benchmark/Benchmark.js
================================================
export default class Benchmark {
constructor() {
// TypeScript slop
this.timeSpent = 0;
this.timesCalled = 0;
this.beforeTimers = [];
}
reset() {
this.timeSpent = 0;
this.timesCalled = 0;
this.beforeTimers = [];
}
getNewTimestamp() {
if (performance) {
return performance.now();
}
return new Date().getTime();
}
incrementCount() {
this.timesCalled++;
}
// TODO(slightlyoff):
// disable all of these hrtime requests when not benchmarking
before() {
this.timesCalled++;
this.beforeTimers.push(this.getNewTimestamp());
}
after() {
if (!this.beforeTimers.length) {
throw new Error("You called Benchmark after() without a before().");
}
let before = this.beforeTimers.pop();
if (!this.beforeTimers.length) {
this.timeSpent += this.getNewTimestamp() - before;
}
}
getTimesCalled() {
return this.timesCalled;
}
getTotal() {
return this.timeSpent;
}
}
================================================
FILE: src/Benchmark/BenchmarkGroup.js
================================================
import debugUtil from "debug";
import ConsoleLogger from "../Util/ConsoleLogger.js";
import isAsyncFunction from "../Util/IsAsyncFunction.js";
import Benchmark from "./Benchmark.js";
const debugBenchmark = debugUtil("Eleventy:Benchmark");
class BenchmarkGroup {
constructor() {
this.benchmarks = {};
// Warning: aggregate benchmarks automatically default to false via BenchmarkManager->getBenchmarkGroup
this.isVerbose = true;
this.logger = new ConsoleLogger();
this.minimumThresholdMs = 50;
this.minimumThresholdPercent = 8;
}
setIsVerbose(isVerbose) {
this.isVerbose = isVerbose;
this.logger.isVerbose = isVerbose;
}
reset() {
for (var type in this.benchmarks) {
this.benchmarks[type].reset();
}
}
// TODO use addAsync everywhere instead
add(type, callback) {
let benchmark = (this.benchmarks[type] = new Benchmark());
/** @this {any} */
let fn = function (...args) {
benchmark.before();
let ret = callback.call(this, ...args);
benchmark.after();
return ret;
};
Object.defineProperty(fn, "__eleventyInternal", {
value: {
type: isAsyncFunction(callback) ? "async" : "sync",
callback,
},
});
return fn;
}
// callback must return a promise
// async addAsync(type, callback) {
// let benchmark = (this.benchmarks[type] = new Benchmark());
// benchmark.before();
// // don’t await here.
// let promise = callback.call(this);
// promise.then(function() {
// benchmark.after();
// });
// return promise;
// }
setMinimumThresholdMs(minimumThresholdMs) {
let val = parseInt(minimumThresholdMs, 10);
if (isNaN(val)) {
throw new Error("`setMinimumThresholdMs` expects a number argument.");
}
this.minimumThresholdMs = val;
}
setMinimumThresholdPercent(minimumThresholdPercent) {
let val = parseInt(minimumThresholdPercent, 10);
if (isNaN(val)) {
throw new Error("`setMinimumThresholdPercent` expects a number argument.");
}
this.minimumThresholdPercent = val;
}
has(type) {
return !!this.benchmarks[type];
}
get(type) {
if (!this.benchmarks[type]) {
this.benchmarks[type] = new Benchmark();
}
return this.benchmarks[type];
}
padNumber(num, length) {
if (("" + num).length >= length) {
return num;
}
let prefix = new Array(length + 1).join(" ");
return (prefix + num).slice(-1 * length);
}
finish(label, totalTimeSpent) {
for (var type in this.benchmarks) {
let bench = this.benchmarks[type];
let isAbsoluteMinimumComparison = this.minimumThresholdMs > 0;
let totalForBenchmark = bench.getTotal();
let percent = Math.round((totalForBenchmark * 100) / totalTimeSpent);
let callCount = bench.getTimesCalled();
let output = {
ms: this.padNumber(totalForBenchmark.toFixed(0), 6),
percent: this.padNumber(percent, 3),
calls: this.padNumber(callCount, 5),
};
let str = `Benchmark ${output.ms}ms ${output.percent}% ${output.calls}× (${label}) ${type}`;
if (
isAbsoluteMinimumComparison &&
totalForBenchmark >= this.minimumThresholdMs &&
percent > this.minimumThresholdPercent
) {
this.logger.warn(str);
}
// Opt out of logging if low count (1× or 2×) or 0ms / 1%
if (
callCount > 1 || // called more than once
Math.round(totalForBenchmark) > 0 // more than 0.5ms
) {
debugBenchmark(str);
}
}
}
}
export default BenchmarkGroup;
================================================
FILE: src/Benchmark/BenchmarkManager.js
================================================
import BenchmarkGroup from "./BenchmarkGroup.js";
// TODO this should not be a singleton, it belongs in the config or somewhere on the Eleventy instance.
class BenchmarkManager {
constructor() {
this.benchmarkGroups = {};
this.isVerbose = true;
this.start = this.getNewTimestamp();
}
reset() {
this.start = this.getNewTimestamp();
for (var j in this.benchmarkGroups) {
this.benchmarkGroups[j].reset();
}
}
getNewTimestamp() {
if (performance) {
return performance.now();
}
return new Date().getTime();
}
setVerboseOutput(isVerbose) {
this.isVerbose = !!isVerbose;
}
hasBenchmarkGroup(name) {
return name in this.benchmarkGroups;
}
getBenchmarkGroup(name) {
if (!this.benchmarkGroups[name]) {
this.benchmarkGroups[name] = new BenchmarkGroup();
// Special behavior for aggregate benchmarks
// so they don’t console.log every time
if (name === "Aggregate") {
this.benchmarkGroups[name].setIsVerbose(false);
} else {
this.benchmarkGroups[name].setIsVerbose(this.isVerbose);
}
}
return this.benchmarkGroups[name];
}
getAll() {
return this.benchmarkGroups;
}
get(name) {
if (name) {
return this.getBenchmarkGroup(name);
}
return this.getAll();
}
finish() {
let totalTimeSpentBenchmarking = this.getNewTimestamp() - this.start;
for (var j in this.benchmarkGroups) {
this.benchmarkGroups[j].finish(j, totalTimeSpentBenchmarking);
}
}
}
export default BenchmarkManager;
================================================
FILE: src/Core.js
================================================
import { MinimalCore } from "./CoreMinimal.js";
import FileSystemSearch from "./FileSystemSearch.js";
import EleventyFiles from "./EleventyFiles.js";
import TemplatePassthroughManager from "./TemplatePassthroughManager.js";
// Core with File System support (but without Dev Server or Chokidar or Bundled Plugins)
export class Core extends MinimalCore {
async initializeConfig(initOverrides) {
await super.initializeConfig(initOverrides);
/** @type {object} */
this.fileSystemSearch = new FileSystemSearch();
}
async init(options = {}) {
await super.init(options);
this.templateData.setFileSystemSearch(this.fileSystemSearch);
this.passthroughManager = new TemplatePassthroughManager(this.eleventyConfig);
this.passthroughManager.setRunMode(this.runMode);
this.passthroughManager.setDryRun(this.isDryRun);
this.passthroughManager.extensionMap = this.extensionMap;
this.passthroughManager.setFileSystemSearch(this.fileSystemSearch);
let formats = this.templateFormats.getTemplateFormats();
this.eleventyFiles = new EleventyFiles(formats, this.eleventyConfig);
this.eleventyFiles.setPassthroughManager(this.passthroughManager);
this.eleventyFiles.setFileSystemSearch(this.fileSystemSearch);
this.eleventyFiles.setRunMode(this.runMode);
this.eleventyFiles.extensionMap = this.extensionMap;
// This needs to be set before init or it’ll construct a new one
this.eleventyFiles.templateData = this.templateData;
this.eleventyFiles.init();
this.writer.setPassthroughManager(this.passthroughManager);
this.writer.setEleventyFiles(this.eleventyFiles);
}
/**
* Restarts Eleventy.
*/
async restart() {
await super.restart();
// TODO
this.passthroughManager.reset();
// TODO
this.eleventyFiles.restart();
}
}
================================================
FILE: src/CoreMinimal.js
================================================
import debugUtil from "debug";
import { isPlainObject, TemplatePath } from "@11ty/eleventy-utils";
import chalk from "./Adapters/Packages/chalk.js";
import TemplateData from "./Data/TemplateData.js";
import TemplateWriter from "./TemplateWriter.js";
import EleventyExtensionMap from "./EleventyExtensionMap.js";
import { EleventyErrorHandler } from "./Errors/EleventyErrorHandler.js";
import TemplateConfig from "./TemplateConfig.js";
import TemplateEngineManager from "./Engines/TemplateEngineManager.js";
/* Utils */
import { readableFileSize } from "./Util/FileSize.js";
import simplePlural from "./Util/Pluralize.js";
import ConsoleLogger from "./Util/ConsoleLogger.js";
import ProjectDirectories from "./Util/ProjectDirectories.js";
import {
getEleventyPackageJson,
importJsonSync,
getWorkingProjectPackageJsonPath,
} from "./Util/ImportJsonSync.js";
import ProjectTemplateFormats from "./Util/ProjectTemplateFormats.js";
const pkg = getEleventyPackageJson();
const debug = debugUtil("Eleventy");
/**
* Eleventy’s programmatic API
* @module 11ty/eleventy/Eleventy
*/
export class MinimalCore {
/**
* Userspace package.json file contents
* @type {object|undefined}
*/
#projectPackageJson;
/** @type {string} */
#projectPackageJsonPath;
/** @type {ProjectTemplateFormats|undefined} */
#templateFormats;
/** @type {ConsoleLogger|undefined} */
#logger;
/** @type {ProjectDirectories|undefined} */
#directories;
/** @type {boolean|undefined} */
#verboseOverride;
/** @type {boolean} */
#isVerboseMode = true;
/** @type {boolean|undefined} */
#preInitVerbose;
/** @type {boolean} */
#hasConfigInitialized = false;
/** @type {boolean} */
#needsInit = true;
/** @type {Promise|undefined} */
#initPromise;
/** @type {EleventyErrorHandler|undefined} */
#errorHandler;
/** @type {Map} */
#privateCaches = new Map();
/** @type {boolean|undefined} */
#isEsm;
/** @type {string} */
#activeConfigurationPath;
// Support both new Eleventy(options) and new Eleventy(input, output, options)
#normalizeConstructorArguments(...args) {
let input;
let output;
let options;
let eleventyConfig;
if (isPlainObject(args[0])) {
options = args[0] || {};
input = options.input;
output = options.output;
eleventyConfig = args[1];
} else {
input = args[0];
output = args[1];
options = args[2] || {};
eleventyConfig = args[3];
}
return {
input,
output,
options,
eleventyConfig,
};
}
/**
* @typedef {object} EleventyOptions
* @property {'cli'|'script'=} source
* @property {'build'|'serve'|'watch'=} runMode
* @property {boolean=} dryRun
* @property {string=} configPath
* @property {string=} pathPrefix
* @property {boolean=} quietMode
* @property {Function=} config
* @property {string=} inputDir
* @param {string} [input] - Directory or filename for input/sources files.
* @param {string} [output] - Directory serving as the target for writing the output files.
* @param {EleventyOptions} [options={}]
* @param {TemplateConfig} [eleventyConfig]
*/
constructor(...args) {
let {
input,
output,
options = {},
eleventyConfig = null,
} = this.#normalizeConstructorArguments(...args);
/**
* @type {string|undefined}
* @description Holds the path to the input (might be a file or folder)
*/
this.rawInput = input || undefined;
/**
* @type {string|undefined}
* @description holds the path to the output directory
*/
this.rawOutput = output || undefined;
/**
* @type {module:11ty/eleventy/TemplateConfig}
* @description Override the config instance (for centralized config re-use)
*/
this.eleventyConfig = eleventyConfig;
/**
* @type {EleventyOptions}
* @description Options object passed to the Eleventy constructor
* @default {}
*/
this.options = options;
/**
* @type {'cli'|'script'}
* @description Called via CLI (`cli`) or Programmatically (`script`)
* @default "script"
*/
this.source = options.source || "script";
/**
* @type {string}
* @description One of build, serve, or watch
* @default "build"
*/
this.runMode = options.runMode || "build";
/**
* @type {boolean}
* @description Is Eleventy running in dry mode?
* @default false
*/
this.isDryRun = options.dryRun ?? false;
/**
* @type {boolean}
* @description Is this an incremental build? (only operates on a subset of input files)
* @default false
*/
this.isIncremental = false;
/**
* @type {string|undefined}
* @description If an incremental build, this is the file we’re operating on.
* @default null
*/
this.programmaticApiIncrementalFile = undefined;
/**
* @type {boolean}
* @description Should we process files on first run? (The --ignore-initial feature)
* @default true
*/
this.isRunInitialBuild = true;
/**
* @type {Number}
* @description Number of builds run on this instance.
* @default 0
*/
this.buildCount = 0;
/**
* @member {String} - Force ESM or CJS mode instead of detecting from package.json. Either cjs, esm, or auto.
* @default "auto"
*/
this.loader = this.options.loader ?? "auto";
/**
* @type {Number}
* @description The timestamp of Eleventy start.
*/
this.start = this.getNewTimestamp();
}
/**
* @type {string|undefined}
* @description An override of Eleventy's default config file paths
* @default undefined
*/
get configPath() {
return this.options.configPath;
}
/**
* @type {string}
* @description The top level directory the site pretends to reside in
* @default "/"
*/
get pathPrefix() {
return this.options.pathPrefix || "/";
}
/**
* Reads the version of Eleventy.
*
* @static
* @returns {string} - The version of Eleventy.
*/
static getVersion() {
return pkg.version;
}
/**
* @deprecated since 1.0.1, use static Eleventy.getVersion()
*/
getVersion() {
return MinimalCore.getVersion();
}
async initializeConfig(initOverrides) {
if (!this.eleventyConfig) {
this.eleventyConfig = new TemplateConfig(null, this.configPath);
} else if (this.configPath) {
await this.eleventyConfig.setProjectConfigPath(this.configPath);
}
this.#activeConfigurationPath =
this.configPath ?? this.eleventyConfig.getLocalProjectConfigFile();
this.eleventyConfig.setRunMode(this.runMode);
this.eleventyConfig.setProjectUsingEsm(this.isEsm);
this.eleventyConfig.setLogger(this.logger);
this.eleventyConfig.setDirectories(this.directories);
this.eleventyConfig.setTemplateFormats(this.templateFormats);
if (this.pathPrefix || this.pathPrefix === "") {
this.eleventyConfig.setPathPrefix(this.pathPrefix);
}
// Debug mode should always run quiet (all output goes to debug logger)
if (process.env.DEBUG) {
this.#verboseOverride = false;
} else if (this.options.quietMode === true || this.options.quietMode === false) {
this.#verboseOverride = !this.options.quietMode;
}
// Moved before config merges: https://github.com/11ty/eleventy/issues/3316
if (this.#verboseOverride === true || this.#verboseOverride === false) {
this.eleventyConfig.userConfig._setQuietModeOverride(!this.#verboseOverride);
}
this.eleventyConfig.userConfig.directories = this.directories;
/* Programmatic API config */
if (this.options.config && typeof this.options.config === "function") {
debug("Running options.config configuration callback (passed to Eleventy constructor)");
// TODO use return object here?
await this.options.config(this.eleventyConfig.userConfig);
}
/**
* @type {object}
* @description Initialize Eleventy environment variables
* @default null
*/
// this.runMode need to be set before this
this.env = this.getEnvironmentVariableValues();
this.initializeEnvironmentVariables(this.env);
// Async initialization of configuration
await this.eleventyConfig.init(initOverrides);
/**
* @type {object}
* @description Initialize Eleventy’s configuration, including the user config file
*/
this.config = this.eleventyConfig.getConfig();
/**
* @type {object}
* @description Singleton BenchmarkManager instance
*/
this.bench = this.config.benchmarkManager;
if (performance) {
debug("Eleventy warm up time: %o (ms)", performance.now());
}
this.#hasConfigInitialized = true;
// after #hasConfigInitialized above
this.setIsVerbose(this.#preInitVerbose ?? !this.config.quietMode);
}
getNewTimestamp() {
if (performance) {
return performance.now();
}
return new Date().getTime();
}
/** @type {ProjectDirectories} */
get directories() {
if (!this.#directories) {
this.#directories = new ProjectDirectories();
this.#directories.setInput(this.rawInput, this.options.inputDir);
this.#directories.setOutput(this.rawOutput);
if (this.source == "cli" && (this.rawInput !== undefined || this.rawOutput !== undefined)) {
this.#directories.freeze();
}
}
return this.#directories;
}
/** @type {string} */
get input() {
return this.directories.inputFile || this.directories.input || this.config.dir.input;
}
/** @type {string} */
get inputFile() {
return this.directories.inputFile;
}
/** @type {string} */
get inputDir() {
return this.directories.input;
}
// Not used internally, removed in 3.0.
setInputDir() {
throw new Error(
"Eleventy->setInputDir was removed in 3.0. Use the inputDir option to the constructor",
);
}
/** @type {string} */
get outputDir() {
return this.directories.output || this.config.dir.output;
}
/**
* Updates the dry-run mode of Eleventy.
*
* @param {boolean} isDryRun - Shall Eleventy run in dry mode?
*/
setDryRun(isDryRun) {
this.isDryRun = !!isDryRun;
}
/**
* Sets the incremental build mode.
*
* @param {boolean} isIncremental - Shall Eleventy run in incremental build mode and only write the files that trigger watch updates
*/
setIncrementalBuild(isIncremental) {
this.isIncremental = !!isIncremental;
if (this.writer) {
this.writer.setIncrementalBuild(this.isIncremental);
}
}
/**
* Set whether or not to do an initial build
*
* @param {boolean} ignoreInitialBuild - Shall Eleventy ignore the default initial build before watching in watch/serve mode?
* @default true
*/
setIgnoreInitial(ignoreInitialBuild) {
this.isRunInitialBuild = !ignoreInitialBuild;
if (this.writer) {
this.writer.setRunInitialBuild(this.isRunInitialBuild);
}
}
/**
* Updates the path prefix used in the config.
*
* @param {string} pathPrefix - The new path prefix.
*/
setPathPrefix(pathPrefix) {
if (pathPrefix || pathPrefix === "") {
this.eleventyConfig.setPathPrefix(pathPrefix);
// TODO reset config
// this.config = this.eleventyConfig.getConfig();
}
}
/**
* Restarts Eleventy.
*/
async restart() {
debug("Restarting.");
this.start = this.getNewTimestamp();
this.extensionMap.reset();
this.bench.reset();
}
#cache(key, inst) {
if (!("caches" in inst)) {
throw new Error("To use #cache you need a `caches` getter object");
}
// Restore from cache
if (this.#privateCaches.has(key)) {
let c = this.#privateCaches.get(key);
for (let cacheKey in c) {
inst[cacheKey] = c[cacheKey];
}
} else {
// Set cache
let c = {};
for (let cacheKey of inst.caches || []) {
c[cacheKey] = inst[cacheKey];
}
this.#privateCaches.set(key, c);
}
}
/**
* Starts Eleventy.
*/
async init(options = {}) {
let { viaConfigReset } = Object.assign({ viaConfigReset: false }, options);
if (!this.#hasConfigInitialized) {
await this.initializeConfig();
} else {
// Note: Global event bus is different from user config event bus
this.config.events.reset();
}
await this.config.events.emit("eleventy.config", this.eleventyConfig);
if (this.env) {
await this.config.events.emit("eleventy.env", this.env);
}
let formats = this.templateFormats.getTemplateFormats();
let engineManager = new TemplateEngineManager(this.eleventyConfig);
this.extensionMap = new EleventyExtensionMap(this.eleventyConfig);
this.extensionMap.setFormats(formats);
this.extensionMap.engineManager = engineManager;
await this.config.events.emit("eleventy.extensionmap", this.extensionMap);
this.templateData = new TemplateData(this.eleventyConfig);
this.templateData.setProjectUsingEsm(this.isEsm);
this.templateData.extensionMap = this.extensionMap;
if (this.env) {
this.templateData.environmentVariables = this.env;
}
// Note these directories are all project root relative
this.config.events.emit("eleventy.directories", this.directories.getUserspaceInstance());
this.writer = new TemplateWriter(formats, this.templateData, this.eleventyConfig);
if (!viaConfigReset) {
// set or restore cache
this.#cache("TemplateWriter", this.writer);
}
this.writer.logger = this.logger;
this.writer.extensionMap = this.extensionMap;
this.writer.setRunInitialBuild(this.isRunInitialBuild);
this.writer.setIncrementalBuild(this.isIncremental);
let debugStr = `Directories:
Input:
Directory: ${this.directories.input}
File: ${this.directories.inputFile || false}
Glob: ${this.directories.inputGlob || false}
Data: ${this.directories.data}
Includes: ${this.directories.includes}
Layouts: ${this.directories.layouts || false}
Output: ${this.directories.output}
Template Formats: ${formats.join(",")}
Verbose Output: ${this.verboseMode}`;
debug(debugStr);
this.writer.setVerboseOutput(this.verboseMode);
this.writer.setDryRun(this.isDryRun);
this.#needsInit = false;
}
// These are all set as initial global data under eleventy.env.* (see TemplateData->environmentVariables)
getEnvironmentVariableValues() {
let values = {
source: this.source,
runMode: this.runMode,
};
if (this.#activeConfigurationPath) {
values.config = TemplatePath.absolutePath(this.#activeConfigurationPath);
}
// Fixed: instead of configuration directory, explicit root or working directory
values.root = TemplatePath.getWorkingDir();
values.source = this.source;
// Backwards compatibility
Object.defineProperty(values, "isServerless", {
enumerable: false,
value: false,
});
return values;
}
/**
* Set process.ENV variables for use in Eleventy projects
*
* @method
*/
initializeEnvironmentVariables(env) {
// Recognize that global data `eleventy.version` is coerced to remove prerelease tags
// and this is the raw version (3.0.0 versus 3.0.0-alpha.6).
// `eleventy.env.version` does not yet exist (unnecessary)
process.env.ELEVENTY_VERSION = MinimalCore.getVersion();
process.env.ELEVENTY_ROOT = env.root;
debug("Setting process.env.ELEVENTY_ROOT: %o", env.root);
process.env.ELEVENTY_SOURCE = env.source;
process.env.ELEVENTY_RUN_MODE = env.runMode;
}
/** @param {boolean} value */
set verboseMode(value) {
this.setIsVerbose(value);
}
/** @type {boolean} */
get verboseMode() {
return this.#isVerboseMode;
}
/** @type {ConsoleLogger} */
get logger() {
if (!this.#logger) {
this.#logger = new ConsoleLogger();
this.#logger.isVerbose = this.verboseMode;
}
return this.#logger;
}
/** @param {ConsoleLogger} logger */
set logger(logger) {
this.eleventyConfig.setLogger(logger);
this.#logger = logger;
}
disableLogger() {
this.logger.overrideLogger(false);
}
/** @type {EleventyErrorHandler} */
get errorHandler() {
if (!this.#errorHandler) {
this.#errorHandler = new EleventyErrorHandler();
this.#errorHandler.isVerbose = this.verboseMode;
this.#errorHandler.logger = this.logger;
}
return this.#errorHandler;
}
/**
* Updates the verbose mode of Eleventy.
*
* @method
* @param {boolean} isVerbose - Shall Eleventy run in verbose mode?
*/
setIsVerbose(isVerbose) {
if (!this.#hasConfigInitialized) {
this.#preInitVerbose = !!isVerbose;
return;
}
// always defer to --quiet if override happened
isVerbose = this.#verboseOverride ?? !!isVerbose;
this.#isVerboseMode = isVerbose;
if (this.logger) {
this.logger.isVerbose = isVerbose;
}
this.bench.setVerboseOutput(isVerbose);
if (this.writer) {
this.writer.setVerboseOutput(isVerbose);
}
if (this.errorHandler) {
this.errorHandler.isVerbose = isVerbose;
}
// Set verbose mode in config file
this.eleventyConfig.verbose = isVerbose;
}
get templateFormats() {
if (!this.#templateFormats) {
let tf = new ProjectTemplateFormats();
this.#templateFormats = tf;
}
return this.#templateFormats;
}
/**
* Updates the template formats of Eleventy.
*
* @method
* @param {string} formats - The new template formats.
*/
setFormats(formats) {
this.templateFormats.setViaCommandLine(formats);
}
/**
* Updates the run mode of Eleventy.
*
* @method
* @param {string} runMode - One of "build", "watch", or "serve"
*/
setRunMode(runMode) {
this.runMode = runMode;
}
/**
* Set the file that needs to be rendered/compiled/written for an incremental build.
* This method is also wired up to the CLI --incremental=incrementalFile
*
* @method
* @param {string} incrementalFile - File path (added or modified in a project)
*/
setIncrementalFile(incrementalFile) {
if (incrementalFile) {
// This used to also setIgnoreInitial(true) but was changed in 3.0.0-alpha.14
this.setIncrementalBuild(true);
this.programmaticApiIncrementalFile = TemplatePath.addLeadingDotSlash(incrementalFile);
// Used to determind template relevance for compile cache keys
this.eleventyConfig.setPreviousBuildModifiedFile(incrementalFile);
}
}
unsetIncrementalFile() {
// only applies to initial build, no re-runs (--watch/--serve)
if (this.programmaticApiIncrementalFile) {
// this.setIgnoreInitial(false);
this.programmaticApiIncrementalFile = undefined;
}
// reset back to false
this.setIgnoreInitial(false);
}
/**
* Resets the config of Eleventy.
*
* @method
*/
async resetConfig() {
delete this.eleventyConfig;
// ensures `initializeConfig()` will run when `init()` is called next
this.#hasConfigInitialized = false;
}
// fetch from project’s package.json
get projectPackageJsonPath() {
if (this.#projectPackageJsonPath === undefined) {
this.#projectPackageJsonPath = getWorkingProjectPackageJsonPath() || false;
}
return this.#projectPackageJsonPath;
}
get projectPackageJson() {
if (!this.#projectPackageJson) {
let p = this.projectPackageJsonPath;
this.#projectPackageJson = p ? importJsonSync(p) : {};
}
return this.#projectPackageJson;
}
get isEsm() {
if (this.#isEsm !== undefined) {
return this.#isEsm;
}
if (this.loader == "esm") {
this.#isEsm = true;
} else if (this.loader == "cjs") {
this.#isEsm = false;
} else if (this.loader == "auto") {
// Note: Node defaults to CommonJS if missing, Deno defaults to ESM
// https://docs.deno.com/runtime/fundamentals/node/#commonjs-support
if (typeof Deno !== "undefined") {
this.#isEsm = this.projectPackageJson?.type !== "commonjs";
} else {
this.#isEsm = this.projectPackageJson?.type === "module";
}
} else {
throw new Error("The 'loader' option must be one of 'esm', 'cjs', or 'auto'");
}
return this.#isEsm;
}
/**
* Writes templates to the file system.
*
* @async
* @method
* @param {String} subtype - (optional) or "templates" (skips passthrough copy) or "copy" (skips templates)
* @returns {Promise<{Array}>}
*/
async write(subtype) {
if (subtype) {
if (subtype !== "fs" && !subtype?.startsWith("fs:")) {
subtype = `fs:${subtype}`;
}
return this.executeBuild(subtype);
}
return this.executeBuild("fs");
}
/**
* Renders templates to a JSON object.
*
* @async
* @method
* @returns {Promise<{Array}>}
*/
async toJSON() {
return this.executeBuild("json");
}
toNDJSON() {
throw new Error("Feature removed in Eleventy v4: https://github.com/11ty/eleventy/issues/3382");
}
/**
* tbd.
*
* @async
* @method
* @returns {Promise<{Array}>} ret - tbd.
*/
async executeBuild(to = "fs") {
if (this.#needsInit) {
if (!this.#initPromise) {
this.#initPromise = this.init();
}
await this.#initPromise.then(() => {
// #needsInit also set to false at the end of `init()`
this.#needsInit = false;
this.#initPromise = undefined;
});
}
if (!this.writer) {
throw new Error(
"Internal error: Eleventy didn’t run init() properly and wasn’t able to create a TemplateWriter.",
);
}
let incrementalFile =
this.programmaticApiIncrementalFile || this.watchQueue?.getIncrementalFile();
if (incrementalFile) {
this.writer.setIncrementalFile(incrementalFile);
}
let returnObj;
let hasError = false;
let outputMode = String(to);
// normalize fs:templates or fs:copy to `fs`
if (outputMode.includes(":")) {
outputMode = outputMode.split(":").shift();
}
try {
let directories = this.directories.getUserspaceInstance();
let eventsArg = {
directories,
// v3.0.0-alpha.6, changed to use `directories` instead (this was only used by serverless plugin)
inputDir: directories.input,
// Deprecated (not normalized) use `directories` instead.
dir: this.config.dir,
runMode: this.runMode,
outputMode,
incremental: this.isIncremental,
};
await this.config.events.emit("beforeBuild", eventsArg);
await this.config.events.emit("eleventy.before", eventsArg);
let promise;
if (to === "fs") {
promise = this.writer.write();
} else if (to === "fs:templates") {
promise = this.writer.writeTemplates();
} else if (to === "json") {
promise = this.writer.getJSON("json");
} else {
throw new Error(
`Invalid argument for \`Eleventy->executeBuild(${to})\`, expected "json", "fs", or "fs:templates".`,
);
}
let resolved = await promise;
// Passing the processed output to the eleventy.after event (2.0+)
eventsArg.results = resolved.templates;
if (to === "json" || to === "fs:templates") {
// Backwards compat
returnObj = resolved.templates;
} else {
// Backwards compat
returnObj = [resolved.passthroughCopy, resolved.templates];
}
this.unsetIncrementalFile();
this.writer.resetIncrementalFile();
eventsArg.uses = this.eleventyConfig.usesGraph.map;
await this.config.events.emit("afterBuild", eventsArg);
await this.config.events.emit("eleventy.after", eventsArg);
this.buildCount++;
} catch (error) {
hasError = true;
// Issue #2405: Don’t change the exitCode for programmatic scripts
let errorSeverity = this.source === "script" ? "error" : "fatal";
this.errorHandler.once(errorSeverity, error, "Problem writing Eleventy templates");
throw error;
} finally {
this.bench.finish();
if (outputMode === "fs") {
this.logger.logWithOptions({
message: this.logFinished(),
color: hasError ? "red" : "green",
force: true,
});
}
debug("Finished.");
debug(`
Have a suggestion/feature request/feedback? Feeling frustrated? I want to hear it!
Open an issue: https://github.com/11ty/eleventy/issues/new`);
}
return returnObj;
}
/**
* Logs some statistics after a complete run of Eleventy.
*
* @returns {string} ret - The log message.
*/
logFinished() {
if (!this.writer) {
throw new Error(
"Did you call Eleventy.init to create the TemplateWriter instance? Hint: you probably didn’t.",
);
}
let ret = [];
let {
copyCount,
copySize,
skipCount,
writeCount,
// renderCount, // files that render (costly) but may not write to disk
} = this.writer.getMetadata();
let slashRet = [];
if (copyCount) {
debug("Total passthrough copy aggregate size: %o", readableFileSize(copySize));
slashRet.push(`Copied ${chalk.bold(copyCount)}`);
}
slashRet.push(
`Wrote ${chalk.bold(writeCount)} ${simplePlural(writeCount, "file", "files")}${
skipCount ? ` (skipped ${skipCount})` : ""
}`,
);
// slashRet.push(
// `${renderCount} rendered`
// )
if (slashRet.length) {
ret.push(slashRet.join(" "));
}
let time = (this.getNewTimestamp() - this.start) / 1000;
ret.push(
`in ${chalk.bold(time.toFixed(2))} ${simplePlural(time.toFixed(2), "second", "seconds")}`,
);
let cfgStr = this.#activeConfigurationPath
? `, ${TemplatePath.stripLeadingDotSlash(this.#activeConfigurationPath)}`
: " no config file";
// More than 1 second total, show estimate of per-template time
if (time >= 1 && writeCount > 1) {
ret.push(
chalk.gray(`(${((time * 1000) / writeCount).toFixed(1)}ms each, v${pkg.version}${cfgStr})`),
);
} else {
ret.push(chalk.gray(`(v${MinimalCore.getVersion()}${cfgStr})`));
}
return ret.join(" ");
}
}
================================================
FILE: src/Data/ComputedData.js
================================================
import lodash from "@11ty/lodash-custom";
import debugUtil from "debug";
import ComputedDataQueue from "./ComputedDataQueue.js";
import ComputedDataTemplateString from "./ComputedDataTemplateString.js";
import ComputedDataProxy from "./ComputedDataProxy.js";
const { set: lodashSet, get: lodashGet } = lodash;
const debug = debugUtil("Eleventy:ComputedData");
class ComputedData {
constructor(config) {
this.computed = {};
this.symbolParseFunctions = {};
this.templateStringKeyLookup = {};
this.computedKeys = new Set();
this.declaredDependencies = {};
this.queue = new ComputedDataQueue();
this.config = config;
}
add(key, renderFn, declaredDependencies = [], symbolParseFn, templateInstance) {
this.computedKeys.add(key);
this.declaredDependencies[key] = declaredDependencies;
// bind config filters/JS functions
if (typeof renderFn === "function") {
let fns = {};
// TODO bug? no access to non-universal config things?
if (this.config) {
fns = {
...this.config.javascriptFunctions,
};
}
fns.tmpl = templateInstance;
renderFn = renderFn.bind(fns);
}
lodashSet(this.computed, key, renderFn);
if (symbolParseFn) {
lodashSet(this.symbolParseFunctions, key, symbolParseFn);
}
}
addTemplateString(key, renderFn, declaredDependencies = [], symbolParseFn, templateInstance) {
this.add(key, renderFn, declaredDependencies, symbolParseFn, templateInstance);
this.templateStringKeyLookup[key] = true;
}
async resolveVarOrder(data) {
let proxyByTemplateString = new ComputedDataTemplateString(this.computedKeys);
let proxyByProxy = new ComputedDataProxy(this.computedKeys);
for (let key of this.computedKeys) {
let computed = lodashGet(this.computed, key);
if (typeof computed !== "function") {
// add nodes for non functions (primitives like booleans, etc)
// This will not handle template strings, as they are normalized to functions
this.queue.addNode(key);
} else {
this.queue.uses(key, this.declaredDependencies[key]);
let symbolParseFn = lodashGet(this.symbolParseFunctions, key);
let varsUsed = [];
if (symbolParseFn) {
// use the parseForSymbols function in the TemplateEngine
varsUsed = symbolParseFn();
} else if (symbolParseFn !== false) {
// skip resolution is this is false (just use declaredDependencies)
let isTemplateString = !!this.templateStringKeyLookup[key];
let proxy = isTemplateString ? proxyByTemplateString : proxyByProxy;
varsUsed = await proxy.findVarsUsed(computed, data);
}
debug("%o accesses %o variables", key, varsUsed);
let filteredVarsUsed = varsUsed.filter((varUsed) => {
return (
(varUsed !== key && this.computedKeys.has(varUsed)) ||
varUsed.startsWith("collections.")
);
});
this.queue.uses(key, filteredVarsUsed);
}
}
}
async _setupDataEntry(data, order) {
debug("Computed data order of execution: %o", order);
for (let key of order) {
let computed = lodashGet(this.computed, key);
if (typeof computed === "function") {
let ret = await computed(data);
lodashSet(data, key, ret);
} else if (computed !== undefined) {
lodashSet(data, key, computed);
}
}
}
async setupData(data, orderFilter) {
await this.resolveVarOrder(data);
await this.processRemainingData(data, orderFilter);
}
async processRemainingData(data, orderFilter) {
// process all variables
let order = this.queue.getOrder();
if (orderFilter && typeof orderFilter === "function") {
order = order.filter(orderFilter.bind(this.queue));
}
await this._setupDataEntry(data, order);
this.queue.markComputed(order);
}
}
export default ComputedData;
================================================
FILE: src/Data/ComputedDataProxy.js
================================================
import lodash from "@11ty/lodash-custom";
import { isPlainObject } from "@11ty/eleventy-utils";
const { set: lodashSet, get: lodashGet } = lodash;
/* Calculates computed data using Proxies */
class ComputedDataProxy {
constructor(computedKeys) {
if (Array.isArray(computedKeys)) {
this.computedKeys = new Set(computedKeys);
} else {
this.computedKeys = computedKeys;
}
}
isArrayOrPlainObject(data) {
return Array.isArray(data) || isPlainObject(data);
}
getProxyData(data, keyRef) {
// WARNING: SIDE EFFECTS
// Set defaults for keys not already set on parent data
// TODO should make another effort to get rid of this,
// See the ProxyWrap util for more proxy handlers that will likely fix this
let undefinedValue = "__11TY_UNDEFINED__";
if (this.computedKeys) {
for (let key of this.computedKeys) {
if (lodashGet(data, key, undefinedValue) === undefinedValue) {
lodashSet(data, key, "");
}
}
}
let proxyData = this._getProxyData(data, keyRef);
return proxyData;
}
_getProxyForObject(dataObj, keyRef, parentKey = "") {
return new Proxy(
{},
{
get: (obj, key) => {
if (typeof key !== "string") {
return obj[key];
}
let newKey = `${parentKey ? `${parentKey}.` : ""}${key}`;
// Issue #1137
// Special case for Collections, always return an Array for collection keys
// so they it works fine with Array methods like `filter`, `map`, etc
if (newKey === "collections") {
keyRef.add(newKey);
return new Proxy(
{},
{
get: (target, key) => {
if (typeof key === "string") {
keyRef.add(`collections.${key}`);
return [];
}
return target[key];
},
},
);
}
let newData = this._getProxyData(dataObj[key], keyRef, newKey);
if (!this.isArrayOrPlainObject(newData)) {
keyRef.add(newKey);
}
return newData;
},
},
);
}
_getProxyForArray(dataArr, keyRef, parentKey = "") {
return new Proxy(new Array(dataArr.length), {
get: (obj, key) => {
if (Array.prototype.hasOwnProperty(key)) {
// remove `filter`, `constructor`, `map`, etc
keyRef.add(parentKey);
return obj[key];
}
// Hm, this needs to be better
if (key === "then") {
keyRef.add(parentKey);
return;
}
let newKey = `${parentKey}[${key}]`;
let newData = this._getProxyData(dataArr[key], keyRef, newKey);
if (!this.isArrayOrPlainObject(newData)) {
keyRef.add(newKey);
}
return newData;
},
});
}
_getProxyData(data, keyRef, parentKey = "") {
if (isPlainObject(data)) {
return this._getProxyForObject(data, keyRef, parentKey);
} else if (Array.isArray(data)) {
return this._getProxyForArray(data, keyRef, parentKey);
}
// everything else!
return data;
}
async findVarsUsed(fn, data = {}) {
let keyRef = new Set();
// careful, logging proxyData will mess with test results!
let proxyData = this.getProxyData(data, keyRef);
// squelch console logs for this fake proxy data pass 😅
// let savedLog = console.log;
// console.log = () => {};
await fn(proxyData);
// console.log = savedLog;
return Array.from(keyRef);
}
}
export default ComputedDataProxy;
================================================
FILE: src/Data/ComputedDataQueue.js
================================================
import { DepGraph as DependencyGraph } from "dependency-graph";
/* Keeps track of the dependency graph between computed data variables
* Removes keys from the graph when they are computed.
*/
class ComputedDataQueue {
constructor() {
this.graph = new DependencyGraph();
}
getOrder() {
return this.graph.overallOrder();
}
getOrderFor(name) {
return this.graph.dependenciesOf(name);
}
getDependsOn(name) {
return this.graph.dependantsOf(name);
}
isUsesStartsWith(name, prefix) {
if (name.startsWith(prefix)) {
return true;
}
return (
this.graph.dependenciesOf(name).filter((entry) => {
return entry.startsWith(prefix);
}).length > 0
);
}
addNode(name) {
if (!this.graph.hasNode(name)) {
this.graph.addNode(name);
}
}
_uses(graph, name, varsUsed = []) {
if (!graph.hasNode(name)) {
graph.addNode(name);
}
for (let varUsed of varsUsed) {
if (!graph.hasNode(varUsed)) {
graph.addNode(varUsed);
}
graph.addDependency(name, varUsed);
}
}
uses(name, varsUsed = []) {
this._uses(this.graph, name, varsUsed);
}
markComputed(varsComputed = []) {
for (let varComputed of varsComputed) {
this.graph.removeNode(varComputed);
}
}
}
export default ComputedDataQueue;
================================================
FILE: src/Data/ComputedDataTemplateString.js
================================================
import lodash from "@11ty/lodash-custom";
import debugUtil from "debug";
const { set: lodashSet } = lodash;
const debug = debugUtil("Eleventy:ComputedDataTemplateString");
/* Calculates computed data in Template Strings.
* Ideally we would use the Proxy approach but it doesn’t work
* in some template languages that visit all available data even if
* it isn’t used in the template (Nunjucks)
*/
class ComputedDataTemplateString {
constructor(computedKeys) {
if (Array.isArray(computedKeys)) {
this.computedKeys = new Set(computedKeys);
} else {
this.computedKeys = computedKeys;
}
// is this ¯\_(lisp)_/¯
// must be strings that won’t be escaped by template languages
this.prefix = "(((11ty(((";
this.suffix = ")))11ty)))";
}
getProxyData() {
let proxyData = {};
// use these special strings as a workaround to check the rendered output
// can’t use proxies here as some template languages trigger proxy for all
// keys in data
for (let key of this.computedKeys) {
// TODO don’t allow to set eleventyComputed.page? other disallowed computed things?
lodashSet(proxyData, key, this.prefix + key + this.suffix);
}
return proxyData;
}
findVarsInOutput(output = "") {
let vars = new Set();
let splits = output.split(this.prefix);
for (let split of splits) {
let varName = split.slice(0, split.indexOf(this.suffix) < 0 ? 0 : split.indexOf(this.suffix));
if (varName) {
vars.add(varName);
}
}
return Array.from(vars);
}
async findVarsUsed(fn) {
let proxyData = this.getProxyData();
let output;
// Mitigation for #1061, errors with filters in the first pass shouldn’t fail the whole thing.
try {
output = await fn(proxyData);
} catch (e) {
debug("Computed Data first pass data resolution error: %o", e);
}
// page.outputPath on serverless urls returns false.
if (typeof output === "string") {
return this.findVarsInOutput(output);
}
return [];
}
}
export default ComputedDataTemplateString;
================================================
FILE: src/Data/TemplateData.js
================================================
import path from "node:path";
import lodash from "@11ty/lodash-custom";
import { Merge, TemplatePath, isPlainObject } from "@11ty/eleventy-utils";
import debugUtil from "debug";
import { inspect } from "../Adapters/Packages/inspect.js";
import unique from "../Util/Objects/Unique.js";
import TemplateGlob from "../TemplateGlob.js";
import EleventyBaseError from "../Errors/EleventyBaseError.js";
import TemplateDataInitialGlobalData from "./TemplateDataInitialGlobalData.js";
import { getEleventyPackageJson, getWorkingProjectPackageJson } from "../Util/ImportJsonSync.js";
import { EleventyImport, EleventyLoadContent } from "../Util/Require.js";
import { DeepFreeze } from "../Util/Objects/DeepFreeze.js";
import { coerce } from "../Util/SemverCoerce.js";
import ReservedData from "../Util/ReservedData.js";
import { isTypeScriptSupported } from "../Util/FeatureTests.cjs";
const { set: lodashSet, get: lodashGet } = lodash;
const debugWarn = debugUtil("Eleventy:Warnings");
const debug = debugUtil("Eleventy:TemplateData");
const debugDev = debugUtil("Dev:Eleventy:TemplateData");
class TemplateDataParseError extends EleventyBaseError {}
class TemplateData {
constructor(templateConfig) {
if (!templateConfig || templateConfig.constructor.name !== "TemplateConfig") {
throw new Error(
"Internal error: Missing `templateConfig` or was not an instance of `TemplateConfig`.",
);
}
this.templateConfig = templateConfig;
this.config = this.templateConfig.getConfig();
this.benchmarks = {
data: this.config.benchmarkManager.get("Data"),
aggregate: this.config.benchmarkManager.get("Aggregate"),
};
this.rawImports = {};
this.globalData = null;
this.templateDirectoryData = {};
this.isEsm = false;
this.initialGlobalData = new TemplateDataInitialGlobalData(this.templateConfig);
}
get dirs() {
return this.templateConfig.directories;
}
get inputDir() {
return this.dirs.input;
}
// if this was set but `falsy` we would fallback to inputDir
get dataDir() {
return this.dirs.data;
}
get absoluteDataDir() {
return TemplatePath.absolutePath(this.dataDir);
}
// This was async in 2.0 and prior but doesn’t need to be any more.
getInputDir() {
return this.dirs.input;
}
getDataDir() {
return this.dataDir;
}
exists(pathname) {
// It's common for data files not to exist, so we avoid going to the FS to
// re-check if they do via a quick-and-dirty cache.
return this.templateConfig.existsCache.exists(pathname);
}
setFileSystemSearch(fileSystemSearch) {
this.fileSystemSearch = fileSystemSearch;
}
setProjectUsingEsm(isEsmProject) {
this.isEsm = !!isEsmProject;
}
get extensionMap() {
if (!this._extensionMap) {
throw new Error("Internal error: missing `extensionMap` in TemplateData.");
}
return this._extensionMap;
}
set extensionMap(map) {
this._extensionMap = map;
}
get environmentVariables() {
return this._env;
}
set environmentVariables(env) {
this._env = env;
}
/* Used by tests */
_setConfig(config) {
this.config = config;
}
getRawImports() {
if (!this.config.keys.package) {
debug(
"Opted-out of package.json assignment for global data with falsy value for `keys.package` configuration.",
);
return this.rawImports;
} else if (Object.keys(this.rawImports).length > 0) {
return this.rawImports;
}
let pkgJson = getWorkingProjectPackageJson();
this.rawImports[this.config.keys.package] = pkgJson;
if (this.config.freezeReservedData) {
DeepFreeze(this.rawImports);
}
return this.rawImports;
}
clearData() {
this.globalData = null;
this.configApiGlobalData = null;
this.templateDirectoryData = {};
}
_getGlobalDataGlobByExtension(extension) {
return TemplateGlob.normalizePath(this.dataDir, `/**/*.${extension}`);
}
// This is a backwards compatibility helper with the old `jsDataFileSuffix` configuration API
getDataFileSuffixes() {
// New API
if (Array.isArray(this.config.dataFileSuffixes)) {
return this.config.dataFileSuffixes;
}
// Backwards compatibility
if (this.config.jsDataFileSuffix) {
let suffixes = [];
suffixes.push(this.config.jsDataFileSuffix); // e.g. filename.11tydata.json
suffixes.push(""); // suffix-less for free with old API, e.g. filename.json
return suffixes;
}
return []; // if both of these entries are set to false, use no files
}
// This is used exclusively for --watch and --serve chokidar targets
async getTemplateDataFileGlob() {
let suffixes = this.getDataFileSuffixes();
let globSuffixesWithLeadingDot = new Set();
globSuffixesWithLeadingDot.add("json"); // covers .11tydata.json too
let globSuffixesWithoutLeadingDot = new Set();
// Typically using [ '.11tydata', '' ] suffixes to find data files
for (let suffix of suffixes) {
// TODO the `suffix` truthiness check is purely for backwards compat?
if (suffix && typeof suffix === "string") {
if (suffix.startsWith(".")) {
// .suffix.js
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.mjs`);
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.cjs`);
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.js`);
if (isTypeScriptSupported()) {
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.mts`);
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.cts`);
globSuffixesWithLeadingDot.add(`${suffix.slice(1)}.ts`);
}
} else {
// "suffix.js" without leading dot
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.mjs`);
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.cjs`);
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.js`);
if (isTypeScriptSupported()) {
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.mts`);
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.cts`);
globSuffixesWithoutLeadingDot.add(`${suffix || ""}.ts`);
}
}
}
}
// Configuration Data Extensions e.g. yaml
if (this.hasUserDataExtensions()) {
for (let extension of this.getUserDataExtensions()) {
globSuffixesWithLeadingDot.add(extension); // covers .11tydata.{extension} too
}
}
let paths = [];
if (globSuffixesWithLeadingDot.size > 0) {
paths.push(`${this.inputDir}**/*.{${Array.from(globSuffixesWithLeadingDot).join(",")}}`);
}
if (globSuffixesWithoutLeadingDot.size > 0) {
paths.push(`${this.inputDir}**/*{${Array.from(globSuffixesWithoutLeadingDot).join(",")}}`);
}
return TemplatePath.addLeadingDotSlashArray(paths);
}
// For spidering dependencies
// TODO Can we reuse getTemplateDataFileGlob instead? Maybe just filter off the .json files before scanning for dependencies
getTemplateJavaScriptDataFileGlob() {
let paths = [];
let suffixes = this.getDataFileSuffixes();
for (let suffix of suffixes) {
if (suffix) {
// TODO this check is purely for backwards compat and I kinda feel like it shouldn’t be here
// paths.push(`${this.inputDir}/**/*${suffix || ""}.cjs`); // Same as above
paths.push(`${this.inputDir}**/*${suffix || ""}.js`); // TODO typescript?
}
}
return TemplatePath.addLeadingDotSlashArray(paths);
}
getGlobalDataGlob() {
let extGlob = this.getGlobalDataExtensionPriorities().join(",");
return [this._getGlobalDataGlobByExtension("{" + extGlob + "}")];
}
getWatchPathCache() {
return this.pathCache;
}
getGlobalDataExtensionPriorities() {
return this.getUserDataExtensions().concat(["json", "mjs", "cjs", "js"]);
}
static calculateExtensionPriority(path, priorities) {
for (let i = 0; i < priorities.length; i++) {
let ext = priorities[i];
if (path.endsWith(ext)) {
return i;
}
}
return priorities.length;
}
async getGlobalDataFiles() {
let priorities = this.getGlobalDataExtensionPriorities();
let fsBench = this.benchmarks.aggregate.get("Searching the file system (data)");
fsBench.before();
let globs = this.getGlobalDataGlob();
let paths = [];
if (this.fileSystemSearch) {
paths = await this.fileSystemSearch.search("global-data", globs);
}
fsBench.after();
// sort paths according to extension priorities
// here we use reverse ordering, because paths with bigger index in array will override the first ones
// example [path/file.json, path/file.js] here js will override json
paths = paths.sort((first, second) => {
let p1 = TemplateData.calculateExtensionPriority(first, priorities);
let p2 = TemplateData.calculateExtensionPriority(second, priorities);
if (p1 < p2) {
return -1;
}
if (p1 > p2) {
return 1;
}
return 0;
});
this.pathCache = paths;
return paths;
}
getObjectPathForDataFile(dataFilePath) {
let absoluteDataFilePath = TemplatePath.absolutePath(dataFilePath);
let reducedPath = TemplatePath.stripLeadingSubPath(absoluteDataFilePath, this.absoluteDataDir);
let parsed = path.parse(reducedPath);
let folders = parsed.dir ? parsed.dir.split("/") : [];
folders.push(parsed.name);
return folders;
}
async getAllGlobalData() {
let globalData = {};
let files = TemplatePath.addLeadingDotSlashArray(await this.getGlobalDataFiles());
this.config.events.emit("eleventy.globalDataFiles", files);
let dataFileConflicts = {};
for (let j = 0, k = files.length; j < k; j++) {
let data = await this.getDataValue(files[j]);
let objectPathTarget = this.getObjectPathForDataFile(files[j]);
// Since we're joining directory paths and an array is not usable as an objectkey since two identical arrays are not double equal,
// we can just join the array by a forbidden character ("/"" is chosen here, since it works on Linux, Mac and Windows).
// If at some point this isn't enough anymore, it would be possible to just use JSON.stringify(objectPathTarget) since that
// is guaranteed to work but is signifivcantly slower.
let objectPathTargetString = objectPathTarget.join(path.sep);
// if two global files have the same path (but different extensions)
// and conflict, let’s merge them.
if (dataFileConflicts[objectPathTargetString]) {
debugWarn(
`merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[objectPathTargetString]}). Overriding existing keys.`,
);
let oldData = lodashGet(globalData, objectPathTarget);
data = Merge(oldData, data);
}
dataFileConflicts[objectPathTargetString] = files[j];
debug(`Found global data file ${files[j]} and adding as: ${objectPathTarget}`);
lodashSet(globalData, objectPathTarget, data);
if (this.config.freezeReservedData) {
ReservedData.check(globalData, files[j]);
}
}
return globalData;
}
async #getInitialGlobalData() {
let globalData = await this.initialGlobalData.getData();
if (!("eleventy" in globalData)) {
globalData.eleventy = {};
}
// #2293 for meta[name=generator]
const pkg = getEleventyPackageJson();
globalData.eleventy.version = coerce(pkg.version).toString();
globalData.eleventy.generator = `Eleventy v${globalData.eleventy.version}`;
if (this.environmentVariables) {
if (!("env" in globalData.eleventy)) {
globalData.eleventy.env = {};
}
Object.assign(globalData.eleventy.env, this.environmentVariables);
}
if (this.dirs) {
if (!("directories" in globalData.eleventy)) {
globalData.eleventy.directories = {};
}
Object.assign(globalData.eleventy.directories, this.dirs.getUserspaceInstance());
}
// Reserved
if (this.config.freezeReservedData) {
DeepFreeze(globalData.eleventy);
}
return globalData;
}
async getInitialGlobalData() {
if (!this.configApiGlobalData) {
this.configApiGlobalData = this.#getInitialGlobalData();
}
return this.configApiGlobalData;
}
async #getGlobalData() {
let rawImports = this.getRawImports();
let configApiGlobalData = await this.getInitialGlobalData();
let globalJson = await this.getAllGlobalData();
let mergedGlobalData = Merge(globalJson, configApiGlobalData);
// OK: Shallow merge when combining rawImports (pkg) with global data files
return Object.assign({}, mergedGlobalData, rawImports);
}
async getGlobalData() {
if (!this.globalData) {
this.globalData = this.#getGlobalData();
}
return this.globalData;
}
/* Template and Directory data files */
async combineLocalData(localDataPaths) {
let localData = {};
if (!Array.isArray(localDataPaths)) {
localDataPaths = [localDataPaths];
}
// Filter out files we know don't exist to avoid overhead for checking
localDataPaths = localDataPaths.filter((path) => {
return this.exists(path);
});
this.config.events.emit("eleventy.dataFiles", localDataPaths);
if (!localDataPaths.length) {
return localData;
}
let dataSource = {};
for (let path of localDataPaths) {
let dataForPath = await this.getDataValue(path);
if (!isPlainObject(dataForPath)) {
debug(
"Warning: Template and Directory data files expect an object to be returned, instead `%o` returned `%o`",
path,
dataForPath,
);
} else {
// clean up data for template/directory data files only.
let cleanedDataForPath = TemplateData.cleanupData(dataForPath, {
file: path,
});
for (let key in cleanedDataForPath) {
if (Object.prototype.hasOwnProperty.call(dataSource, key)) {
debugWarn(
"Local data files have conflicting data. Overwriting '%s' with data from '%s'. Previous data location was from '%s'",
key,
path,
dataSource[key],
);
}
dataSource[key] = path;
}
Merge(localData, cleanedDataForPath);
}
}
return localData;
}
async getTemplateDirectoryData(templatePath) {
if (!this.templateDirectoryData[templatePath]) {
let localDataPaths = await this.getLocalDataPaths(templatePath);
let importedData = await this.combineLocalData(localDataPaths);
this.templateDirectoryData[templatePath] = importedData;
}
return this.templateDirectoryData[templatePath];
}
getUserDataExtensions() {
if (!this.config.dataExtensions) {
return [];
}
// returning extensions in reverse order to create proper extension order
// later added formats will override first ones
return Array.from(this.config.dataExtensions.keys()).reverse();
}
getUserDataParser(extension) {
return this.config.dataExtensions.get(extension);
}
isUserDataExtension(extension) {
return this.config.dataExtensions && this.config.dataExtensions.has(extension);
}
hasUserDataExtensions() {
return this.config.dataExtensions && this.config.dataExtensions.size > 0;
}
async _parseDataFile(path, parser, options = {}) {
let readFile = !("read" in options) || options.read === true;
let rawInput;
if (readFile) {
rawInput = EleventyLoadContent(path, options);
}
if (readFile && !rawInput) {
return {};
}
try {
if (readFile) {
return parser(rawInput, path);
} else {
// path as a first argument is when `read: false`
// path as a second argument is for consistency with `read: true` API
return parser(path, path);
}
} catch (e) {
throw new TemplateDataParseError(`Having trouble parsing data file ${path}`, e);
}
}
// ignoreProcessing = false for global data files
// ignoreProcessing = true for local data files
async getDataValue(path) {
let extension = TemplatePath.getExtension(path);
if (extension === "js" || extension === "cjs" || extension === "mjs") {
// JS data file or require’d JSON (no preprocessing needed)
if (!this.exists(path)) {
return {};
}
let aggregateDataBench = this.benchmarks.aggregate.get("Data File");
aggregateDataBench.before();
let dataBench = this.benchmarks.data.get(`\`${path}\``);
dataBench.before();
let type = "cjs";
if (extension === "mjs" || (extension === "js" && this.isEsm)) {
type = "esm";
}
// We always need to use `import()`, as `require` isn’t available in ESM.
let returnValue = await EleventyImport(path, type);
// TODO special exception for Global data `permalink.js`
// module.exports = (data) => `${data.page.filePathStem}/`; // Does not work
// module.exports = () => ((data) => `${data.page.filePathStem}/`); // Works
if (typeof returnValue === "function") {
let configApiGlobalData = await this.getInitialGlobalData();
returnValue = await returnValue(configApiGlobalData || {});
}
dataBench.after();
aggregateDataBench.after();
return returnValue;
} else if (this.isUserDataExtension(extension)) {
// Other extensions
let { parser, options } = this.getUserDataParser(extension);
return this._parseDataFile(path, parser, options);
} else if (extension === "json") {
// File to string, parse with JSON (preprocess)
const parser = (content) => JSON.parse(content);
return this._parseDataFile(path, parser);
} else {
throw new TemplateDataParseError(
`Could not find an appropriate data parser for ${path}. Do you need to add a plugin to your config file?`,
);
}
}
_pushExtensionsToPaths(paths, curpath, extensions) {
for (let extension of extensions) {
paths.push(curpath + "." + extension);
}
}
_addBaseToPaths(paths, base, extensions, nonEmptySuffixesOnly = false) {
let suffixes = this.getDataFileSuffixes();
for (let suffix of suffixes) {
suffix = suffix || "";
if (nonEmptySuffixesOnly && suffix === "") {
continue;
}
// data suffix
if (suffix) {
paths.push(base + suffix + ".js");
paths.push(base + suffix + ".cjs");
paths.push(base + suffix + ".mjs");
}
paths.push(base + suffix + ".json"); // default: .11tydata.json
// inject user extensions
this._pushExtensionsToPaths(paths, base + suffix, extensions);
}
}
async getLocalDataPaths(templatePath) {
let paths = [];
let parsed = path.parse(templatePath);
let inputDir = this.inputDir;
debugDev("getLocalDataPaths(%o)", templatePath);
debugDev("parsed.dir: %o", parsed.dir);
let userExtensions = this.getUserDataExtensions();
if (parsed.dir) {
let fileNameNoExt = this.extensionMap.removeTemplateExtension(parsed.base);
// default dataSuffix: .11tydata, is appended in _addBaseToPaths
debug("Using %o suffixes to find data files.", this.getDataFileSuffixes());
// Template data file paths
let filePathNoExt = parsed.dir + "/" + fileNameNoExt;
this._addBaseToPaths(paths, filePathNoExt, userExtensions);
// Directory data file paths
let allDirs = TemplatePath.getAllDirs(parsed.dir);
debugDev("allDirs: %o", allDirs);
for (let dir of allDirs) {
let lastDir = TemplatePath.getLastPathSegment(dir);
let dirPathNoExt = dir + "/" + lastDir;
if (inputDir) {
debugDev("dirStr: %o; inputDir: %o", dir, inputDir);
}
// TODO use DirContains
if (!inputDir || (dir.startsWith(inputDir) && dir !== inputDir)) {
if (this.config.dataFileDirBaseNameOverride) {
let indexDataFile = dir + "/" + this.config.dataFileDirBaseNameOverride;
this._addBaseToPaths(paths, indexDataFile, userExtensions, true);
} else {
this._addBaseToPaths(paths, dirPathNoExt, userExtensions);
}
}
}
// 0.11.0+ include root input dir files
// if using `docs/` as input dir, looks for docs/docs.json et al
if (inputDir) {
let lastInputDir = TemplatePath.addLeadingDotSlash(
TemplatePath.join(inputDir, TemplatePath.getLastPathSegment(inputDir)),
);
// in root input dir, search for index.11tydata.json et al
if (this.config.dataFileDirBaseNameOverride) {
let indexDataFile =
TemplatePath.getDirFromFilePath(lastInputDir) +
"/" +
this.config.dataFileDirBaseNameOverride;
this._addBaseToPaths(paths, indexDataFile, userExtensions, true);
} else if (lastInputDir !== "./") {
this._addBaseToPaths(paths, lastInputDir, userExtensions);
}
}
}
debug("getLocalDataPaths(%o): %o", templatePath, paths);
return unique(paths).reverse();
}
/* Like cleanupData() but does not mutate */
static getCleanedTagsImmutable(data, options = {}) {
let tags = [];
if (isPlainObject(data) && data.tags) {
if (typeof data.tags === "string") {
tags = (data.tags || "").split(",");
} else if (Array.isArray(data.tags)) {
tags = data.tags;
} else if (data.tags) {
throw new Error(
`String or Array expected for \`tags\`${options.file ? ` in ${options.isVirtualTemplate ? "virtual " : ""}template: ${options.file}` : ""}. Received: ${inspect(data.tags)}`,
);
}
// Deduplicate tags
// Coerce to string #3875
return [...new Set(tags)].map((entry) => String(entry));
}
return tags;
}
static cleanupData(data, options = {}) {
if (isPlainObject(data) && "tags" in data) {
data.tags = this.getCleanedTagsImmutable(data, options);
}
return data;
}
static getNormalizedExcludedCollections(data) {
let excludes = [];
let key = "eleventyExcludeFromCollections";
if (data?.[key] !== true) {
if (Array.isArray(data[key])) {
excludes = data[key];
} else if (typeof data[key] === "string") {
excludes = (data[key] || "").split(",");
}
}
return {
excludes,
excludeAll: data?.eleventyExcludeFromCollections === true,
};
}
static getIncludedCollectionNames(data) {
let tags = TemplateData.getCleanedTagsImmutable(data);
let { excludes, excludeAll } = TemplateData.getNormalizedExcludedCollections(data);
if (excludeAll) {
return [];
}
return ["all", ...tags].filter((tag) => !excludes.includes(tag));
}
static getIncludedTagNames(data) {
return this.getIncludedCollectionNames(data).filter((tagName) => tagName !== "all");
}
}
export default TemplateData;
================================================
FILE: src/Data/TemplateDataInitialGlobalData.js
================================================
import lodash from "@11ty/lodash-custom";
import ReservedData from "../Util/ReservedData.js";
import EleventyBaseError from "../Errors/EleventyBaseError.js";
const { set: lodashSet } = lodash;
class TemplateDataConfigError extends EleventyBaseError {}
class TemplateDataInitialGlobalData {
constructor(templateConfig) {
if (!templateConfig || templateConfig.constructor.name !== "TemplateConfig") {
throw new TemplateDataConfigError("Missing or invalid `templateConfig` (via Render plugin).");
}
this.templateConfig = templateConfig;
this.config = this.templateConfig.getConfig();
}
async getData() {
let globalData = {};
// via eleventyConfig.addGlobalData
if (this.config.globalData) {
let keys = Object.keys(this.config.globalData);
for (let key of keys) {
let returnValue = this.config.globalData[key];
// This section is problematic when used with eleventyComputed #3389
if (typeof returnValue === "function") {
returnValue = await returnValue();
}
lodashSet(globalData, key, returnValue);
}
}
if (this.config.freezeReservedData) {
// TODO-ish might come from the `config` callback too
ReservedData.check(globalData, this.templateConfig.getActiveConfigPath());
}
return globalData;
}
}
export default TemplateDataInitialGlobalData;
================================================
FILE: src/Eleventy.js
================================================
import { relative } from "node:path";
import debugUtil from "debug";
import { TemplatePath } from "@11ty/eleventy-utils";
import { Core } from "./Core.js";
import EleventyServe from "./EleventyServe.js";
import { Watch } from "./Watch.js";
import WatchQueue from "./WatchQueue.js";
import WatchTargets from "./WatchTargets.js";
import EleventyBaseError from "./Errors/EleventyBaseError.js";
// Utils
import checkPassthroughCopyBehavior from "./Util/PassthroughCopyBehaviorCheck.js";
import PathPrefixer from "./Util/PathPrefixer.js";
import PathNormalizer from "./Util/PathNormalizer.js";
import { isGlobMatch } from "./Util/GlobMatcher.js";
import eventBus from "./EventBus.js";
import { withResolvers } from "./Util/PromiseUtil.js";
const debug = debugUtil("Eleventy");
export default class Eleventy extends Core {
/** @type {boolean} */
#isStopping = false;
/** @type {WatchQueue} */
#watchQueue;
// constructor(input, output, options = {}, eleventyConfig = null) {
// super(input, output, options, eleventyConfig);
// }
/**
* Sets the incremental build mode.
*
* @param {boolean} isIncremental - Shall Eleventy run in incremental build mode and only write the files that trigger watch updates
*/
setIncrementalBuild(isIncremental) {
super.setIncrementalBuild(isIncremental);
if (this.#watchQueue) {
this.watchQueue.incremental = !!isIncremental;
}
}
get watchQueue() {
if (!this.#watchQueue) {
this.#watchQueue = new WatchQueue();
this.#watchQueue.incremental = this.isIncremental;
}
return this.#watchQueue;
}
async initializeConfig(initOverrides) {
await super.initializeConfig(initOverrides);
// Careful to make sure the previous server closes on SIGINT, issue #3873
if (!this.eleventyServe) {
/** @type {object} */
this.eleventyServe = new EleventyServe();
}
this.eleventyServe.eleventyConfig = this.eleventyConfig;
/** @type {object} */
this.watchTargets = new WatchTargets(this.eleventyConfig);
this.watchTargets.add(this.config.additionalWatchTargets);
}
async resetConfig() {
await super.resetConfig();
// TODO set this.eleventyServe with this.getChokidarConfig()
if (checkPassthroughCopyBehavior(this.config, this.runMode)) {
this.eleventyServe.resetConfig();
}
}
/**
* Starts Eleventy.
*/
async init(options = {}) {
await super.init(options);
// eleventyServe is always available, even when not in --serve mode
// TODO directorynorm
this.eleventyServe.setOutputDir(this.outputDir);
if (checkPassthroughCopyBehavior(this.config, this.runMode)) {
this.eleventyServe.watchPassthroughCopy(
this.eleventyFiles.getGlobWatcherFilesForPassthroughCopy(),
);
}
}
/**
* @param {string} changedFilePath - File that triggered a re-run (added or modified)
* @param {boolean} [isResetConfig] - are we doing a config reset
*/
async #addFileToWatchQueue(changedFilePath, isResetConfig) {
// Currently this is only for 11ty.js deps but should be extended with usesGraph
let usedByDependants = [];
if (this.watchTargets) {
usedByDependants = this.watchTargets.getDependantsOf(
TemplatePath.addLeadingDotSlash(changedFilePath),
);
}
let relevantLayouts = this.eleventyConfig.usesGraph.getLayoutsUsedBy(changedFilePath);
// `eleventy.templateModified` is no longer used internally, remove in a future major version.
eventBus.emit("eleventy.templateModified", changedFilePath, {
usedByDependants,
relevantLayouts,
});
// These listeners are *global*, not cleared even on config reset
eventBus.emit("eleventy.resourceModified", changedFilePath, usedByDependants, {
viaConfigReset: isResetConfig,
relevantLayouts,
});
this.config.events.emit("eleventy#templateModified", changedFilePath);
this.watchQueue.addToPendingQueue(changedFilePath);
}
shouldTriggerConfigReset(changedFiles) {
// looks for all eligible config files (not just the active one, handles config file rename)
let configFilePaths = new Set(this.eleventyConfig.getLocalProjectConfigFiles());
// https://www.11ty.dev/docs/watch-serve/#reset-configuration
let resetConfigGlobs = WatchTargets.normalizeToGlobs(
Array.from(this.eleventyConfig.userConfig.watchTargetsConfigReset),
);
for (let filePath of changedFiles) {
if (configFilePaths.has(filePath)) {
return true;
}
if (isGlobMatch(filePath, resetConfigGlobs)) {
return true;
}
}
for (let configFilePath of configFilePaths) {
// Any dependencies of the config file changed
let configFileDependencies = new Set(this.watchTargets.getDependenciesOf(configFilePath));
for (let filePath of changedFiles) {
if (configFileDependencies.has(filePath)) {
return true;
}
}
}
return false;
}
// Checks the build queue to see if any configuration related files have changed
#shouldResetConfig(activeQueue = []) {
if (!activeQueue.length) {
return false;
}
return this.shouldTriggerConfigReset(
activeQueue.map((path) => {
return PathNormalizer.normalizeSeperator(TemplatePath.addLeadingDotSlash(path));
}),
);
}
async #rewatch(isResetConfig = false) {
if (this.watchQueue.isBuildRunning()) {
return;
}
this.watchQueue.setBuildRunning();
let queue = this.watchQueue.getActiveQueue();
await this.config.events.emit("beforeWatch", queue);
await this.config.events.emit("eleventy.beforeWatch", queue);
// Clear `import` cache for all files that triggered the rebuild (sync event)
this.watchTargets.clearImportCacheFor(queue);
// reset and reload global configuration
if (isResetConfig) {
// important: run this before config resets otherwise the handlers will disappear.
await this.config.events.emit("eleventy.reset");
this.resetConfig();
}
await this.restart();
await this.init({ viaConfigReset: isResetConfig });
try {
let [passthroughCopyResults, templateResults] = await this.write();
if (isResetConfig) {
// make sure this happens after write()
await this.startWatch();
}
this.watchTargets.reset();
await this.#initWatchDependencies();
// Add new deps to chokidar
let newWatchTargets = this.watchTargets.getNewTargetsSinceLastReset();
this.watcher.watchTargets(newWatchTargets);
// Is a CSS input file and is not in the includes folder
// TODO check output path file extension of this template (not input path)
// TODO add additional API for this, maybe a config callback?
let onlyCssChanges = this.watchQueue.hasAllQueueFiles((path) => {
return (
path.endsWith(".css") &&
// TODO how to make this work with relative includes?
!TemplatePath.startsWithSubPath(path, this.eleventyFiles.getIncludesDir())
);
});
let files = this.watchQueue.getActiveQueue();
// Maps passthrough copy files to output URLs for CSS live reload
let stylesheetUrls = new Set();
for (let entry of passthroughCopyResults) {
for (let filepath in entry.map) {
if (
filepath.endsWith(".css") &&
files.includes(TemplatePath.addLeadingDotSlash(filepath))
) {
stylesheetUrls.add(
"/" + TemplatePath.stripLeadingSubPath(entry.map[filepath], this.outputDir),
);
}
}
}
let normalizedPathPrefix = PathPrefixer.normalizePathPrefix(this.config.pathPrefix);
let matchingTemplates = templateResults
.flat()
.filter((entry) => Boolean(entry))
.map((entry) => {
// only `url`, `inputPath`, and `content` are used: https://github.com/11ty/eleventy-dev-server/blob/1c658605f75224fdc76f68aebe7a412eeb4f1bc9/client/reload-client.js#L140
entry.url = PathPrefixer.joinUrlParts(normalizedPathPrefix, entry.url);
delete entry.rawInput; // Issue #3481
return entry;
});
await this.eleventyServe.reload({
files,
subtype: onlyCssChanges ? "css" : undefined,
build: {
stylesheets: Array.from(stylesheetUrls),
templates: matchingTemplates,
},
});
} catch (error) {
this.eleventyServe.sendError({
error,
});
}
this.watchQueue.setBuildFinished();
let queueSize = this.watchQueue.getPendingQueueSize();
if (queueSize > 0) {
this.logger.log(
`You saved while Eleventy was running, let’s run again. (${queueSize} change${
queueSize !== 1 ? "s" : ""
})`,
);
await this.#rewatch();
}
}
/**
* @returns {module:11ty/eleventy/src/Benchmark/BenchmarkGroup~BenchmarkGroup}
*/
get watcherBench() {
return this.bench.get("Watcher");
}
/**
* Set up watchers and benchmarks.
*
* @async
* @method
*/
async startWatch() {
if (this.projectPackageJsonPath) {
this.watchTargets.add([relative(TemplatePath.getWorkingDir(), this.projectPackageJsonPath)]);
}
this.watchTargets.add(this.eleventyFiles.getGlobWatcherFiles());
this.watchTargets.add(this.eleventyFiles.getIgnoreFiles());
// Watch the local project config file
this.watchTargets.add(this.eleventyConfig.getActiveConfigPath());
// Template and Directory Data Files
this.watchTargets.add(await this.eleventyFiles.getGlobWatcherTemplateDataFiles());
let benchmark = this.watcherBench.get(
"Watching JavaScript Dependencies (disable with `eleventyConfig.setWatchJavaScriptDependencies(false)`)",
);
benchmark.before();
await this.#initWatchDependencies();
benchmark.after();
// Close previous watcher
if (this.watcher) {
await this.watcher.close();
}
// TODO improve unwatching if JS dependencies are removed (or files are deleted)
let { targets, ignores } = await this.getWatchedTargets();
debug("Watching for changes to: %o", targets);
this.watcher = new Watch(this.eleventyConfig);
this.watcher.watchTargets(targets);
this.watcher.addIgnores(ignores);
await this.watcher.start();
this.logger.forceLog("Watching…");
let watchDelay;
let watchRun = async (path) => {
path = TemplatePath.normalize(path);
try {
let isResetConfig = this.#shouldResetConfig([path]);
this.#addFileToWatchQueue(path, isResetConfig);
clearTimeout(watchDelay);
let { promise, resolve, reject } = withResolvers();
watchDelay = setTimeout(async () => {
this.#rewatch(isResetConfig).then(resolve, reject);
}, this.config.watchThrottleWaitTime);
await promise;
} catch (e) {
if (e instanceof EleventyBaseError) {
this.errorHandler.error(e, "Eleventy watch error");
this.watchQueue.setBuildFinished();
} else {
this.errorHandler.fatal(e, "Eleventy fatal watch error");
await this.close();
}
}
this.config.events.emit("eleventy.afterwatch");
};
this.watcher.on("change", async (path) => {
// Emulated passthrough copy logs from the server
if (!this.eleventyServe.isEmulatedPassthroughCopyMatch(path)) {
this.logger.forceLog(
`File changed: ${TemplatePath.stripLeadingDotSlash(TemplatePath.standardizeFilePath(path))}`,
);
}
await watchRun(path);
});
this.watcher.on("add", async (path) => {
// Emulated passthrough copy logs from the server
if (!this.eleventyServe.isEmulatedPassthroughCopyMatch(path)) {
this.logger.forceLog(
`File added: ${TemplatePath.stripLeadingDotSlash(TemplatePath.standardizeFilePath(path))}`,
);
}
this.fileSystemSearch.add(path);
await watchRun(path);
});
this.watcher.on("unlink", async (path) => {
// Emulated passthrough copy logs from the server
if (!this.eleventyServe.isEmulatedPassthroughCopyMatch(path)) {
this.logger.forceLog(
`File deleted: ${TemplatePath.stripLeadingDotSlash(TemplatePath.standardizeFilePath(path))}`,
);
}
this.fileSystemSearch.delete(path);
await watchRun(path);
});
// For testability
return watchRun;
}
/**
* Starts watching dependencies.
*/
async #initWatchDependencies() {
if (!this.eleventyConfig.shouldSpiderJavaScriptDependencies()) {
return;
}
// Lazy resolve isEsm only for --watch
this.watchTargets.setProjectUsingEsm(this.isEsm);
// Template files .11ty.js
let templateFiles = await this.eleventyFiles.getWatchPathCache();
await this.watchTargets.addDependencies(templateFiles);
// TODO use DirContains
let dataDir = TemplatePath.stripLeadingDotSlash(this.templateData.getDataDir());
function filterOutGlobalDataFiles(path) {
return !dataDir || !TemplatePath.stripLeadingDotSlash(path).startsWith(dataDir);
}
// Config file dependencies
await this.watchTargets.addDependencies(
this.eleventyConfig.getActiveConfigPath(),
filterOutGlobalDataFiles,
);
// Deps from Global Data (that aren’t in the global data directory, everything is watched there)
let globalDataDeps = this.templateData.getWatchPathCache();
await this.watchTargets.addDependencies(globalDataDeps, filterOutGlobalDataFiles);
await this.watchTargets.addDependencies(
await this.eleventyFiles.getWatcherTemplateJavaScriptDataFiles(),
);
}
/**
* Returns all watched paths
*
* @async
* @method
* @returns {Object} `targets` file paths, and `ignores` globs Array
*/
async getWatchedTargets() {
return {
targets: await this.watchTargets.getTargets(),
ignores: this.eleventyFiles.getGlobWatcherIgnores(),
};
}
/**
* Start watching files
*
* @async
* @method
*/
async watch() {
this.watcherBench.setMinimumThresholdMs(500);
this.watcherBench.reset();
// Note that watching indirectly depends on this for fetching dependencies from JS files
// See: TemplateWriter:pathCache and WatchTargets
await this.write();
let initWatchBench = this.watcherBench.get("Start up --watch");
initWatchBench.before();
let watchRun = await this.startWatch();
initWatchBench.after();
this.watcherBench.finish("Watch");
// Returns for testability
return watchRun;
}
// Renamed to close()
async stopWatch() {
return this.close();
}
async close() {
// Prevent multiple invocations.
if (this.#isStopping) {
return this.#isStopping;
}
debug("Cleaning up chokidar and server instances, if they exist.");
this.#isStopping = Promise.all([this.eleventyServe.close(), this.watcher?.close()]).then(() => {
this.#isStopping = false;
});
return this.#isStopping;
}
/**
* Serve Eleventy on this port.
*
* @param {Number} port - The HTTP port to serve Eleventy from.
*/
async serve(port) {
// Port is optional and in this case likely via --port on the command line
// May defer to configuration API options `port` property
return this.eleventyServe.serve(port);
}
/**
* Shows a help message including usage.
*
* @static
* @returns {string} - The help message.
*/
static getHelp() {
return `Usage: eleventy
eleventy --input=. --output=./_site
eleventy --serve
Arguments:
--version
--input=.
Input template files (default: \`.\`)
--output=_site
Write HTML output to this folder (default: \`_site\`)
--serve
Run web server on --port (default 8080) and watch them too
--port
Run the --serve web server on this port (default 8080)
--watch
Wait for files to change and automatically rewrite (no web server)
--incremental
Only build the files that have changed. Best with watch/serve.
--incremental=filename.md
Does not require watch/serve. Run an incremental build targeting a single file.
--ignore-initial
Start without a build; build when files change. Works best with watch/serve/incremental.
--formats=liquid,md
Allow only certain template types (default: \`*\`)
--quiet
Don’t print all written files (off by default)
--config=filename.js
Override the eleventy config file path (default: \`.eleventy.js\`)
--pathprefix='/'
Change all url template filters to use this subdirectory.
--dryrun
Don’t write any files. Useful in DEBUG mode, for example: \`DEBUG=Eleventy* npx @11ty/eleventy --dryrun\`
--loader
Set to "esm" to force ESM mode, "cjs" to force CommonJS mode, or "auto" (default) to infer it from package.json.
--to=json
Change the output to JSON (default: \`fs\`)
--to=fs:templates
Writes templates, skips passthrough copy
--help`;
}
/**
* @deprecated since 1.0.1, use static Eleventy.getHelp()
*/
getHelp() {
return Eleventy.getHelp();
}
/* Removed methods */
initWatch() {
throw new Error(
"Eleventy#initWatch() was removed in v4. Use Eleventy#startWatch() instead (initializes and starts the watcher)",
);
}
getWatchedFiles() {
throw new Error(
"Eleventy#getWatchedFiles() was removed in Eleventy v4. Use Eleventy#getWatchedTargets().targets instead.",
);
}
}
export { Eleventy };
/* Utils */
export { EleventyImport as ImportFile } from "./Util/Require.js";
// TODO(breaking) remove these and recommend folks use package level exports e.g. "@11ty/eleventy/plugins/i18n"
/* Plugins */
export { default as BundlePlugin } from "@11ty/eleventy-plugin-bundle";
// Eleventy*Plugin names are legacy names
export {
default as RenderPlugin,
default as EleventyRenderPlugin,
} from "./Plugins/RenderPlugin.js";
export { default as I18nPlugin, default as EleventyI18nPlugin } from "./Plugins/I18nPlugin.js";
export {
default as HtmlBasePlugin,
default as EleventyHtmlBasePlugin,
} from "./Plugins/HtmlBasePlugin.js";
export { TransformPlugin as InputPathToUrlTransformPlugin } from "./Plugins/InputPathToUrl.js";
export { IdAttributePlugin } from "./Plugins/IdAttributePlugin.js";
export { PreserveClosingTagsPlugin } from "./Plugins/PreserveClosingTagsPlugin.js";
// Error messages for Removed plugins
export function EleventyServerlessBundlerPlugin() {
throw new Error(
"Following feedback from our Community Survey, low interest in this plugin prompted its removal from Eleventy core in 3.0 as we refocus on static sites. Learn more: https://v3.11ty.dev/docs/plugins/serverless/",
);
}
export { EleventyServerlessBundlerPlugin as EleventyServerless };
export function EleventyEdgePlugin() {
throw new Error(
"Following feedback from our Community Survey, low interest in this plugin prompted its removal from Eleventy core in 3.0 as we refocus on static sites. Learn more: https://v3.11ty.dev/docs/plugins/edge/",
);
}
================================================
FILE: src/EleventyCommonJs.cjs
================================================
function canRequireModules() {
// via --experimental-require-module or newer than Node 22 support when this flag is no longer necessary
try {
require("./Util/Objects/SampleModule.mjs");
return true;
} catch(e) {
if(e.code === "ERR_REQUIRE_ESM") {
return false;
}
// Rethrow if not an ESM require error.
throw e;
}
}
if(!canRequireModules()) {
let error = new Error(`\`require("@11ty/eleventy")\` is incompatible with Eleventy v3 and this version of Node. You have a few options:
1. (Easiest) Change the \`require\` to use a dynamic import inside of an asynchronous CommonJS configuration
callback, for example:
module.exports = async function {
const {RenderPlugin, I18nPlugin, HtmlBasePlugin} = await import("@11ty/eleventy");
}
2. (Easier) Update the JavaScript syntax in your configuration file from CommonJS to ESM (change \`require\`
to use \`import\` and rename the file to have an \`.mjs\` file extension).
3. (More work) Change your project to use ESM-first by adding \`"type": "module"\` to your package.json. Any
\`.js\` will need to be ported to use ESM syntax (or renamed to \`.cjs\`.)
4. Upgrade your Node version (at time of writing, v20.19 or newer) to enable this behavior. If you use a version
of Node older than v20.19, try the --experimental-require-module command line flag in Node. Read more:
https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require`);
error.skipOriginalStack = true;
throw error;
}
// If we made it here require(ESM) works fine (via --experimental-require-module or newer Node.js defaults)
let mod = require("./Eleventy.js");
module.exports = mod;
================================================
FILE: src/EleventyExtensionMap.js
================================================
import { TemplatePath } from "@11ty/eleventy-utils";
import { isTypeScriptSupported } from "./Util/FeatureTests.cjs";
class EleventyExtensionMap {
#engineManager;
constructor(config) {
this.setTemplateConfig(config);
this._spiderJsDepsCache = {};
/** @type {Array} */
this.validTemplateLanguageKeys;
}
setFormats(formatKeys = []) {
// raw
this.formatKeys = formatKeys;
this.unfilteredFormatKeys = formatKeys.map(function (key) {
return key.trim().toLowerCase();
});
this.validTemplateLanguageKeys = this.unfilteredFormatKeys.filter((key) =>
this.hasExtension(key),
);
this.passthroughCopyKeys = this.unfilteredFormatKeys.filter((key) => !this.hasExtension(key));
}
setTemplateConfig(config) {
if (!config || config.constructor.name !== "TemplateConfig") {
throw new Error("Internal error: Missing or invalid `config` argument.");
}
this.templateConfig = config;
}
get config() {
return this.templateConfig.getConfig();
}
get engineManager() {
if (!this.#engineManager) {
throw new Error("Internal error: Missing `#engineManager` in EleventyExtensionMap.");
}
return this.#engineManager;
}
set engineManager(mgr) {
this.#engineManager = mgr;
}
reset() {
this.#engineManager.reset();
}
/* Used for layout path resolution */
getFileList(path, dir) {
if (!path) {
return [];
}
let files = [];
this.validTemplateLanguageKeys.forEach((key) => {
this.getExtensionsFromKey(key).forEach(function (extension) {
files.push((dir ? dir + "/" : "") + path + "." + extension);
});
});
return files;
}
// Warning: this would false positive on an include, but is only used
// on paths found from the file system glob search.
// TODO: Method name might just need to be renamed to something more accurate.
isFullTemplateFilePath(path) {
for (let extension of this.validTemplateLanguageKeys) {
if (path.endsWith(`.${extension}`)) {
return true;
}
}
return false;
}
getCustomExtensionEntry(extension) {
if (!this.config.extensionMap) {
return;
}
for (let entry of this.config.extensionMap) {
if (entry.extension === extension) {
return entry;
}
}
}
getValidExtensionsForPath(path) {
let extensions = new Set();
for (let extension in this.extensionToKeyMap) {
if (path.endsWith(`.${extension}`)) {
extensions.add(extension);
}
}
// if multiple extensions are valid, sort from longest to shortest
// e.g. .11ty.js and .js
let sorted = Array.from(extensions)
.filter((extension) => this.validTemplateLanguageKeys.includes(extension))
.sort((a, b) => b.length - a.length);
return sorted;
}
async shouldSpiderJavaScriptDependencies(path) {
let extensions = this.getValidExtensionsForPath(path);
for (let extension of extensions) {
if (extension in this._spiderJsDepsCache) {
return this._spiderJsDepsCache[extension];
}
let cls = await this.engineManager.getEngineClassByExtension(extension);
if (cls) {
let entry = this.getCustomExtensionEntry(extension);
let shouldSpider = cls.shouldSpiderJavaScriptDependencies(entry);
this._spiderJsDepsCache[extension] = shouldSpider;
return shouldSpider;
}
}
return false;
}
getPassthroughCopyGlobs(inputDir) {
return this._getGlobs(this.passthroughCopyKeys, inputDir);
}
getValidGlobs(inputDir) {
return this._getGlobs(this.validTemplateLanguageKeys, inputDir);
}
getGlobs(inputDir) {
return this._getGlobs(this.unfilteredFormatKeys, inputDir);
}
_getGlobs(formatKeys, inputDir = "") {
let extensions = new Set();
for (let key of formatKeys) {
if (this.hasExtension(key)) {
for (let extension of this.getExtensionsFromKey(key)) {
extensions.add(extension);
}
} else {
extensions.add(key);
}
}
let dir = TemplatePath.convertToRecursiveGlobSync(inputDir);
if (extensions.size === 1) {
return [`${dir}/*.${Array.from(extensions)[0]}`];
} else if (extensions.size > 1) {
return [
// extra curly brackets /*.{cjs,txt}
`${dir}/*.{${Array.from(extensions).join(",")}}`,
];
}
return [];
}
hasExtension(key) {
for (let extension in this.extensionToKeyMap) {
if (
this.extensionToKeyMap[extension].key === key ||
this.extensionToKeyMap[extension].aliasKey === key
) {
return true;
}
}
return false;
}
getExtensionsFromKey(key) {
let extensions = new Set();
for (let extension in this.extensionToKeyMap) {
if (this.extensionToKeyMap[extension].aliasKey) {
// only add aliased extension if explicitly referenced in formats
// overrides will not have an aliasKey (md => md)
if (this.extensionToKeyMap[extension].aliasKey === key) {
extensions.add(extension);
}
} else if (this.extensionToKeyMap[extension].key === key) {
extensions.add(extension);
}
}
return Array.from(extensions);
}
// Only `addExtension` configuration API extensions
getExtensionEntriesFromKey(key) {
let entries = new Set();
if ("extensionMap" in this.config) {
for (let entry of this.config.extensionMap) {
if (entry.key === key) {
entries.add(entry);
}
}
}
return Array.from(entries);
}
// Determines whether a path is a passthrough copy file or a template (via TemplateWriter)
hasEngine(pathOrKey) {
return !!this.getKey(pathOrKey);
}
getKey(pathOrKey) {
pathOrKey = (pathOrKey || "").toLowerCase();
for (let extension in this.extensionToKeyMap) {
if (pathOrKey === extension || pathOrKey.endsWith("." + extension)) {
let key =
this.extensionToKeyMap[extension].aliasKey || this.extensionToKeyMap[extension].key;
// must be a valid format key passed (e.g. via --formats)
if (this.validTemplateLanguageKeys.includes(key)) {
return key;
}
}
}
}
getExtensionEntry(pathOrKey) {
pathOrKey = (pathOrKey || "").toLowerCase();
for (let extension in this.extensionToKeyMap) {
if (pathOrKey === extension || pathOrKey.endsWith("." + extension)) {
return this.extensionToKeyMap[extension];
}
}
}
removeTemplateExtension(path) {
for (let extension in this.extensionToKeyMap) {
if (path === extension || path.endsWith("." + extension)) {
return path.slice(
0,
path.length - 1 - extension.length < 0 ? 0 : path.length - 1 - extension.length,
);
}
}
return path;
}
// keys are file extensions
// values are template language keys
get extensionToKeyMap() {
if (!this._extensionToKeyMap) {
this._extensionToKeyMap = {
md: { key: "md", extension: "md" },
html: { key: "html", extension: "html" },
njk: { key: "njk", extension: "njk" },
liquid: { key: "liquid", extension: "liquid" },
"11ty.js": { key: "11ty.js", extension: "11ty.js" },
"11ty.cjs": { key: "11ty.js", extension: "11ty.cjs" },
"11ty.mjs": { key: "11ty.js", extension: "11ty.mjs" },
};
if (isTypeScriptSupported()) {
this._extensionToKeyMap["11ty.ts"] = { key: "11ty.js", extension: "11ty.ts" };
this._extensionToKeyMap["11ty.cts"] = { key: "11ty.js", extension: "11ty.cts" };
this._extensionToKeyMap["11ty.mts"] = { key: "11ty.js", extension: "11ty.mts" };
}
if ("extensionMap" in this.config) {
for (let entry of this.config.extensionMap) {
// extension and key are only different when aliasing.
this._extensionToKeyMap[entry.extension] = entry;
}
}
}
return this._extensionToKeyMap;
}
getReadableFileExtensions() {
return Object.keys(this.extensionToKeyMap).join(" ");
}
}
export default EleventyExtensionMap;
================================================
FILE: src/EleventyFiles.js
================================================
import { existsSync, statSync, readFileSync } from "node:fs";
import { TemplatePath } from "@11ty/eleventy-utils";
import debugUtil from "debug";
import DirContains from "./Util/DirContains.js";
import TemplateData from "./Data/TemplateData.js";
import TemplateGlob from "./TemplateGlob.js";
import checkPassthroughCopyBehavior from "./Util/PassthroughCopyBehaviorCheck.js";
const debug = debugUtil("Eleventy:EleventyFiles");
class EleventyFiles {
#extensionMap;
#watcherGlobs;
constructor(formats, templateConfig) {
if (!templateConfig) {
throw new Error("Internal error: Missing `templateConfig`` argument.");
}
this.templateConfig = templateConfig;
this.config = templateConfig.getConfig();
this.aggregateBench = this.config.benchmarkManager.get("Aggregate");
this.formats = formats;
this.eleventyIgnoreContent = false;
}
get dirs() {
return this.templateConfig.directories;
}
get inputDir() {
return this.dirs.input;
}
get outputDir() {
return this.dirs.output;
}
get includesDir() {
return this.dirs.includes;
}
get layoutsDir() {
return this.dirs.layouts;
}
get dataDir() {
return this.dirs.data;
}
// Backwards compat
getDataDir() {
return this.dataDir;
}
setFileSystemSearch(fileSystemSearch) {
this.fileSystemSearch = fileSystemSearch;
}
init() {
if (this.dirs.inputFile || this.dirs.inputGlob) {
this.templateGlobs = TemplateGlob.map([this.dirs.inputFile || this.dirs.inputGlob]);
} else {
// Input is a directory
this.templateGlobs = this.extensionMap.getGlobs(this.inputDir);
}
this.setupGlobs();
}
#getWatcherGlobs() {
if (!this.#watcherGlobs) {
let globs;
// Input is a file
if (this.inputFile) {
globs = this.templateGlobs;
} else {
// input is a directory
globs = this.extensionMap.getValidGlobs(this.inputDir);
}
this.#watcherGlobs = globs;
}
return this.#watcherGlobs;
}
get passthroughGlobs() {
let paths = new Set();
// stuff added in addPassthroughCopy()
for (let path of this.passthroughManager.getConfigPathGlobs()) {
paths.add(path);
}
// non-template language extensions
for (let path of this.extensionMap.getPassthroughCopyGlobs(this.inputDir)) {
paths.add(path);
}
return Array.from(paths);
}
restart() {
this.setupGlobs();
this._glob = null;
}
/* For testing */
_setConfig(config) {
if (!config.ignores) {
config.ignores = new Set();
config.ignores.add("**/node_modules/**");
}
this.config = config;
this.init();
}
/* Set command root for local project paths */
// This is only used by tests
_setLocalPathRoot(dir) {
this.localPathRoot = dir;
}
set extensionMap(extensionMap) {
this.#extensionMap = extensionMap;
}
get extensionMap() {
// for tests
if (!this.#extensionMap) {
throw new Error("Internal error: missing `extensionMap` in EleventyFiles.");
}
return this.#extensionMap;
}
setRunMode(runMode) {
this.runMode = runMode;
}
setPassthroughManager(mgr) {
this.passthroughManager = mgr;
}
set templateData(templateData) {
this._templateData = templateData;
}
get templateData() {
return this._templateData;
}
setupGlobs() {
this.fileIgnores = this.getIgnores();
this.extraIgnores = this.getIncludesAndDataDirs();
this.uniqueIgnores = this.getIgnoreGlobs();
// Conditional added for tests that don’t have a config
if (this.config?.events) {
this.config.events.emit("eleventy.ignores", this.uniqueIgnores);
}
this.normalizedTemplateGlobs = this.templateGlobs;
}
normalizeIgnoreEntry(entry) {
if (!entry.startsWith("**/")) {
return TemplateGlob.normalizePath(this.localPathRoot || ".", entry);
}
return entry;
}
getIgnoreGlobs() {
let uniqueIgnores = new Set();
for (let ignore of this.fileIgnores) {
uniqueIgnores.add(ignore);
}
for (let ignore of this.extraIgnores) {
uniqueIgnores.add(ignore);
}
// Placing the config ignores last here is important to the tests
for (let ignore of this.config.ignores) {
uniqueIgnores.add(this.normalizeIgnoreEntry(ignore));
}
return Array.from(uniqueIgnores);
}
static getFileIgnores(ignoreFiles) {
if (!Array.isArray(ignoreFiles)) {
ignoreFiles = [ignoreFiles];
}
let ignores = [];
for (let ignorePath of ignoreFiles) {
ignorePath = TemplatePath.normalize(ignorePath);
let dir = TemplatePath.getDirFromFilePath(ignorePath);
if (existsSync(ignorePath)) {
let ignoreContent = readFileSync(ignorePath, "utf8");
if (ignoreContent) {
ignores = ignores.concat(EleventyFiles.normalizeIgnoreContent(dir, ignoreContent));
}
}
}
ignores.forEach((path) => debug(`${ignoreFiles} ignoring: ${path}`));
return ignores;
}
static normalizeIgnoreContent(dir, ignoreContent) {
let ignores = [];
if (ignoreContent) {
ignores = ignoreContent
.split("\n")
.map((line) => {
return line.trim();
})
.filter((line) => {
if (line.charAt(0) === "!") {
debug(
">>> When processing .gitignore/.eleventyignore, Eleventy does not currently support negative patterns but encountered one:",
);
debug(">>>", line);
debug("Follow along at https://github.com/11ty/eleventy/issues/693 to track support.");
}
// empty lines or comments get filtered out
return line.length > 0 && line.charAt(0) !== "#" && line.charAt(0) !== "!";
})
.map((line) => {
let path = TemplateGlob.normalizePath(dir, "/", line);
path = TemplatePath.addLeadingDotSlash(TemplatePath.relativePath(path));
try {
// Note these folders must exist to get /** suffix
let stat = statSync(path);
if (stat.isDirectory()) {
return path + "/**";
}
return path;
} catch (e) {
return path;
}
});
}
return ignores;
}
/* Tests only */
_setEleventyIgnoreContent(content) {
this.eleventyIgnoreContent = content;
}
getIgnores() {
let files = new Set();
for (let ignore of EleventyFiles.getFileIgnores(this.getIgnoreFiles())) {
files.add(ignore);
}
// testing API
if (this.eleventyIgnoreContent !== false) {
files.add(this.eleventyIgnoreContent);
}
// Make sure output dir isn’t in the input dir (or it will ignore all input!)
// input: . and output: . (skip ignore)
// input: ./content and output . (skip ignore)
// input: . and output: ./_site (add ignore)
let outputContainsInputDir = DirContains(this.outputDir, this.inputDir);
if (!outputContainsInputDir) {
// both are already normalized in 3.0
files.add(TemplateGlob.map(this.outputDir + "/**"));
}
return Array.from(files);
}
getIgnoreFiles() {
let ignoreFiles = new Set();
let rootDirectory = this.localPathRoot || ".";
if (this.config.useGitIgnore) {
ignoreFiles.add(TemplatePath.join(rootDirectory, ".gitignore"));
}
if (this.eleventyIgnoreContent === false) {
let absoluteInputDir = TemplatePath.absolutePath(this.inputDir);
ignoreFiles.add(TemplatePath.join(rootDirectory, ".eleventyignore"));
if (rootDirectory !== absoluteInputDir) {
ignoreFiles.add(TemplatePath.join(this.inputDir, ".eleventyignore"));
}
}
return Array.from(ignoreFiles);
}
/* Backwards compat */
getIncludesDir() {
return this.includesDir;
}
/* Backwards compat */
getLayoutsDir() {
return this.layoutsDir;
}
getFileGlobs() {
return this.normalizedTemplateGlobs;
}
getRawFiles() {
return this.templateGlobs;
}
async getWatchPathCache() {
// Issue #1325: make sure passthrough copy files are not included here
if (!this.pathCache) {
throw new Error("Watching requires `.getFiles()` to be called first in EleventyFiles");
}
let ret = [];
// Filter out the passthrough copy paths.
for (let path of this.pathCache) {
if (
this.extensionMap.isFullTemplateFilePath(path) &&
(await this.extensionMap.shouldSpiderJavaScriptDependencies(path))
) {
ret.push(path);
}
}
return ret;
}
_globSearch() {
let globs = this.getFileGlobs();
// returns a promise
debug("Searching for: %o", globs);
return this.fileSystemSearch.search("templates", globs, {
ignore: this.uniqueIgnores,
});
}
async getFiles() {
let bench = this.aggregateBench.get("Searching the file system (templates)");
bench.before();
let globResults = await this._globSearch();
let paths = TemplatePath.addLeadingDotSlashArray(globResults);
bench.after();
// Note 2.0.0-canary.19 removed a `filter` option for custom template syntax here that was unpublished and unused.
this.pathCache = paths;
return paths;
}
getFileShape(paths, filePath) {
if (!filePath) {
return;
}
if (this.isPassthroughCopyFile(paths, filePath)) {
return "copy";
}
if (this.isFullTemplateFile(paths, filePath)) {
return "template";
}
// include/layout/unknown
}
isPassthroughCopyFile(paths, filePath) {
return this.passthroughManager.isPassthroughCopyFile(paths, filePath);
}
// Assumption here that filePath is not a passthrough copy file
isFullTemplateFile(paths, filePath) {
if (!filePath) {
return false;
}
for (let path of paths) {
if (path === filePath) {
return true;
}
}
return false;
}
/* For `eleventy --watch` */
getGlobWatcherFiles() {
let directoryGlobs = this.getIncludesAndDataDirs();
let globs = this.#getWatcherGlobs();
if (checkPassthroughCopyBehavior(this.config, this.runMode)) {
return globs.concat(directoryGlobs);
}
// Revert to old passthroughcopy copy files behavior
return globs.concat(this.passthroughGlobs).concat(directoryGlobs);
}
/* For `eleventy --watch` */
getGlobWatcherFilesForPassthroughCopy() {
return this.passthroughGlobs;
}
/* For `eleventy --watch` */
async getGlobWatcherTemplateDataFiles() {
let templateData = this.templateData;
return await templateData.getTemplateDataFileGlob();
}
/* For `eleventy --watch` */
// TODO this isn’t great but reduces complexity avoiding using TemplateData:getLocalDataPaths for each template in the cache
async getWatcherTemplateJavaScriptDataFiles() {
let globs = this.templateData.getTemplateJavaScriptDataFileGlob();
let bench = this.aggregateBench.get("Searching the file system (watching)");
bench.before();
let results = TemplatePath.addLeadingDotSlashArray(
await this.fileSystemSearch.search("js-dependencies", globs, {
ignore: [
"**/node_modules/**",
".git/**",
// TODO outputDir
// this.outputDir,
],
}),
);
bench.after();
return results;
}
/* Ignored by `eleventy --watch` */
getGlobWatcherIgnores() {
// convert to format without ! since they are passed in as a separate argument to glob watcher
let entries = new Set(
this.fileIgnores.map((ignore) => TemplatePath.stripLeadingDotSlash(ignore)),
);
for (let ignore of this.config.watchIgnores) {
entries.add(this.normalizeIgnoreEntry(ignore));
}
// de-duplicated
return Array.from(entries);
}
getIncludesAndDataDirs() {
let rawPaths = new Set();
rawPaths.add(this.includesDir);
if (this.layoutsDir) {
rawPaths.add(this.layoutsDir);
}
rawPaths.add(this.dataDir);
return Array.from(rawPaths)
.filter((entry) => {
// never ignore the input directory (even if config file returns "" for these)
return entry && entry !== this.inputDir;
})
.map((entry) => {
return TemplateGlob.map(entry + "**");
});
}
}
export default EleventyFiles;
================================================
FILE: src/EleventyServe.js
================================================
import debugUtil from "debug";
import { Merge, TemplatePath } from "@11ty/eleventy-utils";
import { Watch } from "./Watch.js";
function stringifyOptions(options) {
return JSON.stringify(options, function replacer(key, value) {
if (typeof value === "function") {
return value.toString();
}
return value;
});
}
import EleventyBaseError from "./Errors/EleventyBaseError.js";
import ConsoleLogger from "./Util/ConsoleLogger.js";
import PathPrefixer from "./Util/PathPrefixer.js";
import checkPassthroughCopyBehavior from "./Util/PassthroughCopyBehaviorCheck.js";
import { getModulePackageJson } from "./Util/ImportJsonSync.js";
import { EleventyImport } from "./Util/Require.js";
import { isGlobMatch } from "./Util/GlobMatcher.js";
const debug = debugUtil("Eleventy:EleventyServe");
class EleventyServeConfigError extends EleventyBaseError {}
const DEFAULT_SERVER_OPTIONS = {
module: "@11ty/eleventy-dev-server",
port: 8080,
// pathPrefix: "/",
// setup: function() {},
// ready: function(server) {},
// logger: { info: function() {}, error: function() {} }
};
class EleventyServe {
#eleventyConfig;
#savedConfigOptions;
#aliases;
#initOptionsFetched = false;
#chokidar;
// these are *not* normalized
#watchTargets = new Set();
constructor() {
this.logger = new ConsoleLogger();
}
get config() {
if (!this.eleventyConfig) {
throw new EleventyServeConfigError(
"You need to set the eleventyConfig property on EleventyServe.",
);
}
return this.eleventyConfig.getConfig();
}
set config(config) {
throw new Error("It’s not allowed to set config on EleventyServe. Set eleventyConfig instead.");
}
setAliases(aliases) {
this.#aliases = aliases;
if (this._server && "setAliases" in this._server) {
this._server.setAliases(aliases);
}
}
get eleventyConfig() {
if (!this.#eleventyConfig) {
throw new EleventyServeConfigError(
"You need to set the eleventyConfig property on EleventyServe.",
);
}
return this.#eleventyConfig;
}
set eleventyConfig(config) {
this.#eleventyConfig = config;
if (checkPassthroughCopyBehavior(this.#eleventyConfig.userConfig, "serve")) {
this.#eleventyConfig.userConfig.events.on("eleventy.passthrough", ({ map }) => {
// for-free passthrough copy
this.setAliases(map);
});
}
}
// TODO directorynorm
setOutputDir(outputDir) {
// TODO check if this is different and if so, restart server (if already running)
// This applies if you change the output directory in your config file during watch/serve
this.outputDir = outputDir;
}
static getDevServer() {
// This happens on demand for performance purposes when not used by builds
// https://github.com/11ty/eleventy/pull/3689
return import("@11ty/eleventy-dev-server").then((i) => i.default);
}
async getServerModule(name) {
try {
if (!name || name === DEFAULT_SERVER_OPTIONS.module) {
return EleventyServe.getDevServer();
}
// Look for peer dep in local project
let projectNodeModulesPath = TemplatePath.absolutePath("./node_modules/");
let serverPath = TemplatePath.absolutePath(projectNodeModulesPath, name);
// No references outside of the project node_modules are allowed
if (!serverPath.startsWith(projectNodeModulesPath)) {
throw new Error("Invalid node_modules name for Eleventy server instance, received:" + name);
}
let serverPackageJson = getModulePackageJson(serverPath);
// Normalize with `main` entry from
if (TemplatePath.isDirectorySync(serverPath)) {
if (serverPackageJson.main) {
serverPath = TemplatePath.absolutePath(
projectNodeModulesPath,
name,
serverPackageJson.main,
);
} else {
throw new Error(
`Eleventy server ${name} is missing a \`main\` entry in its package.json file. Traversed up from ${serverPath}.`,
);
}
}
let module = await EleventyImport(serverPath);
if (!("getServer" in module)) {
throw new Error(
`Eleventy server module requires a \`getServer\` static method. Could not find one on module: \`${name}\``,
);
}
if (serverPackageJson["11ty"]?.compatibility) {
try {
this.eleventyConfig.userConfig.versionCheck(serverPackageJson["11ty"].compatibility);
} catch (e) {
this.logger.warn(`Warning: \`${name}\` Plugin Compatibility: ${e.message}`);
}
}
return module;
} catch (e) {
this.logger.error(
"There was an error with your custom Eleventy server. We’re using the default server instead.\n" +
e.message,
);
debug("Eleventy server error %o", e);
return EleventyServe.getDevServer();
}
}
get options() {
if (this._options) {
return this._options;
}
this._options = Object.assign(
{
pathPrefix: PathPrefixer.normalizePathPrefix(this.config.pathPrefix),
logger: this.logger,
},
DEFAULT_SERVER_OPTIONS,
this.config.serverOptions,
);
this.#savedConfigOptions = this.config.serverOptions;
if (!this.#initOptionsFetched && this.getSetupCallback()) {
throw new Error(
"Init options have not yet been fetched in the setup callback. This probably means that `init()` has not yet been called.",
);
}
return this._options;
}
get server() {
if (!this._server) {
throw new Error("Missing server instance. Did you call .initServerInstance?");
}
return this._server;
}
async initServerInstance() {
if (this._server) {
return;
}
let serverModule = await this.getServerModule(this.options.module);
if (this.options.module === DEFAULT_SERVER_OPTIONS.module) {
// Fix for missing globs in Chokidar@4
let copyWatch = new Watch(this.eleventyConfig);
copyWatch.watchTargets(this.#watchTargets);
// Careful with ignores here: https://github.com/11ty/eleventy/issues/1134
// copyWatch.addIgnores();
await copyWatch.start();
this.#chokidar = copyWatch;
this.options.chokidar = copyWatch;
}
// Static method `getServer` was already checked in `getServerModule`
this._server = serverModule.getServer("eleventy-server", this.outputDir, this.options);
this.setAliases(this.#aliases);
}
getSetupCallback() {
let setupCallback = this.config.serverOptions.setup;
if (setupCallback && typeof setupCallback === "function") {
return setupCallback;
}
}
async #init() {
let setupCallback = this.getSetupCallback();
if (setupCallback) {
let opts = await setupCallback();
this.#initOptionsFetched = true;
if (opts) {
Merge(this.options, opts);
}
}
}
async init() {
if (!this._initPromise) {
this._initPromise = this.#init();
}
return this._initPromise;
}
// Port comes in here from --port on the command line
async serve(port) {
this._commandLinePort = port;
await this.init();
await this.initServerInstance();
this.server.serve(port || this.options.port);
if (typeof this.config.serverOptions?.ready === "function") {
if (typeof this.server.ready === "function") {
// Dev Server 2.0.7+
// wait for ready promise to resolve before triggering ready callback
await this.server.ready();
await this.config.serverOptions?.ready(this.server);
} else {
throw new Error(
"The `ready` option in Eleventy’s `setServerOptions` method requires a `ready` function on the Dev Server instance. If you’re using Eleventy Dev Server, you will need Dev Server 2.0.7+ or newer to use this feature.",
);
}
}
}
async close() {
if (this._server) {
await this._server.close();
this._server = undefined;
}
}
async sendError({ error }) {
if (this._server) {
await this.server.sendError({
error,
});
}
}
// when the configuration file changes (but server options *may* not, which would otherwise trigger restart())
resetConfig() {
this.#watchTargets = new Set();
}
// Restart the server entirely
// We don’t want to use a native `restart` method (e.g. restart() in Vite) so that
// we can correctly handle a `module` property change (changing the server type)
async restart() {
// Blow away cached options
delete this._options;
await this.close();
// saved --port in `serve()`
await this.serve(this._commandLinePort);
}
// checkPassthroughCopyBehavior check is called upstream in Eleventy.js
watchPassthroughCopy(globs = []) {
for (let glob of globs) {
this.#watchTargets.add(glob);
}
// if the watcher has already started, add the targets
if (this.#chokidar) {
this.#chokidar.watchTargets(globs);
}
}
isEmulatedPassthroughCopyMatch(filepath) {
return isGlobMatch(filepath, Array.from(this.#watchTargets));
}
hasOptionsChanged() {
return (
stringifyOptions(this.config.serverOptions) !== stringifyOptions(this.#savedConfigOptions)
);
}
// Live reload the server
async reload(reloadEvent = {}) {
if (!this._server) {
return;
}
// Restart the server if the options have changed
if (this.hasOptionsChanged()) {
debug("Server options changed, we’re restarting the server");
await this.restart();
} else {
await this.server.reload(reloadEvent);
}
}
}
export default EleventyServe;
================================================
FILE: src/Engines/Custom.js
================================================
import TemplateEngine from "./TemplateEngine.js";
import getJavaScriptData from "../Util/GetJavaScriptData.js";
export default class CustomEngine extends TemplateEngine {
constructor(name, eleventyConfig) {
super(name, eleventyConfig);
this.entry = this.getExtensionMapEntry();
this.needsInit = "init" in this.entry && typeof this.entry.init === "function";
this.setDefaultEngine(undefined);
}
getExtensionMapEntry() {
if ("extensionMap" in this.config) {
let name = this.name.toLowerCase();
// Iterates over only the user config `addExtension` entries
for (let entry of this.config.extensionMap) {
let entryKey = (entry.aliasKey || entry.key || "").toLowerCase();
if (entryKey === name) {
return entry;
}
}
}
throw Error(
`Could not find a custom extension for ${this.name}. Did you add it to your config file?`,
);
}
setDefaultEngine(defaultEngine) {
this._defaultEngine = defaultEngine;
}
get cacheable() {
// Enable cacheability for this template
if (this.entry?.compileOptions?.cache !== undefined) {
return this.entry.compileOptions.cache;
} else if (this.needsToReadFileContents()) {
return true;
} else if (this._defaultEngine?.cacheable !== undefined) {
return this._defaultEngine.cacheable;
}
return super.cacheable;
}
async getInstanceFromInputPath(inputPath) {
if (
"getInstanceFromInputPath" in this.entry &&
typeof this.entry.getInstanceFromInputPath === "function"
) {
// returns Promise
return this.entry.getInstanceFromInputPath(inputPath);
}
// aliased upstream type
if (
this._defaultEngine &&
"getInstanceFromInputPath" in this._defaultEngine &&
typeof this._defaultEngine.getInstanceFromInputPath === "function"
) {
// returns Promise
return this._defaultEngine.getInstanceFromInputPath(inputPath);
}
return false;
}
/**
* Whether to use the module loader directly
*
* @override
*/
useJavaScriptImport() {
if ("useJavaScriptImport" in this.entry) {
return this.entry.useJavaScriptImport;
}
if (
this._defaultEngine &&
"useJavaScriptImport" in this._defaultEngine &&
typeof this._defaultEngine.useJavaScriptImport === "function"
) {
return this._defaultEngine.useJavaScriptImport();
}
return false;
}
/**
* @override
*/
needsToReadFileContents() {
if ("read" in this.entry) {
return this.entry.read;
}
// Handle aliases to `11ty.js` templates, avoid reading files in the alias, see #2279
// Here, we are short circuiting fallback to defaultRenderer, does not account for compile
// functions that call defaultRenderer explicitly
if (this._defaultEngine && "needsToReadFileContents" in this._defaultEngine) {
return this._defaultEngine.needsToReadFileContents();
}
return true;
}
// If we init from multiple places, wait for the first init to finish before continuing on.
async _runningInit() {
if (this.needsInit) {
if (!this._initing) {
this._initBench = this.benchmarks.aggregate.get(`Engine (${this.name}) Init`);
this._initBench.before();
this._initing = this.entry.init.bind({
config: this.config,
bench: this.benchmarks.aggregate,
})();
}
await this._initing;
this.needsInit = false;
if (this._initBench) {
this._initBench.after();
this._initBench = undefined;
}
}
}
async getExtraDataFromFile(inputPath) {
if (this.entry.getData === false) {
return;
}
if (!("getData" in this.entry)) {
// Handle aliases to `11ty.js` templates, use upstream default engine data fetch, see #2279
if (this._defaultEngine && "getExtraDataFromFile" in this._defaultEngine) {
return this._defaultEngine.getExtraDataFromFile(inputPath);
}
return;
}
await this._runningInit();
if (typeof this.entry.getData === "function") {
let dataBench = this.benchmarks.aggregate.get(
`Engine (${this.name}) Get Data From File (Function)`,
);
dataBench.before();
let data = this.entry.getData(inputPath);
dataBench.after();
return data;
}
let keys = new Set();
if (this.entry.getData === true) {
keys.add("data");
} else if (Array.isArray(this.entry.getData)) {
for (let key of this.entry.getData) {
keys.add(key);
}
}
let dataBench = this.benchmarks.aggregate.get(`Engine (${this.name}) Get Data From File`);
dataBench.before();
let inst = await this.getInstanceFromInputPath(inputPath);
if (inst === false) {
dataBench.after();
return Promise.reject(
new Error(
`\`getInstanceFromInputPath\` callback missing from '${this.name}' template engine plugin. It is required when \`getData\` is in use. You can set \`getData: false\` to opt-out of this.`,
),
);
}
// override keys set at the plugin level in the individual template
if (inst.eleventyDataKey) {
keys = new Set(inst.eleventyDataKey);
}
let mixins;
if (this.config) {
// Object.assign usage: see TemplateRenderCustomTest.js: `JavaScript functions should not be mutable but not *that* mutable`
mixins = Object.assign({}, this.config.javascriptFunctions);
}
let promises = [];
for (let key of keys) {
promises.push(
getJavaScriptData(inst, inputPath, key, {
mixins,
isObjectRequired: key === "data",
}),
);
}
let results = await Promise.all(promises);
let data = {};
for (let result of results) {
Object.assign(data, result);
}
dataBench.after();
return data;
}
async compile(str, inputPath, ...args) {
await this._runningInit();
let defaultCompilationFn;
if (this._defaultEngine) {
defaultCompilationFn = async (data) => {
const renderFn = await this._defaultEngine.compile(str, inputPath, ...args);
return renderFn(data);
};
}
// Fall back to default compiler if the user does not provide their own
if (!this.entry.compile) {
if (defaultCompilationFn) {
return defaultCompilationFn;
} else {
throw new Error(
`Missing \`compile\` property for custom template syntax definition eleventyConfig.addExtension("${this.name}"). This is not necessary when aliasing to an existing template syntax.`,
);
}
}
// TODO generalize this (look at JavaScript.js)
let compiledFn = this.entry.compile.bind({
config: this.config,
addDependencies: (from, toArray = []) => {
this.config.uses.addDependency(from, toArray);
},
defaultRenderer: defaultCompilationFn, // bind defaultRenderer to compile function
})(str, inputPath);
// Support `undefined` to skip compile/render
if (compiledFn) {
// Bind defaultRenderer to render function
if ("then" in compiledFn && typeof compiledFn.then === "function") {
// Promise, wait to bind
return compiledFn.then((fn) => {
if (typeof fn === "function") {
return fn.bind
gitextract__ua1mjth/ ├── .editorconfig ├── .git-blame-ignore-revs ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ └── possible-bug.yml │ ├── dependabot.yml │ ├── opencollective.yml │ └── workflows/ │ ├── ci.yml │ ├── codeql.yml │ ├── release.yml │ └── scorecard.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── cmd.cjs ├── docs/ │ ├── coverage.md │ ├── coverage.njk │ ├── eleventy.coverage.js │ └── release-instructions.md ├── eslint.config.js ├── package.json ├── packages/ │ └── client/ │ ├── README.md │ ├── generate-bundle.js │ ├── package.json │ ├── src/ │ │ ├── BundleCore.js │ │ ├── BundleEleventy.js │ │ ├── BundleI18nPlugin.js │ │ ├── BundleLiquid.js │ │ ├── BundleMarkdown.js │ │ ├── BundleNunjucks.js │ │ └── shims/ │ │ ├── process.cjs │ │ └── shim-core.js │ ├── test/ │ │ ├── client-core.test.js │ │ ├── client-eleventy.test.js │ │ └── shared-tests.js │ ├── update-package-json.js │ └── vitest.config.js ├── scripts/ │ ├── release-dryrun.sh │ └── release.sh ├── src/ │ ├── Adapters/ │ │ ├── Engines/ │ │ │ ├── Liquid.core.js │ │ │ ├── Liquid.js │ │ │ ├── Markdown.core.js │ │ │ ├── Markdown.js │ │ │ ├── Nunjucks.core.js │ │ │ └── Nunjucks.js │ │ ├── Packages/ │ │ │ ├── chalk.client.js │ │ │ ├── chalk.js │ │ │ ├── inspect.core.js │ │ │ ├── inspect.js │ │ │ ├── semver.client.js │ │ │ ├── semver.js │ │ │ ├── url.core.js │ │ │ └── url.js │ │ ├── getDefaultConfig.core.js │ │ └── getDefaultConfig.js │ ├── Benchmark/ │ │ ├── Benchmark.js │ │ ├── BenchmarkGroup.js │ │ └── BenchmarkManager.js │ ├── Core.js │ ├── CoreMinimal.js │ ├── Data/ │ │ ├── ComputedData.js │ │ ├── ComputedDataProxy.js │ │ ├── ComputedDataQueue.js │ │ ├── ComputedDataTemplateString.js │ │ ├── TemplateData.js │ │ └── TemplateDataInitialGlobalData.js │ ├── Eleventy.js │ ├── EleventyCommonJs.cjs │ ├── EleventyExtensionMap.js │ ├── EleventyFiles.js │ ├── EleventyServe.js │ ├── Engines/ │ │ ├── Custom.js │ │ ├── FrontMatter/ │ │ │ └── JavaScript.js │ │ ├── Html.js │ │ ├── JavaScript.js │ │ ├── Liquid.js │ │ ├── Markdown.js │ │ ├── Nunjucks.js │ │ ├── TemplateEngine.js │ │ ├── TemplateEngineManager.js │ │ └── Util/ │ │ └── ContextAugmenter.js │ ├── Errors/ │ │ ├── DuplicatePermalinkOutputError.js │ │ ├── EleventyBaseError.js │ │ ├── EleventyErrorHandler.js │ │ ├── EleventyErrorUtil.js │ │ ├── TemplateContentPrematureUseError.js │ │ ├── TemplateContentUnrenderedTemplateError.js │ │ └── UsingCircularTemplateContentReferenceError.js │ ├── EventBus.js │ ├── FileSystemSearch.js │ ├── Filters/ │ │ ├── GetCollectionItem.js │ │ ├── GetCollectionItemIndex.js │ │ ├── GetLocaleCollectionItem.js │ │ └── Url.js │ ├── GlobalDependencyMap.js │ ├── LayoutCache.js │ ├── Plugins/ │ │ ├── HtmlBasePlugin.js │ │ ├── HtmlRelativeCopyPlugin.js │ │ ├── I18nPlugin.js │ │ ├── IdAttributePlugin.js │ │ ├── InputPathToUrl.js │ │ ├── Pagination.js │ │ ├── PreserveClosingTagsPlugin.js │ │ └── RenderPlugin.js │ ├── Template.js │ ├── TemplateBehavior.js │ ├── TemplateCollection.js │ ├── TemplateConfig.js │ ├── TemplateContent.js │ ├── TemplateFileSlug.js │ ├── TemplateGlob.js │ ├── TemplateLayout.js │ ├── TemplateLayoutPathResolver.js │ ├── TemplateMap.js │ ├── TemplatePassthrough.js │ ├── TemplatePassthroughManager.js │ ├── TemplatePermalink.js │ ├── TemplatePreprocessors.js │ ├── TemplateRender.js │ ├── TemplateWriter.js │ ├── UserConfig.js │ ├── Util/ │ │ ├── ArrayUtil.js │ │ ├── AsyncEventEmitter.js │ │ ├── Compatibility.js │ │ ├── ConsoleLogger.js │ │ ├── DateParse.js │ │ ├── DirContains.js │ │ ├── EsmResolver.js │ │ ├── EsmResolverPortAdapter.core.js │ │ ├── EsmResolverPortAdapter.js │ │ ├── EventBusUtil.js │ │ ├── ExistsCache.js │ │ ├── FeatureTests.cjs │ │ ├── FeatureTests.core.cjs │ │ ├── FilePathUtil.js │ │ ├── FileSize.js │ │ ├── FileSystemManager.js │ │ ├── GetJavaScriptData.js │ │ ├── Git.js │ │ ├── GlobMatcher.client.js │ │ ├── GlobMatcher.js │ │ ├── GlobRemap.js │ │ ├── GlobStripper.js │ │ ├── HtmlRelativeCopy.js │ │ ├── HtmlTransformer.js │ │ ├── ImportJsonSync.js │ │ ├── IsAsyncFunction.js │ │ ├── JavaScriptDependencies.core.js │ │ ├── JavaScriptDependencies.js │ │ ├── MemoizeFunction.js │ │ ├── NewLineAdapter.core.js │ │ ├── NewLineAdapter.js │ │ ├── Objects/ │ │ │ ├── DeepFreeze.js │ │ │ ├── ObjectFilter.js │ │ │ ├── ProxyWrap.js │ │ │ ├── SampleModule.mjs │ │ │ ├── Sortable.js │ │ │ └── Unique.js │ │ ├── PassthroughCopyBehaviorCheck.js │ │ ├── PathNormalizer.js │ │ ├── PathPrefixer.js │ │ ├── Pluralize.js │ │ ├── ProjectDirectories.js │ │ ├── ProjectTemplateFormats.js │ │ ├── PromiseUtil.js │ │ ├── Require.js │ │ ├── RequireUtils.core.js │ │ ├── RequireUtils.js │ │ ├── ReservedData.js │ │ ├── ResolvePlugin.client.js │ │ ├── ResolvePlugin.js │ │ ├── RetrieveGlobals.client.js │ │ ├── RetrieveGlobals.core.js │ │ ├── RetrieveGlobals.js │ │ ├── SemverCoerce.js │ │ ├── SetUtil.js │ │ ├── TemplateDepGraph.js │ │ ├── TransformsUtil.js │ │ ├── TypeScript/ │ │ │ └── TypeScriptSample.cts │ │ ├── UrlUtil.js │ │ ├── importer.client.js │ │ ├── importer.core.js │ │ ├── importer.js │ │ ├── spawn.core.js │ │ └── spawn.js │ ├── Watch.js │ ├── WatchQueue.js │ ├── WatchTargets.js │ ├── defaultConfig.js │ ├── defaultConfigExtended.client.js │ └── defaultConfigExtended.js ├── test/ │ ├── ArrayUtilTest.js │ ├── BenchmarkTest.js │ ├── BundlePluginTest.js │ ├── CompatibilityTest.js │ ├── ComputedDataProxyTest.js │ ├── ComputedDataQueueTest.js │ ├── ComputedDataTemplateStringTest.js │ ├── ComputedDataTest.js │ ├── ConsoleLoggerTest.js │ ├── DependencyGraphTest.js │ ├── DirContainsTest.js │ ├── EleventyAddGlobalDataTest.js │ ├── EleventyErrorHandlerTest.js │ ├── EleventyErrorUtilTest.js │ ├── EleventyExtensionMapTest.js │ ├── EleventyFilesGitIgnoreEleventyIgnoreTest.js │ ├── EleventyFilesTest.js │ ├── EleventyImgTransformTest.js │ ├── EleventyMarkdownTest.js │ ├── EleventyNunjucksTest.js │ ├── EleventyServeTest.js │ ├── EleventyTest-CustomDateParsing.js │ ├── EleventyTest-PageData.js │ ├── EleventyTest-Preprocessors.js │ ├── EleventyTest-Shortcodes.js │ ├── EleventyTest.js │ ├── EleventyVirtualTemplatesTest.js │ ├── ExistsCacheTest.js │ ├── FileSystemSearchTest.js │ ├── GetCollectionItemIndexTest.js │ ├── GetCollectionItemTest.js │ ├── GlobRemapTest.js │ ├── GlobStripperTest.js │ ├── GlobalDependencyMapTest.js │ ├── HtmlBasePluginTest.js │ ├── HtmlRelativeCopyTest.js │ ├── I18nPluginTest.js │ ├── IdAttributePluginTest.js │ ├── ImportJsonSyncTest.js │ ├── InputPathToUrlPluginTest.js │ ├── Issue3467Test.js │ ├── Issue3788Test.js │ ├── Issue3797Test.js │ ├── Issue3808Test.js │ ├── Issue3809Test.js │ ├── Issue3816Test.js │ ├── Issue3818Test.js │ ├── Issue3823Test.js │ ├── Issue3825Test.js │ ├── Issue3831Test.js │ ├── Issue3833Test.js │ ├── Issue3850Test.js │ ├── Issue3853Test.js │ ├── Issue3854Test.js │ ├── Issue3860Test.js │ ├── Issue3870IncrementalTest.js │ ├── Issue3870Test.js │ ├── Issue3875Test.js │ ├── Issue434Test.js │ ├── Issue775Test.js │ ├── JavaScriptDependenciesTest.js │ ├── JavaScriptFrontMatterTest.js │ ├── LayoutCacheTest.js │ ├── LodashTest.js │ ├── PaginationTest.js │ ├── PassthroughCopyBehaviorTest.js │ ├── PathNormalizerTest.js │ ├── PathPrefixer.js │ ├── PluralizeTest.js │ ├── PreserveClosingTagsPluginTest.js │ ├── ProjectDirectoriesTest.js │ ├── ProjectTemplateFormatsTest.js │ ├── ProxyWrapTest.js │ ├── ReservedDataTest.js │ ├── SemverCheckTest.js │ ├── SortableTest.js │ ├── TemplateCollectionTest.js │ ├── TemplateConfigTest.js │ ├── TemplateDataTest.js │ ├── TemplateDepGraphTest.js │ ├── TemplateEngineManagerTest.js │ ├── TemplateEngineTest.js │ ├── TemplateFileSlugTest.js │ ├── TemplateGlobTest.js │ ├── TemplateLayoutPathResolverTest.js │ ├── TemplateLayoutTest.js │ ├── TemplateMapTest-ComputedData.js │ ├── TemplateMapTest.js │ ├── TemplatePassthroughManagerTest.js │ ├── TemplatePassthroughTest.js │ ├── TemplatePermalinkTest.js │ ├── TemplateRenderCustomTest.js │ ├── TemplateRenderHTMLTest.js │ ├── TemplateRenderJavaScriptTest.js │ ├── TemplateRenderLiquidTest.js │ ├── TemplateRenderMarkdownPluginTest.js │ ├── TemplateRenderMarkdownTest.js │ ├── TemplateRenderNunjucksTest.js │ ├── TemplateRenderPluginTest.js │ ├── TemplateRenderTest.js │ ├── TemplateTest-CompileOptions.js │ ├── TemplateTest-ComputedData.js │ ├── TemplateTest-CustomExtensions.js │ ├── TemplateTest-DataCascade.js │ ├── TemplateTest-Dates.js │ ├── TemplateTest-JavaScript.js │ ├── TemplateTest.js │ ├── TemplateTest_Permalink.js │ ├── TemplateWriterTest.js │ ├── TestUtilityTest.js │ ├── TransformsUtilTest.js │ ├── UrlTest.js │ ├── UserConfigTest.js │ ├── UserDataExtensionsTest.js │ ├── Util/ │ │ ├── normalizeNewLines.js │ │ └── normalizeSeparators.js │ ├── UtilSetUnionTest.js │ ├── WatchQueueTest.js │ ├── WatchTargetsTest.js │ ├── _getNewTemplateForTests.js │ ├── _getRenderedTemplates.js │ ├── _issues/ │ │ ├── 0/ │ │ │ ├── content/ │ │ │ │ └── index.html │ │ │ ├── eleventy.config.js │ │ │ └── issue-0-test.js │ │ ├── 2250/ │ │ │ ├── 2250-test.js │ │ │ ├── javascript.11ty.cjs │ │ │ ├── liquid.liquid │ │ │ └── nunjucks.njk │ │ ├── 3697/ │ │ │ ├── 3697-test.js │ │ │ └── _data/ │ │ │ └── folder/ │ │ │ ├── 0.json │ │ │ └── 3.json │ │ ├── 3809/ │ │ │ ├── .app/ │ │ │ │ ├── .eleventy.js │ │ │ │ └── _data/ │ │ │ │ └── app.json │ │ │ └── index.njk │ │ ├── 3853/ │ │ │ └── deeper/ │ │ │ └── index.njk │ │ ├── 3854/ │ │ │ ├── app/ │ │ │ │ ├── .eleventy.js │ │ │ │ └── index.njk │ │ │ └── index.njk │ │ ├── 3896/ │ │ │ ├── eleventy-input-folder/ │ │ │ │ ├── 3896.html │ │ │ │ └── _archive/ │ │ │ │ └── ignored.html │ │ │ └── test-files/ │ │ │ ├── eleventy.config.js │ │ │ └── issue3896-test.js │ │ ├── 3932/ │ │ │ ├── 1/ │ │ │ │ └── 2025.html │ │ │ ├── eleventy.config.js │ │ │ └── issue-3932-test.js │ │ └── 975/ │ │ ├── 975-test.js │ │ ├── another-post.md │ │ ├── index.md │ │ └── post.md │ ├── _testHelpers.js │ ├── cmdTest.js │ ├── file-system-search/ │ │ └── file.txt │ ├── noop/ │ │ └── .gitkeep │ ├── noop2/ │ │ └── .gitkeep │ ├── proxy-pagination-globaldata/ │ │ ├── _data/ │ │ │ └── banner.js │ │ ├── tmpl.liquid │ │ ├── tmpl2.njk │ │ └── tmpl4.11ty.js │ ├── semverCoerceTest.js │ ├── slugify-filter/ │ │ ├── comma.njk │ │ ├── multibyte.njk │ │ ├── slug-number.njk │ │ ├── slug-options.njk │ │ ├── slugify-number.njk │ │ ├── slugify-options.njk │ │ └── test.njk │ ├── stubs/ │ │ ├── .eleventyignore │ │ ├── 2016-02-01-permalinkdate.liquid │ │ ├── _data/ │ │ │ ├── globalData.json │ │ │ ├── globalData2.cjs │ │ │ ├── globalDataFn.js │ │ │ ├── globalDataFnCJS.cjs │ │ │ ├── subdir/ │ │ │ │ └── testDataSubdir.json │ │ │ ├── testData.json │ │ │ └── testDataLiquid.json │ │ ├── _includes/ │ │ │ ├── base.njk │ │ │ ├── custom-filter.liquid │ │ │ ├── default.liquid │ │ │ ├── defaultLayout.liquid │ │ │ ├── defaultLayoutLayoutContent.liquid │ │ │ ├── imports.njk │ │ │ ├── included-data.html │ │ │ ├── included-relative.njk │ │ │ ├── included.html │ │ │ ├── included.liquid │ │ │ ├── included.njk │ │ │ ├── included.nunj │ │ │ ├── layout-a.liquid │ │ │ ├── layout-b.liquid │ │ │ ├── layoutLiquid.liquid │ │ │ ├── layouts/ │ │ │ │ ├── div-wrapper-layout.njk │ │ │ │ ├── engineOverrides.njk │ │ │ │ ├── engineOverridesMd.njk │ │ │ │ ├── inasubdir.njk │ │ │ │ ├── issue-115.liquid │ │ │ │ ├── layout-contentdump.njk │ │ │ │ ├── layout-inherit-a.njk │ │ │ │ ├── layout-inherit-b.njk │ │ │ │ ├── layout-inherit-c.njk │ │ │ │ ├── post.liquid │ │ │ │ └── templateMapCollection.njk │ │ │ ├── multiple.liquid │ │ │ ├── multiple.md │ │ │ ├── mylocallayout.njk │ │ │ ├── permalink-data-layout.njk │ │ │ ├── permalink-in-layout/ │ │ │ │ ├── layout-fileslug.liquid │ │ │ │ └── layout.liquid │ │ │ ├── scopeleak.liquid │ │ │ ├── subfolder/ │ │ │ │ ├── included.html │ │ │ │ ├── included.liquid │ │ │ │ └── included.nunj │ │ │ └── test.js │ │ ├── _layouts/ │ │ │ └── layoutsdefault.liquid │ │ ├── add-extension/ │ │ │ ├── test.njk │ │ │ └── test.txt │ │ ├── broken-config.cjs │ │ ├── buffer.11ty.cjs │ │ ├── cfg-directories-export/ │ │ │ ├── eleventy.config.js │ │ │ └── src/ │ │ │ └── .gitkeep │ │ ├── cfg-directories-export-cjs/ │ │ │ ├── eleventy.config.cjs │ │ │ └── src/ │ │ │ └── .gitkeep │ │ ├── class-async-data-fn.11ty.cjs │ │ ├── class-async-filter.11ty.cjs │ │ ├── class-async.11ty.cjs │ │ ├── class-buffer.11ty.cjs │ │ ├── class-data-filter.11ty.cjs │ │ ├── class-data-fn-filter.11ty.cjs │ │ ├── class-data-fn-shorthand.11ty.cjs │ │ ├── class-data-fn.11ty.cjs │ │ ├── class-data-permalink-async-fn.11ty.cjs │ │ ├── class-data-permalink-buffer.11ty.cjs │ │ ├── class-data-permalink-fn-buffer.11ty.cjs │ │ ├── class-data-permalink-fn-filter.11ty.cjs │ │ ├── class-data-permalink-fn.11ty.cjs │ │ ├── class-data-permalink.11ty.cjs │ │ ├── class-data.11ty.cjs │ │ ├── class-filter.11ty.cjs │ │ ├── class-fns-has-page.11ty.cjs │ │ ├── class-fns.11ty.cjs │ │ ├── class-norender.11ty.cjs │ │ ├── class-with-dep-upstream.js │ │ ├── class-with-dep.11ty.cjs │ │ ├── class.11ty.cjs │ │ ├── classfields-data.11ty.cjs │ │ ├── cmd-help-processing/ │ │ │ └── _data/ │ │ │ └── test.js │ │ ├── collection/ │ │ │ ├── test1.md │ │ │ ├── test10.md │ │ │ ├── test2.md │ │ │ ├── test3.md │ │ │ ├── test4.md │ │ │ ├── test5.md │ │ │ ├── test6.html │ │ │ ├── test7.njk │ │ │ ├── test8.md │ │ │ └── test9.md │ │ ├── collection-layout/ │ │ │ ├── _includes/ │ │ │ │ └── layout.liquid │ │ │ ├── dog1.liquid │ │ │ └── template.liquid │ │ ├── collection-layout-wrap.njk │ │ ├── collection-slug/ │ │ │ ├── dog1.njk │ │ │ └── template.njk │ │ ├── collection-template/ │ │ │ ├── _includes/ │ │ │ │ └── layout.liquid │ │ │ ├── dog1.liquid │ │ │ └── template.liquid │ │ ├── collection2/ │ │ │ ├── test1.md │ │ │ └── test2.md │ │ ├── component/ │ │ │ ├── component.11tydata.cjs │ │ │ ├── component.11tydata.js │ │ │ ├── component.11tydata.json │ │ │ ├── component.json │ │ │ └── component.njk │ │ ├── component-async/ │ │ │ ├── component.11tydata.cjs │ │ │ ├── component.11tydata.js │ │ │ └── component.njk │ │ ├── config-deps-upstream.cjs │ │ ├── config-deps.cjs │ │ ├── config-empty-pathprefix.cjs │ │ ├── config-promise.js │ │ ├── config.cjs │ │ ├── custom-extension-no-permalink.txt │ │ ├── custom-extension.txt │ │ ├── custom-frontmatter/ │ │ │ ├── template-excerpt-comment.njk │ │ │ ├── template-newline1.njk │ │ │ ├── template-newline2.njk │ │ │ ├── template-newline3.njk │ │ │ ├── template-nonewline.njk │ │ │ ├── template-toml.njk │ │ │ └── template.njk │ │ ├── data-cascade/ │ │ │ ├── template.11tydata.cjs │ │ │ └── template.njk │ │ ├── datafiledoesnotexist/ │ │ │ └── template.njk │ │ ├── dates/ │ │ │ ├── 2018-01-01-file5.md │ │ │ ├── 2019-01-01-folder/ │ │ │ │ └── 2020-01-01-file.md │ │ │ ├── file1.md │ │ │ ├── file2.md │ │ │ ├── file2b.md │ │ │ ├── file3.md │ │ │ └── file4.md │ │ ├── default-class-export-and-others.11ty.js │ │ ├── default-export-and-others.11ty.js │ │ ├── default-frontmatter.txt │ │ ├── default-function-export-and-named-data.11ty.cjs │ │ ├── default-function-export-and-named-data.11ty.js │ │ ├── default-no-liquid.md │ │ ├── default.liquid │ │ ├── default.md │ │ ├── dependencies/ │ │ │ ├── dep1.cjs │ │ │ ├── dep2.cjs │ │ │ └── two-deps.11ty.cjs │ │ ├── deps/ │ │ │ ├── dep1.cjs │ │ │ └── dep2.cjs │ │ ├── dynamic-permalink/ │ │ │ └── test.njk │ │ ├── eleventyComputed/ │ │ │ ├── first.njk │ │ │ ├── override-reuse.njk │ │ │ ├── override.njk │ │ │ ├── permalink-simple.njk │ │ │ ├── permalink-slug.njk │ │ │ ├── permalink.njk │ │ │ ├── second.njk │ │ │ ├── third.njk │ │ │ ├── true.njk │ │ │ └── use-global-data.njk │ │ ├── eleventyExcludeFromCollections.njk │ │ ├── eleventyExcludeFromCollectionsPermalinkFalse.njk │ │ ├── engine-singletons/ │ │ │ ├── first.njk │ │ │ └── second.njk │ │ ├── exitCode/ │ │ │ └── failure.njk │ │ ├── exitCode_globalData/ │ │ │ ├── _data/ │ │ │ │ └── test.js │ │ │ └── test.liquid │ │ ├── exitCode_success/ │ │ │ └── success.njk │ │ ├── exports-flatdata.11ty.cjs │ │ ├── fileslug.11ty.cjs │ │ ├── firstdir/ │ │ │ └── seconddir/ │ │ │ └── component.njk │ │ ├── formatTest.liquid │ │ ├── frontmatter-date/ │ │ │ ├── test.liquid │ │ │ └── test.njk │ │ ├── function-arrow.11ty.cjs │ │ ├── function-async-filter.11ty.cjs │ │ ├── function-async.11ty.cjs │ │ ├── function-buffer.11ty.cjs │ │ ├── function-filter.11ty.cjs │ │ ├── function-fns.11ty.cjs │ │ ├── function-markdown.11ty.cjs │ │ ├── function-prototype.11ty.cjs │ │ ├── function-throws-async.11ty.cjs │ │ ├── function-throws.11ty.cjs │ │ ├── function.11ty.cjs │ │ ├── glob-pages/ │ │ │ ├── about.md │ │ │ ├── contact.md │ │ │ └── home.md │ │ ├── global-dash-variable.liquid │ │ ├── globby/ │ │ │ ├── _includes/ │ │ │ │ └── include.html │ │ │ └── test.html │ │ ├── ignore-dedupe/ │ │ │ └── .gitignore │ │ ├── ignore1/ │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignore2/ │ │ │ ├── .gitignore │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignore3/ │ │ │ ├── .eleventyignore │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignore4/ │ │ │ ├── .eleventyignore │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignore5/ │ │ │ ├── .gitignore │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignore6/ │ │ │ ├── .eleventyignore │ │ │ ├── .gitignore │ │ │ └── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignoredFolder/ │ │ │ └── ignored.md │ │ ├── ignorelocalroot/ │ │ │ └── .eleventyignore │ │ ├── ignorelocalrootgitignore/ │ │ │ ├── .eleventyignore │ │ │ └── .gitignore │ │ ├── img/ │ │ │ └── stub.md │ │ ├── included.liquid │ │ ├── includer.liquid │ │ ├── includesemptystring.liquid │ │ ├── index.html │ │ ├── index.liquid │ │ ├── issue-115/ │ │ │ ├── index-with-layout.liquid │ │ │ ├── index.liquid │ │ │ ├── template-bars.liquid │ │ │ └── template-foos.liquid │ │ ├── issue-135/ │ │ │ ├── template.json │ │ │ └── template.njk │ │ ├── issue-522/ │ │ │ ├── excluded.md │ │ │ └── template.md │ │ ├── issue-95/ │ │ │ ├── cat.md │ │ │ └── notacat.md │ │ ├── layout-permalink-difflang/ │ │ │ ├── _includes/ │ │ │ │ └── test.njk │ │ │ └── test.md │ │ ├── layoutsemptystring.liquid │ │ ├── local-data-tags/ │ │ │ ├── component.11tydata.cjs │ │ │ └── component.njk │ │ ├── multiple-ignores/ │ │ │ ├── .eleventyignore │ │ │ ├── ignoredFolder/ │ │ │ │ └── ignored.md │ │ │ └── subfolder/ │ │ │ ├── .eleventyignore │ │ │ └── ignoredFolder2/ │ │ │ └── ignored2.md │ │ ├── multipleexports-promises.11ty.cjs │ │ ├── multipleexports.11ty.cjs │ │ ├── njk-relative/ │ │ │ └── dir/ │ │ │ ├── base.njk │ │ │ ├── imports.njk │ │ │ ├── included.njk │ │ │ └── unique-include-123.njk │ │ ├── object-norender.11ty.cjs │ │ ├── object.11ty.cjs │ │ ├── oneinstance.11ty.cjs │ │ ├── overrides/ │ │ │ ├── layout.njk │ │ │ ├── layoutfalse.njk │ │ │ ├── page-templatesyntax.md │ │ │ ├── test-bypass.md │ │ │ ├── test-empty.html │ │ │ ├── test-empty.md │ │ │ ├── test-error.njk │ │ │ ├── test-md.liquid │ │ │ ├── test-multiple.md │ │ │ ├── test-multiple2.njk │ │ │ ├── test-njk.liquid │ │ │ ├── test.html │ │ │ ├── test.liquid │ │ │ └── test.md │ │ ├── page-target-collections/ │ │ │ ├── paginateall.njk │ │ │ ├── tagpages.njk │ │ │ └── tagpagesall.njk │ │ ├── paged/ │ │ │ ├── cfg-collection-tag-cfg-collection/ │ │ │ │ ├── consumer.njk │ │ │ │ ├── paged-downstream.njk │ │ │ │ ├── paged-main.njk │ │ │ │ ├── test1.njk │ │ │ │ ├── test2.njk │ │ │ │ └── test3.njk │ │ │ ├── collection/ │ │ │ │ ├── consumer.njk │ │ │ │ ├── main.njk │ │ │ │ ├── test1.njk │ │ │ │ ├── test2.njk │ │ │ │ └── test3.njk │ │ │ ├── collection-apply-to-all/ │ │ │ │ ├── consumer.njk │ │ │ │ ├── main.njk │ │ │ │ ├── test1.njk │ │ │ │ ├── test2.njk │ │ │ │ └── test3.njk │ │ │ ├── notpaged.njk │ │ │ ├── paged-before-and-reverse.njk │ │ │ ├── paged-before-filter.njk │ │ │ ├── paged-before-metadata.njk │ │ │ ├── paged-before.njk │ │ │ ├── paged-empty-pageonemptydata.njk │ │ │ ├── paged-empty.njk │ │ │ ├── paged.json │ │ │ ├── paged.njk │ │ │ ├── pagedalias.njk │ │ │ ├── pagedaliassize2.njk │ │ │ ├── pagedinlinedata-reverse.njk │ │ │ ├── pagedinlinedata.njk │ │ │ ├── pagedobject.njk │ │ │ ├── pagedobjectfilterarray.njk │ │ │ ├── pagedobjectfilterstring.njk │ │ │ ├── pagedobjectvalues.njk │ │ │ ├── pagedpermalink.njk │ │ │ ├── pagedpermalinkif.liquid │ │ │ ├── pagedpermalinkif.njk │ │ │ ├── pagedpermalinknumeric.njk │ │ │ ├── pagedpermalinknumericoneindexed.njk │ │ │ └── pagedresolve.njk │ │ ├── paged-global-data-mutable/ │ │ │ ├── _data/ │ │ │ │ └── testdata.cjs │ │ │ └── paged-differing-data-set.njk │ │ ├── pagedate.liquid │ │ ├── pagedate.njk │ │ ├── pagedateutc.njk │ │ ├── pagination-eleventycomputed-permalink.liquid │ │ ├── pagination-eleventycomputed-title.liquid │ │ ├── pagination-templatecontent/ │ │ │ ├── index.njk │ │ │ ├── post-1.md │ │ │ └── post-2.md │ │ ├── permalink-build/ │ │ │ └── permalink-build.md │ │ ├── permalink-conflicts/ │ │ │ ├── test1.md │ │ │ ├── test2.md │ │ │ └── test3.md │ │ ├── permalink-conflicts-false/ │ │ │ ├── test1.md │ │ │ └── test2.md │ │ ├── permalink-data-layout/ │ │ │ ├── test.json │ │ │ └── test.njk │ │ ├── permalink-empty-object/ │ │ │ └── empty-object.md │ │ ├── permalink-false/ │ │ │ └── test.md │ │ ├── permalink-false-computed/ │ │ │ └── test.md │ │ ├── permalink-in-layout-fileslug.liquid │ │ ├── permalink-in-layout.liquid │ │ ├── permalink-markdown-override.md │ │ ├── permalink-markdown-var.md │ │ ├── permalink-markdown.md │ │ ├── permalink-nobuild/ │ │ │ └── permalink-nobuild.md │ │ ├── permalink-true/ │ │ │ └── permalink-true.md │ │ ├── permalinkdata-jsfn.njk │ │ ├── permalinkdata-jspermalinkfn.njk │ │ ├── permalinkdata.njk │ │ ├── permalinkdate.liquid │ │ ├── permalinked.liquid │ │ ├── posts/ │ │ │ ├── post1.njk │ │ │ ├── posts.json │ │ │ └── posts.njk │ │ ├── prematureTemplateContent/ │ │ │ ├── test.11ty.cjs │ │ │ ├── test.liquid │ │ │ ├── test.md │ │ │ └── test.njk │ │ ├── promise.11ty.cjs │ │ ├── public/ │ │ │ └── test.css │ │ ├── relative-liquid/ │ │ │ └── dir/ │ │ │ └── included.liquid │ │ ├── reuse-permalink/ │ │ │ ├── reuse-permalink.json │ │ │ └── test1.liquid │ │ ├── script-frontmatter/ │ │ │ ├── test-default.njk │ │ │ ├── test-js.njk │ │ │ └── test.njk │ │ ├── string.11ty.cjs │ │ ├── string.11ty.custom │ │ ├── string.11ty.possum │ │ ├── stubs-1541/ │ │ │ └── _includes/ │ │ │ └── render-source.liquid │ │ ├── stubs-computed-permalink/ │ │ │ ├── eleventycomputed-nested-object.11ty.cjs │ │ │ ├── eleventycomputed-object-replace.11ty.cjs │ │ │ └── eleventycomputed-object.11ty.cjs │ │ ├── stubs-virtual-conflict/ │ │ │ └── virtual.md │ │ ├── subdir/ │ │ │ ├── img/ │ │ │ │ └── .gitkeep │ │ │ └── index.html │ │ ├── subfolder/ │ │ │ ├── index.html │ │ │ ├── subfolder/ │ │ │ │ └── subfolder.liquid │ │ │ └── subfolder.liquid │ │ ├── tagged-pagination-multiples/ │ │ │ └── test.njk │ │ ├── tagged-pagination-multiples-layout/ │ │ │ └── test.njk │ │ ├── template-passthrough/ │ │ │ ├── .htaccess │ │ │ └── static/ │ │ │ ├── nested/ │ │ │ │ └── test-nested.css │ │ │ ├── test.css │ │ │ └── test.js │ │ ├── template-passthrough2/ │ │ │ ├── .htaccess │ │ │ └── static/ │ │ │ ├── nested/ │ │ │ │ └── test-nested.css │ │ │ ├── test.css │ │ │ └── test.js │ │ ├── template.liquid │ │ ├── templateFrontMatter.liquid │ │ ├── templateFrontMatterJs.njk │ │ ├── templateFrontMatterJson.liquid │ │ ├── templateLayoutCacheDuplicates/ │ │ │ └── _includes/ │ │ │ └── layout.njk │ │ ├── templateLayoutCacheDuplicates-b/ │ │ │ └── _includes/ │ │ │ └── layout.njk │ │ ├── templateMapCollection/ │ │ │ ├── paged-cfg-permalink.md │ │ │ ├── paged-cfg-tagged-apply-to-all.md │ │ │ ├── paged-cfg-tagged-permalink-apply-to-all.md │ │ │ ├── paged-cfg-tagged-permalink.md │ │ │ ├── paged-cfg-tagged.md │ │ │ ├── paged-cfg.md │ │ │ ├── paged-tag-dogs-templateContent-alias.md │ │ │ ├── paged-tag-dogs-templateContent.md │ │ │ ├── paged-tag.md │ │ │ ├── templateContent.md │ │ │ ├── test1.md │ │ │ ├── test2.md │ │ │ ├── test3.md │ │ │ ├── test4.md │ │ │ ├── test5.md │ │ │ └── testWithLayout.md │ │ ├── templateTwoLayouts.liquid │ │ ├── templateWithLayout.liquid │ │ ├── templateWithLayoutContent.liquid │ │ ├── templateWithLayoutKey.liquid │ │ ├── templatetest-frontmatter/ │ │ │ ├── multiple.njk │ │ │ └── single.njk │ │ ├── test-override-js-markdown.11ty.cjs │ │ ├── testing.html │ │ ├── transform-pages/ │ │ │ └── template.njk │ │ ├── use-collection.11ty.cjs │ │ ├── vue-layout.11ty.cjs │ │ ├── vue.11ty.cjs │ │ ├── writeTest/ │ │ │ └── test.md │ │ ├── writeTestJS/ │ │ │ ├── sample.cjs │ │ │ └── test.11ty.cjs │ │ ├── writeTestJS-casesensitive/ │ │ │ ├── sample.Js │ │ │ └── test.11Ty.js │ │ ├── writeTestJS-passthrough/ │ │ │ ├── sample.js │ │ │ └── test.11ty.js │ │ └── writeTestMarkdown/ │ │ ├── sample.md │ │ └── sample2.markdown │ ├── stubs--to/ │ │ ├── test.md │ │ └── test2.liquid │ ├── stubs-1206/ │ │ ├── page1.njk │ │ └── page2.njk │ ├── stubs-1242/ │ │ ├── _data/ │ │ │ ├── xyz.dottest/ │ │ │ │ └── test.json │ │ │ └── xyz.dottest.json │ │ └── empty.md │ ├── stubs-1325/ │ │ ├── test.11ty.js │ │ └── test.js │ ├── stubs-142/ │ │ └── index.njk │ ├── stubs-1691/ │ │ ├── _data/ │ │ │ └── str.txt │ │ ├── template.11tydata.txt │ │ └── template.njk │ ├── stubs-2145/ │ │ ├── _includes/ │ │ │ └── layout.njk │ │ └── test.njk │ ├── stubs-2167/ │ │ └── paginated.njk │ ├── stubs-2224/ │ │ └── index.njk │ ├── stubs-2258/ │ │ ├── _includes/ │ │ │ ├── _code.scss │ │ │ └── layout.njk │ │ ├── eleventy.config.cjs │ │ └── style.scss │ ├── stubs-2258-2830-skip-layouts/ │ │ ├── _includes/ │ │ │ └── layout.njk │ │ ├── eleventy.config.cjs │ │ └── style.scss │ ├── stubs-2261/ │ │ ├── _includes/ │ │ │ └── block.njk │ │ ├── eleventy.config.js │ │ └── index.njk │ ├── stubs-2367/ │ │ ├── _includes/ │ │ │ └── layout.liquid │ │ ├── templateWithLiquidShortcodeMultipleArguments-template2.liquid │ │ └── templateWithLiquidShortcodeMultipleArguments.liquid │ ├── stubs-2602/ │ │ └── index.njk │ ├── stubs-2753/ │ │ ├── _data/ │ │ │ └── global.js │ │ ├── page1.njk │ │ └── page2.njk │ ├── stubs-2790/ │ │ └── page.11ty.cjs │ ├── stubs-2851/ │ │ ├── content.njk │ │ └── paginated.njk │ ├── stubs-3013/ │ │ ├── html/ │ │ │ ├── _data/ │ │ │ │ └── books.json │ │ │ ├── _includes/ │ │ │ │ └── base.html │ │ │ └── book.html │ │ ├── liquid/ │ │ │ ├── _data/ │ │ │ │ └── books.json │ │ │ ├── _includes/ │ │ │ │ └── base.liquid │ │ │ └── book.liquid │ │ ├── md/ │ │ │ ├── _data/ │ │ │ │ └── books.json │ │ │ ├── _includes/ │ │ │ │ └── base.md │ │ │ └── book.md │ │ └── njk/ │ │ ├── _data/ │ │ │ └── books.json │ │ ├── _includes/ │ │ │ └── base.njk │ │ └── book.njk │ ├── stubs-3285/ │ │ └── src/ │ │ └── scripts/ │ │ └── hello-world.js │ ├── stubs-3356/ │ │ └── .gitkeep │ ├── stubs-337/ │ │ ├── data/ │ │ │ └── xyz.json │ │ └── src/ │ │ └── empty.md │ ├── stubs-3807/ │ │ ├── Issue3807test.js │ │ ├── _layouts/ │ │ │ ├── base.html │ │ │ └── home.html │ │ ├── eleventy.config.js │ │ └── index.md │ ├── stubs-3810/ │ │ ├── _includes/ │ │ │ └── promo.njk │ │ ├── eleventy.config.js │ │ └── index.md │ ├── stubs-403/ │ │ ├── .eleventyignore │ │ ├── _includes/ │ │ │ └── include.liquid │ │ └── template.liquid │ ├── stubs-408-sass/ │ │ ├── _code.scss │ │ └── style.scss │ ├── stubs-413/ │ │ └── date-frontmatter.md │ ├── stubs-434/ │ │ └── _includes/ │ │ ├── macros-filter.njk │ │ └── macros.njk │ ├── stubs-475/ │ │ ├── _includes/ │ │ │ └── layout.njk │ │ └── transform-layout/ │ │ └── transform-layout.njk │ ├── stubs-630/ │ │ ├── _data/ │ │ │ ├── globalData0.cjs │ │ │ ├── globalData1.cjs │ │ │ ├── globalData2.json │ │ │ ├── globalData3.yaml │ │ │ ├── globalData4.nosj │ │ │ ├── mergingGlobalData.cjs │ │ │ ├── mergingGlobalData.js │ │ │ ├── mergingGlobalData.json │ │ │ ├── mergingGlobalData.nosj │ │ │ ├── mergingGlobalData.yaml │ │ │ └── subdir/ │ │ │ └── globalDataSubdir.yaml │ │ └── component-yaml/ │ │ ├── component.11tydata.cjs │ │ ├── component.11tydata.json │ │ ├── component.11tydata.nosj │ │ ├── component.11tydata.yaml │ │ ├── component.json │ │ ├── component.njk │ │ └── component.yaml │ ├── stubs-670/ │ │ ├── content.njk │ │ └── index.njk │ ├── stubs-919/ │ │ ├── test.11tydata.cjs │ │ ├── test.njk │ │ └── test2.njk │ ├── stubs-absolute/ │ │ └── test.md │ ├── stubs-addglobaldata/ │ │ └── test.liquid │ ├── stubs-addglobaldata-noop/ │ │ └── test.txt │ ├── stubs-autocopy/ │ │ └── .gitkeep │ ├── stubs-base/ │ │ └── index.njk │ ├── stubs-base-case-sens/ │ │ └── index.njk │ ├── stubs-circular-layout/ │ │ └── _includes/ │ │ ├── layout-cycle-a.njk │ │ ├── layout-cycle-b.njk │ │ ├── layout-cycle-c.njk │ │ └── layout-cycle-self.njk │ ├── stubs-computed-array/ │ │ └── test.liquid │ ├── stubs-computed-collections/ │ │ ├── collections.njk │ │ └── dog.njk │ ├── stubs-computed-collections-filter/ │ │ ├── collections.njk │ │ └── dog.njk │ ├── stubs-computed-dirdata/ │ │ └── dir/ │ │ ├── dir.11tydata.cjs │ │ ├── first.11ty.cjs │ │ └── second.11ty.cjs │ ├── stubs-computed-global/ │ │ ├── _data/ │ │ │ └── eleventyComputed.cjs │ │ └── intermix.njk │ ├── stubs-computed-pagination/ │ │ ├── child.11ty.cjs │ │ └── paginated.njk │ ├── stubs-computed-symbolparse/ │ │ ├── test.liquid │ │ └── test.njk │ ├── stubs-custom-extension/ │ │ └── test.js1 │ ├── stubs-data-cascade/ │ │ ├── global-versus-layout/ │ │ │ ├── _data/ │ │ │ │ └── cascade.cjs │ │ │ ├── _includes/ │ │ │ │ └── base.njk │ │ │ └── test.njk │ │ ├── layout-data-files/ │ │ │ ├── _includes/ │ │ │ │ └── base.njk │ │ │ ├── test.11tydata.cjs │ │ │ └── test.njk │ │ ├── layout-versus-dirdatafile/ │ │ │ └── src/ │ │ │ ├── _includes/ │ │ │ │ └── base.njk │ │ │ ├── src.11tydata.cjs │ │ │ └── test.njk │ │ └── layout-versus-tmpldatafile/ │ │ ├── _includes/ │ │ │ └── base.njk │ │ ├── test.11tydata.cjs │ │ └── test.njk │ ├── stubs-data-esm/ │ │ └── _data/ │ │ ├── commonjs.cjs │ │ └── module.mjs │ ├── stubs-dependency-tree/ │ │ ├── child.cjs │ │ ├── grandchild.cjs │ │ └── index.cjs │ ├── stubs-empty/ │ │ └── .gitkeep │ ├── stubs-empty-json-data/ │ │ └── _data/ │ │ └── empty.json │ ├── stubs-fancyjs/ │ │ ├── test.11ty.tsx │ │ └── test.mdx │ ├── stubs-freeze/ │ │ ├── eleventy/ │ │ │ └── _data/ │ │ │ └── eleventy.js │ │ └── page/ │ │ └── _data/ │ │ └── page.js │ ├── stubs-global-data-config-api/ │ │ └── empty.txt │ ├── stubs-global-data-config-api-nested/ │ │ └── _data/ │ │ └── deep.cjs │ ├── stubs-i18n/ │ │ ├── en/ │ │ │ └── index.liquid │ │ ├── en-us/ │ │ │ └── index.11ty.cjs │ │ ├── es/ │ │ │ └── index.njk │ │ └── non-lang-file.njk │ ├── stubs-img-transform/ │ │ ├── ignored.md │ │ ├── missing-alt.md │ │ ├── multiple.md │ │ └── single.md │ ├── stubs-incremental/ │ │ └── layout-chain/ │ │ ├── _includes/ │ │ │ ├── base.njk │ │ │ └── parent.njk │ │ └── test.njk │ ├── stubs-layout-cache/ │ │ ├── _includes/ │ │ │ ├── layout.liquid │ │ │ └── layout.njk │ │ ├── test.liquid │ │ └── test.njk │ ├── stubs-layouts-event/ │ │ ├── _includes/ │ │ │ ├── first.liquid │ │ │ ├── second.liquid │ │ │ └── third.liquid │ │ └── page.md │ ├── stubs-njk-async/ │ │ └── _includes/ │ │ └── loop.njk │ ├── stubs-pagination-computed-quotes/ │ │ ├── post.liquid │ │ └── test.liquid │ ├── stubs-pagination-computed-quotes-njk/ │ │ ├── post.njk │ │ └── test.njk │ ├── stubs-pathtourl/ │ │ ├── css.njk │ │ ├── filter.njk │ │ ├── tmpl.njk │ │ └── transform.njk │ ├── stubs-render-plugin/ │ │ ├── 11tyjs-file-override.njk │ │ ├── 11tyjs-file.njk │ │ ├── 11tyjs.liquid │ │ ├── _includes/ │ │ │ ├── frontmatter.liquid │ │ │ ├── include-js.txt │ │ │ ├── include.11ty.cjs │ │ │ ├── include.liquid │ │ │ └── include.njk │ │ ├── bad-data.njk │ │ ├── capture-liquid.njk │ │ ├── capture-njk.liquid │ │ ├── data-no-templatelang.liquid │ │ ├── false.liquid │ │ ├── liquid-direct.njk │ │ ├── liquid-eleventy.njk │ │ ├── liquid-global.njk │ │ ├── liquid-md.11ty.cjs │ │ ├── liquid-md.liquid │ │ ├── liquid-page.liquid │ │ ├── liquid-page.njk │ │ ├── liquid.njk │ │ ├── md.liquid │ │ ├── njk-eleventy.liquid │ │ ├── njk-file-not-exist.liquid │ │ ├── njk-file.liquid │ │ ├── njk-file.njk │ │ ├── njk-page.liquid │ │ ├── nunjucks-frontmatter.njk │ │ ├── nunjucks-global.liquid │ │ ├── nunjucks.11ty.cjs │ │ ├── nunjucks.liquid │ │ ├── using-frontmatter.liquid │ │ └── vue.liquid │ ├── stubs-virtual/ │ │ ├── .gitkeep │ │ └── eleventy.config.js │ ├── stubs-virtual-nowrite/ │ │ └── .gitkeep │ └── views/ │ └── .gitkeep ├── test_node/ │ ├── 3824/ │ │ ├── 3824-test.js │ │ ├── _includes/ │ │ │ ├── head.tsx │ │ │ └── view-props.tsx │ │ ├── eleventy.config.js │ │ ├── index.11ty.tsx │ │ └── tsconfig-3824.json │ ├── 3824-incremental/ │ │ ├── 3824-incremental-test.js │ │ ├── _includes/ │ │ │ ├── head.tsx │ │ │ └── view-props.tsx │ │ ├── eleventy.config.js │ │ ├── index.11ty.tsx │ │ └── tsconfig-3824.json │ ├── JsxTest.js │ ├── MdxTest.js │ ├── README.md │ └── tests.js └── tsconfig.json
SYMBOL INDEX (1627 symbols across 223 files)
FILE: cmd.cjs
class SimpleError (line 22) | class SimpleError extends Error {
method constructor (line 23) | constructor(...args) {
function exec (line 29) | async function exec() {
FILE: eslint.config.js
constant GLOB_SRC_EXT (line 6) | const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
constant GLOB_TESTS (line 8) | const GLOB_TESTS = [
FILE: packages/client/generate-bundle.js
constant PREFIX (line 7) | const PREFIX = `[11ty/bundle/client] `;
function size (line 9) | function size(filepath) {
FILE: packages/client/src/shims/process.cjs
function defaultSetTimout (line 14) | function defaultSetTimout() {
function defaultClearTimeout (line 17) | function defaultClearTimeout () {
function runTimeout (line 40) | function runTimeout(fun) {
function runClearTimeout (line 65) | function runClearTimeout(marker) {
function cleanUpNextTick (line 97) | function cleanUpNextTick() {
function drainQueue (line 112) | function drainQueue() {
function Item (line 150) | function Item(fun, array) {
function noop (line 164) | function noop() {}
FILE: packages/client/src/shims/shim-core.js
class Buffer (line 10) | class Buffer {
method isBuffer (line 15) | static isBuffer() {
method [Symbol.hasInstance] (line 11) | static [Symbol.hasInstance](instance) {
FILE: packages/client/test/shared-tests.js
method config (line 14) | config(eleventyConfig) {
method config (line 30) | config(eleventyConfig) {
method config (line 47) | config(eleventyConfig) {
method config (line 60) | config(eleventyConfig) {
method config (line 74) | config(eleventyConfig) {
method config (line 95) | config(eleventyConfig) {
method config (line 109) | config(eleventyConfig) {
FILE: src/Adapters/Packages/chalk.client.js
function noop (line 1) | function noop(arg) {
FILE: src/Adapters/Packages/inspect.core.js
function inspect (line 1) | function inspect(target) {
FILE: src/Adapters/Packages/inspect.js
function inspect (line 3) | function inspect(target) {
FILE: src/Adapters/Packages/semver.client.js
function satisfies (line 1) | function satisfies(version, range) {
FILE: src/Adapters/Packages/url.core.js
function fileURLToPath (line 6) | function fileURLToPath(url) {
FILE: src/Benchmark/Benchmark.js
class Benchmark (line 1) | class Benchmark {
method constructor (line 2) | constructor() {
method reset (line 9) | reset() {
method getNewTimestamp (line 15) | getNewTimestamp() {
method incrementCount (line 22) | incrementCount() {
method before (line 28) | before() {
method after (line 33) | after() {
method getTimesCalled (line 44) | getTimesCalled() {
method getTotal (line 48) | getTotal() {
FILE: src/Benchmark/BenchmarkGroup.js
class BenchmarkGroup (line 9) | class BenchmarkGroup {
method constructor (line 10) | constructor() {
method setIsVerbose (line 19) | setIsVerbose(isVerbose) {
method reset (line 24) | reset() {
method add (line 31) | add(type, callback) {
method setMinimumThresholdMs (line 65) | setMinimumThresholdMs(minimumThresholdMs) {
method setMinimumThresholdPercent (line 73) | setMinimumThresholdPercent(minimumThresholdPercent) {
method has (line 81) | has(type) {
method get (line 85) | get(type) {
method padNumber (line 92) | padNumber(num, length) {
method finish (line 101) | finish(label, totalTimeSpent) {
FILE: src/Benchmark/BenchmarkManager.js
class BenchmarkManager (line 5) | class BenchmarkManager {
method constructor (line 6) | constructor() {
method reset (line 12) | reset() {
method getNewTimestamp (line 20) | getNewTimestamp() {
method setVerboseOutput (line 27) | setVerboseOutput(isVerbose) {
method hasBenchmarkGroup (line 31) | hasBenchmarkGroup(name) {
method getBenchmarkGroup (line 35) | getBenchmarkGroup(name) {
method getAll (line 51) | getAll() {
method get (line 55) | get(name) {
method finish (line 63) | finish() {
FILE: src/Core.js
class Core (line 7) | class Core extends MinimalCore {
method initializeConfig (line 8) | async initializeConfig(initOverrides) {
method init (line 15) | async init(options = {}) {
method restart (line 43) | async restart() {
FILE: src/CoreMinimal.js
class MinimalCore (line 33) | class MinimalCore {
method #normalizeConstructorArguments (line 69) | #normalizeConstructorArguments(...args) {
method constructor (line 111) | constructor(...args) {
method configPath (line 211) | get configPath() {
method pathPrefix (line 220) | get pathPrefix() {
method getVersion (line 230) | static getVersion() {
method getVersion (line 237) | getVersion() {
method initializeConfig (line 241) | async initializeConfig(initOverrides) {
method getNewTimestamp (line 316) | getNewTimestamp() {
method directories (line 324) | get directories() {
method input (line 339) | get input() {
method inputFile (line 344) | get inputFile() {
method inputDir (line 349) | get inputDir() {
method setInputDir (line 354) | setInputDir() {
method outputDir (line 361) | get outputDir() {
method setDryRun (line 370) | setDryRun(isDryRun) {
method setIncrementalBuild (line 379) | setIncrementalBuild(isIncremental) {
method setIgnoreInitial (line 393) | setIgnoreInitial(ignoreInitialBuild) {
method setPathPrefix (line 406) | setPathPrefix(pathPrefix) {
method restart (line 417) | async restart() {
method #cache (line 425) | #cache(key, inst) {
method init (line 449) | async init(options = {}) {
method getEnvironmentVariableValues (line 513) | getEnvironmentVariableValues() {
method initializeEnvironmentVariables (line 542) | initializeEnvironmentVariables(env) {
method verboseMode (line 556) | set verboseMode(value) {
method verboseMode (line 561) | get verboseMode() {
method logger (line 566) | get logger() {
method logger (line 576) | set logger(logger) {
method disableLogger (line 581) | disableLogger() {
method errorHandler (line 586) | get errorHandler() {
method setIsVerbose (line 602) | setIsVerbose(isVerbose) {
method templateFormats (line 631) | get templateFormats() {
method setFormats (line 646) | setFormats(formats) {
method setRunMode (line 656) | setRunMode(runMode) {
method setIncrementalFile (line 667) | setIncrementalFile(incrementalFile) {
method unsetIncrementalFile (line 679) | unsetIncrementalFile() {
method resetConfig (line 695) | async resetConfig() {
method projectPackageJsonPath (line 703) | get projectPackageJsonPath() {
method projectPackageJson (line 710) | get projectPackageJson() {
method isEsm (line 718) | get isEsm() {
method write (line 749) | async write(subtype) {
method toJSON (line 767) | async toJSON() {
method toNDJSON (line 771) | toNDJSON() {
method executeBuild (line 782) | async executeBuild(to = "fs") {
method logFinished (line 901) | logFinished() {
FILE: src/Data/ComputedData.js
class ComputedData (line 11) | class ComputedData {
method constructor (line 12) | constructor(config) {
method add (line 22) | add(key, renderFn, declaredDependencies = [], symbolParseFn, templateI...
method addTemplateString (line 47) | addTemplateString(key, renderFn, declaredDependencies = [], symbolPars...
method resolveVarOrder (line 52) | async resolveVarOrder(data) {
method _setupDataEntry (line 90) | async _setupDataEntry(data, order) {
method setupData (line 104) | async setupData(data, orderFilter) {
method processRemainingData (line 110) | async processRemainingData(data, orderFilter) {
FILE: src/Data/ComputedDataProxy.js
class ComputedDataProxy (line 7) | class ComputedDataProxy {
method constructor (line 8) | constructor(computedKeys) {
method isArrayOrPlainObject (line 16) | isArrayOrPlainObject(data) {
method getProxyData (line 20) | getProxyData(data, keyRef) {
method _getProxyForObject (line 39) | _getProxyForObject(dataObj, keyRef, parentKey = "") {
method _getProxyForArray (line 79) | _getProxyForArray(dataArr, keyRef, parentKey = "") {
method _getProxyData (line 104) | _getProxyData(data, keyRef, parentKey = "") {
method findVarsUsed (line 115) | async findVarsUsed(fn, data = {}) {
FILE: src/Data/ComputedDataQueue.js
class ComputedDataQueue (line 6) | class ComputedDataQueue {
method constructor (line 7) | constructor() {
method getOrder (line 11) | getOrder() {
method getOrderFor (line 15) | getOrderFor(name) {
method getDependsOn (line 19) | getDependsOn(name) {
method isUsesStartsWith (line 23) | isUsesStartsWith(name, prefix) {
method addNode (line 34) | addNode(name) {
method _uses (line 40) | _uses(graph, name, varsUsed = []) {
method uses (line 53) | uses(name, varsUsed = []) {
method markComputed (line 57) | markComputed(varsComputed = []) {
FILE: src/Data/ComputedDataTemplateString.js
class ComputedDataTemplateString (line 12) | class ComputedDataTemplateString {
method constructor (line 13) | constructor(computedKeys) {
method getProxyData (line 26) | getProxyData() {
method findVarsInOutput (line 40) | findVarsInOutput(output = "") {
method findVarsUsed (line 52) | async findVarsUsed(fn) {
FILE: src/Data/TemplateData.js
class TemplateDataParseError (line 24) | class TemplateDataParseError extends EleventyBaseError {}
class TemplateData (line 26) | class TemplateData {
method constructor (line 27) | constructor(templateConfig) {
method dirs (line 50) | get dirs() {
method inputDir (line 54) | get inputDir() {
method dataDir (line 59) | get dataDir() {
method absoluteDataDir (line 63) | get absoluteDataDir() {
method getInputDir (line 68) | getInputDir() {
method getDataDir (line 72) | getDataDir() {
method exists (line 76) | exists(pathname) {
method setFileSystemSearch (line 82) | setFileSystemSearch(fileSystemSearch) {
method setProjectUsingEsm (line 86) | setProjectUsingEsm(isEsmProject) {
method extensionMap (line 90) | get extensionMap() {
method extensionMap (line 97) | set extensionMap(map) {
method environmentVariables (line 101) | get environmentVariables() {
method environmentVariables (line 105) | set environmentVariables(env) {
method _setConfig (line 110) | _setConfig(config) {
method getRawImports (line 114) | getRawImports() {
method clearData (line 134) | clearData() {
method _getGlobalDataGlobByExtension (line 140) | _getGlobalDataGlobByExtension(extension) {
method getDataFileSuffixes (line 145) | getDataFileSuffixes() {
method getTemplateDataFileGlob (line 162) | async getTemplateDataFileGlob() {
method getTemplateJavaScriptDataFileGlob (line 218) | getTemplateJavaScriptDataFileGlob() {
method getGlobalDataGlob (line 232) | getGlobalDataGlob() {
method getWatchPathCache (line 237) | getWatchPathCache() {
method getGlobalDataExtensionPriorities (line 241) | getGlobalDataExtensionPriorities() {
method calculateExtensionPriority (line 245) | static calculateExtensionPriority(path, priorities) {
method getGlobalDataFiles (line 255) | async getGlobalDataFiles() {
method getObjectPathForDataFile (line 286) | getObjectPathForDataFile(dataFilePath) {
method getAllGlobalData (line 296) | async getAllGlobalData() {
method #getInitialGlobalData (line 337) | async #getInitialGlobalData() {
method getInitialGlobalData (line 373) | async getInitialGlobalData() {
method #getGlobalData (line 381) | async #getGlobalData() {
method getGlobalData (line 392) | async getGlobalData() {
method combineLocalData (line 401) | async combineLocalData(localDataPaths) {
method getTemplateDirectoryData (line 449) | async getTemplateDirectoryData(templatePath) {
method getUserDataExtensions (line 459) | getUserDataExtensions() {
method getUserDataParser (line 469) | getUserDataParser(extension) {
method isUserDataExtension (line 473) | isUserDataExtension(extension) {
method hasUserDataExtensions (line 477) | hasUserDataExtensions() {
method _parseDataFile (line 481) | async _parseDataFile(path, parser, options = {}) {
method getDataValue (line 508) | async getDataValue(path) {
method _pushExtensionsToPaths (line 558) | _pushExtensionsToPaths(paths, curpath, extensions) {
method _addBaseToPaths (line 564) | _addBaseToPaths(paths, base, extensions, nonEmptySuffixesOnly = false) {
method getLocalDataPaths (line 587) | async getLocalDataPaths(templatePath) {
method getCleanedTagsImmutable (line 654) | static getCleanedTagsImmutable(data, options = {}) {
method cleanupData (line 676) | static cleanupData(data, options = {}) {
method getNormalizedExcludedCollections (line 684) | static getNormalizedExcludedCollections(data) {
method getIncludedCollectionNames (line 702) | static getIncludedCollectionNames(data) {
method getIncludedTagNames (line 713) | static getIncludedTagNames(data) {
FILE: src/Data/TemplateDataInitialGlobalData.js
class TemplateDataConfigError (line 8) | class TemplateDataConfigError extends EleventyBaseError {}
class TemplateDataInitialGlobalData (line 10) | class TemplateDataInitialGlobalData {
method constructor (line 11) | constructor(templateConfig) {
method getData (line 19) | async getData() {
FILE: src/Eleventy.js
class Eleventy (line 23) | class Eleventy extends Core {
method setIncrementalBuild (line 39) | setIncrementalBuild(isIncremental) {
method watchQueue (line 47) | get watchQueue() {
method initializeConfig (line 55) | async initializeConfig(initOverrides) {
method resetConfig (line 70) | async resetConfig() {
method init (line 82) | async init(options = {}) {
method #addFileToWatchQueue (line 100) | async #addFileToWatchQueue(changedFilePath, isResetConfig) {
method shouldTriggerConfigReset (line 128) | shouldTriggerConfigReset(changedFiles) {
method #shouldResetConfig (line 161) | #shouldResetConfig(activeQueue = []) {
method #rewatch (line 173) | async #rewatch(isResetConfig = false) {
method watcherBench (line 283) | get watcherBench() {
method startWatch (line 293) | async startWatch() {
method #initWatchDependencies (line 400) | async #initWatchDependencies() {
method getWatchedTargets (line 440) | async getWatchedTargets() {
method watch (line 453) | async watch() {
method stopWatch (line 475) | async stopWatch() {
method close (line 479) | async close() {
method serve (line 498) | async serve(port) {
method getHelp (line 510) | static getHelp() {
method getHelp (line 573) | getHelp() {
method initWatch (line 578) | initWatch() {
method getWatchedFiles (line 583) | getWatchedFiles() {
function EleventyServerlessBundlerPlugin (line 616) | function EleventyServerlessBundlerPlugin() {
function EleventyEdgePlugin (line 624) | function EleventyEdgePlugin() {
FILE: src/EleventyCommonJs.cjs
function canRequireModules (line 1) | function canRequireModules() {
FILE: src/EleventyExtensionMap.js
class EleventyExtensionMap (line 5) | class EleventyExtensionMap {
method constructor (line 8) | constructor(config) {
method setFormats (line 16) | setFormats(formatKeys = []) {
method setTemplateConfig (line 31) | setTemplateConfig(config) {
method config (line 39) | get config() {
method engineManager (line 43) | get engineManager() {
method engineManager (line 51) | set engineManager(mgr) {
method reset (line 55) | reset() {
method getFileList (line 60) | getFileList(path, dir) {
method isFullTemplateFilePath (line 78) | isFullTemplateFilePath(path) {
method getCustomExtensionEntry (line 87) | getCustomExtensionEntry(extension) {
method getValidExtensionsForPath (line 99) | getValidExtensionsForPath(path) {
method shouldSpiderJavaScriptDependencies (line 116) | async shouldSpiderJavaScriptDependencies(path) {
method getPassthroughCopyGlobs (line 135) | getPassthroughCopyGlobs(inputDir) {
method getValidGlobs (line 139) | getValidGlobs(inputDir) {
method getGlobs (line 143) | getGlobs(inputDir) {
method _getGlobs (line 147) | _getGlobs(formatKeys, inputDir = "") {
method hasExtension (line 173) | hasExtension(key) {
method getExtensionsFromKey (line 186) | getExtensionsFromKey(key) {
method getExtensionEntriesFromKey (line 204) | getExtensionEntriesFromKey(key) {
method hasEngine (line 217) | hasEngine(pathOrKey) {
method getKey (line 221) | getKey(pathOrKey) {
method getExtensionEntry (line 235) | getExtensionEntry(pathOrKey) {
method removeTemplateExtension (line 244) | removeTemplateExtension(path) {
method extensionToKeyMap (line 258) | get extensionToKeyMap() {
method getReadableFileExtensions (line 287) | getReadableFileExtensions() {
FILE: src/EleventyFiles.js
class EleventyFiles (line 13) | class EleventyFiles {
method constructor (line 17) | constructor(formats, templateConfig) {
method dirs (line 30) | get dirs() {
method inputDir (line 34) | get inputDir() {
method outputDir (line 38) | get outputDir() {
method includesDir (line 42) | get includesDir() {
method layoutsDir (line 46) | get layoutsDir() {
method dataDir (line 50) | get dataDir() {
method getDataDir (line 55) | getDataDir() {
method setFileSystemSearch (line 59) | setFileSystemSearch(fileSystemSearch) {
method init (line 63) | init() {
method #getWatcherGlobs (line 74) | #getWatcherGlobs() {
method passthroughGlobs (line 90) | get passthroughGlobs() {
method restart (line 103) | restart() {
method _setConfig (line 109) | _setConfig(config) {
method _setLocalPathRoot (line 122) | _setLocalPathRoot(dir) {
method extensionMap (line 126) | set extensionMap(extensionMap) {
method extensionMap (line 130) | get extensionMap() {
method setRunMode (line 138) | setRunMode(runMode) {
method setPassthroughManager (line 142) | setPassthroughManager(mgr) {
method templateData (line 146) | set templateData(templateData) {
method templateData (line 150) | get templateData() {
method setupGlobs (line 154) | setupGlobs() {
method normalizeIgnoreEntry (line 167) | normalizeIgnoreEntry(entry) {
method getIgnoreGlobs (line 174) | getIgnoreGlobs() {
method getFileIgnores (line 191) | static getFileIgnores(ignoreFiles) {
method normalizeIgnoreContent (line 215) | static normalizeIgnoreContent(dir, ignoreContent) {
method _setEleventyIgnoreContent (line 257) | _setEleventyIgnoreContent(content) {
method getIgnores (line 261) | getIgnores() {
method getIgnoreFiles (line 286) | getIgnoreFiles() {
method getIncludesDir (line 307) | getIncludesDir() {
method getLayoutsDir (line 312) | getLayoutsDir() {
method getFileGlobs (line 316) | getFileGlobs() {
method getRawFiles (line 320) | getRawFiles() {
method getWatchPathCache (line 324) | async getWatchPathCache() {
method _globSearch (line 343) | _globSearch() {
method getFiles (line 353) | async getFiles() {
method getFileShape (line 366) | getFileShape(paths, filePath) {
method isPassthroughCopyFile (line 379) | isPassthroughCopyFile(paths, filePath) {
method isFullTemplateFile (line 384) | isFullTemplateFile(paths, filePath) {
method getGlobWatcherFiles (line 399) | getGlobWatcherFiles() {
method getGlobWatcherFilesForPassthroughCopy (line 413) | getGlobWatcherFilesForPassthroughCopy() {
method getGlobWatcherTemplateDataFiles (line 418) | async getGlobWatcherTemplateDataFiles() {
method getWatcherTemplateJavaScriptDataFiles (line 425) | async getWatcherTemplateJavaScriptDataFiles() {
method getGlobWatcherIgnores (line 444) | getGlobWatcherIgnores() {
method getIncludesAndDataDirs (line 458) | getIncludesAndDataDirs() {
FILE: src/EleventyServe.js
function stringifyOptions (line 6) | function stringifyOptions(options) {
class EleventyServeConfigError (line 26) | class EleventyServeConfigError extends EleventyBaseError {}
constant DEFAULT_SERVER_OPTIONS (line 28) | const DEFAULT_SERVER_OPTIONS = {
class EleventyServe (line 37) | class EleventyServe {
method constructor (line 46) | constructor() {
method config (line 50) | get config() {
method config (line 60) | set config(config) {
method setAliases (line 64) | setAliases(aliases) {
method eleventyConfig (line 72) | get eleventyConfig() {
method eleventyConfig (line 82) | set eleventyConfig(config) {
method setOutputDir (line 94) | setOutputDir(outputDir) {
method getDevServer (line 100) | static getDevServer() {
method getServerModule (line 106) | async getServerModule(name) {
method options (line 164) | get options() {
method server (line 189) | get server() {
method initServerInstance (line 197) | async initServerInstance() {
method getSetupCallback (line 223) | getSetupCallback() {
method #init (line 230) | async #init() {
method init (line 242) | async init() {
method serve (line 251) | async serve(port) {
method close (line 273) | async close() {
method sendError (line 281) | async sendError({ error }) {
method resetConfig (line 290) | resetConfig() {
method restart (line 297) | async restart() {
method watchPassthroughCopy (line 308) | watchPassthroughCopy(globs = []) {
method isEmulatedPassthroughCopyMatch (line 319) | isEmulatedPassthroughCopyMatch(filepath) {
method hasOptionsChanged (line 323) | hasOptionsChanged() {
method reload (line 330) | async reload(reloadEvent = {}) {
FILE: src/Engines/Custom.js
class CustomEngine (line 4) | class CustomEngine extends TemplateEngine {
method constructor (line 5) | constructor(name, eleventyConfig) {
method getExtensionMapEntry (line 14) | getExtensionMapEntry() {
method setDefaultEngine (line 31) | setDefaultEngine(defaultEngine) {
method cacheable (line 35) | get cacheable() {
method getInstanceFromInputPath (line 48) | async getInstanceFromInputPath(inputPath) {
method useJavaScriptImport (line 75) | useJavaScriptImport() {
method needsToReadFileContents (line 94) | needsToReadFileContents() {
method _runningInit (line 110) | async _runningInit() {
method getExtraDataFromFile (line 130) | async getExtraDataFromFile(inputPath) {
method compile (line 211) | async compile(str, inputPath, ...args) {
method defaultTemplateFileExtension (line 264) | get defaultTemplateFileExtension() {
method useLayouts (line 269) | useLayouts() {
method hasDependencies (line 274) | hasDependencies(inputPath) {
method isFileRelevantTo (line 281) | isFileRelevantTo(inputPath, comparisonFile, includeLayouts) {
method getCompileCacheKey (line 285) | getCompileCacheKey(str, inputPath) {
method permalinkNeedsCompilation (line 312) | permalinkNeedsCompilation(/*str*/) {
method shouldSpiderJavaScriptDependencies (line 332) | static shouldSpiderJavaScriptDependencies(entry) {
FILE: src/Engines/Html.js
class Html (line 3) | class Html extends TemplateEngine {
method constructor (line 4) | constructor(name, eleventyConfig) {
method cacheable (line 8) | get cacheable() {
method #getPreEngine (line 12) | async #getPreEngine(preTemplateEngine) {
method compile (line 16) | async compile(str, inputPath, preTemplateEngine) {
FILE: src/Engines/JavaScript.js
class JavaScriptTemplateNotDefined (line 9) | class JavaScriptTemplateNotDefined extends EleventyBaseError {}
class JavaScript (line 11) | class JavaScript extends TemplateEngine {
method constructor (line 12) | constructor(name, templateConfig) {
method cacheable (line 32) | get cacheable() {
method normalize (line 36) | normalize(result) {
method _getInstance (line 48) | _getInstance(mod) {
method #getInstanceFromInputPath (line 111) | async #getInstanceFromInputPath(inputPath) {
method getInstanceFromInputPath (line 136) | async getInstanceFromInputPath(inputPath) {
method needsToReadFileContents (line 149) | needsToReadFileContents() {
method useJavaScriptImport (line 158) | useJavaScriptImport() {
method getExtraDataFromFile (line 162) | async getExtraDataFromFile(inputPath) {
method getJavaScriptFunctions (line 167) | getJavaScriptFunctions(inst) {
method wrapJavaScriptFunction (line 182) | static wrapJavaScriptFunction(inst, fn) {
method addExportsToBundles (line 188) | addExportsToBundles(inst, url) {
method compile (line 227) | async compile(str, inputPath) {
method shouldSpiderJavaScriptDependencies (line 259) | static shouldSpiderJavaScriptDependencies() {
FILE: src/Engines/Liquid.js
class Liquid (line 11) | class Liquid extends TemplateEngine {
method constructor (line 20) | constructor(name, eleventyConfig) {
method cacheable (line 30) | get cacheable() {
method setLibrary (line 34) | setLibrary(override) {
method getLiquidOptions (line 47) | getLiquidOptions() {
method wrapFilter (line 62) | static wrapFilter(name, fn) {
method normalizeScope (line 83) | static normalizeScope(context) {
method addCustomTags (line 99) | addCustomTags(tags) {
method addFilters (line 105) | addFilters(filters) {
method addFilter (line 111) | addFilter(name, filter) {
method addTag (line 115) | addTag(name, tagFn) {
method addAllShortcodes (line 127) | addAllShortcodes(shortcodes) {
method addAllPairedShortcodes (line 133) | addAllPairedShortcodes(shortcodes) {
method parseArguments (line 139) | static parseArguments(lexer, str) {
method parseArgumentsBuiltin (line 174) | static parseArgumentsBuiltin(args) {
method addShortcode (line 192) | addShortcode(shortcodeName, shortcodeFn) {
method addPairedShortcode (line 228) | addPairedShortcode(shortcodeName, shortcodeFn) {
method parseForSymbols (line 279) | parseForSymbols(str) {
method permalinkNeedsCompilation (line 298) | permalinkNeedsCompilation(str) {
method needsCompilation (line 304) | needsCompilation(str) {
method compile (line 313) | async compile(str, inputPath) {
FILE: src/Engines/Markdown.js
class Markdown (line 5) | class Markdown extends TemplateEngine {
method constructor (line 6) | constructor(name, eleventyConfig) {
method cacheable (line 14) | get cacheable() {
method setLibrary (line 18) | setLibrary(mdLib) {
method setMarkdownOptions (line 37) | setMarkdownOptions(options) {
method getMarkdownOptions (line 41) | getMarkdownOptions() {
method #getPreEngine (line 60) | async #getPreEngine(preTemplateEngine) {
method compile (line 68) | async compile(str, inputPath, preTemplateEngine, bypassMarkdown) {
FILE: src/Engines/Nunjucks.js
class EleventyNunjucksError (line 18) | class EleventyNunjucksError extends EleventyBaseError {}
class Nunjucks (line 20) | class Nunjucks extends TemplateEngine {
method constructor (line 21) | constructor(name, eleventyConfig) {
method #getFileSystemDirs (line 37) | #getFileSystemDirs() {
method #setEnv (line 46) | #setEnv(override) {
method setLibrary (line 86) | setLibrary(override) {
method addFilters (line 140) | addFilters(filters, isAsync) {
method wrapFilter (line 146) | static wrapFilter(name, fn) {
method normalizeContext (line 165) | static normalizeContext(context) {
method addCustomTags (line 179) | addCustomTags(tags) {
method addTag (line 185) | addTag(name, tagFn) {
method addGlobals (line 198) | addGlobals(globals) {
method addGlobal (line 204) | addGlobal(name, globalFn) {
method addAllShortcodes (line 208) | addAllShortcodes(shortcodes, isAsync = false) {
method addAllPairedShortcodes (line 214) | addAllPairedShortcodes(shortcodes, isAsync = false) {
method _getShortcodeFn (line 220) | _getShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) {
method _getPairedShortcodeFn (line 292) | _getPairedShortcodeFn(shortcodeName, shortcodeFn, isAsync = false) {
method addShortcode (line 385) | addShortcode(shortcodeName, shortcodeFn, isAsync = false) {
method addPairedShortcode (line 390) | addPairedShortcode(shortcodeName, shortcodeFn, isAsync = false) {
method permalinkNeedsCompilation (line 396) | permalinkNeedsCompilation(str) {
method needsCompilation (line 402) | needsCompilation(str) {
method _getParseExtensions (line 417) | _getParseExtensions() {
method parseForSymbols (line 450) | parseForSymbols(str) {
method compile (line 488) | async compile(str, inputPath) {
FILE: src/Engines/TemplateEngine.js
class TemplateEngineConfigError (line 4) | class TemplateEngineConfigError extends EleventyBaseError {}
constant AMENDED_INSTANCES (line 8) | const AMENDED_INSTANCES = new Set();
class TemplateEngine (line 10) | class TemplateEngine {
method constructor (line 15) | constructor(name, eleventyConfig) {
method cacheable (line 26) | get cacheable() {
method dirs (line 30) | get dirs() {
method inputDir (line 34) | get inputDir() {
method includesDir (line 38) | get includesDir() {
method config (line 42) | get config() {
method benchmarks (line 50) | get benchmarks() {
method engineManager (line 59) | get engineManager() {
method engineManager (line 63) | set engineManager(manager) {
method extensionMap (line 67) | get extensionMap() {
method extensionMap (line 74) | set extensionMap(map) {
method extensions (line 78) | get extensions() {
method extensionEntries (line 85) | get extensionEntries() {
method getName (line 92) | getName() {
method getIncludesDir (line 97) | getIncludesDir() {
method setEngineLib (line 104) | setEngineLib(engineLib, isOverrideViaSetLibrary = false) {
method getEngineLib (line 128) | getEngineLib() {
method _testRender (line 132) | async _testRender(str, data) {
method useJavaScriptImport (line 138) | useJavaScriptImport() {
method needsToReadFileContents (line 143) | needsToReadFileContents() {
method getExtraDataFromFile (line 147) | getExtraDataFromFile() {
method getCompileCacheKey (line 151) | getCompileCacheKey(str, inputPath) {
method defaultTemplateFileExtension (line 163) | get defaultTemplateFileExtension() {
method useLayouts (line 168) | useLayouts() {
method permalinkNeedsCompilation (line 173) | permalinkNeedsCompilation(str) {
method needsCompilation (line 178) | needsCompilation(str) {
method compile (line 187) | async compile() {
method shouldSpiderJavaScriptDependencies (line 192) | static shouldSpiderJavaScriptDependencies() {
method hasDependencies (line 196) | hasDependencies(inputPath) {
method isFileRelevantTo (line 203) | isFileRelevantTo(inputPath, comparisonFile) {
FILE: src/Engines/TemplateEngineManager.js
class TemplateEngineManager (line 6) | class TemplateEngineManager {
method constructor (line 9) | constructor(eleventyConfig) {
method config (line 19) | get config() {
method isAlias (line 23) | static isAlias(entry) {
method isSimpleAlias (line 31) | static isSimpleAlias(entry) {
method keyToClassNameMap (line 44) | get keyToClassNameMap() {
method reset (line 86) | reset() {
method getClassNameFromTemplateKey (line 90) | getClassNameFromTemplateKey(key) {
method hasEngine (line 94) | hasEngine(name) {
method getEngineClassByExtension (line 98) | async getEngineClassByExtension(extension) {
method getCustomEngineClass (line 133) | async getCustomEngineClass() {
method #getEngine (line 140) | async #getEngine(name, extensionMap) {
method isEngineRemovedFromCore (line 179) | isEngineRemovedFromCore(name) {
method getEngine (line 183) | async getEngine(name, extensionMap) {
FILE: src/Engines/Util/ContextAugmenter.js
constant DATA_KEYS (line 1) | const DATA_KEYS = ["page", "eleventy"];
function augmentFunction (line 3) | function augmentFunction(fn, options = {}) {
function augmentObject (line 18) | function augmentObject(targetObject, options = {}) {
FILE: src/Errors/DuplicatePermalinkOutputError.js
class DuplicatePermalinkOutputError (line 3) | class DuplicatePermalinkOutputError extends EleventyBaseError {
method removeDuplicateErrorStringFromOutput (line 4) | get removeDuplicateErrorStringFromOutput() {
FILE: src/Errors/EleventyBaseError.js
class EleventyBaseError (line 5) | class EleventyBaseError extends Error {
method constructor (line 10) | constructor(message, originalError) {
FILE: src/Errors/EleventyErrorHandler.js
class EleventyErrorHandler (line 9) | class EleventyErrorHandler {
method constructor (line 10) | constructor() {
method isVerbose (line 14) | get isVerbose() {
method isVerbose (line 18) | set isVerbose(verbose) {
method logger (line 23) | get logger() {
method logger (line 32) | set logger(logger) {
method warn (line 36) | warn(e, msg) {
method fatal (line 40) | fatal(e, msg) {
method once (line 45) | once(type, e, msg) {
method error (line 57) | error(e, msg) {
method getTotalErrorCount (line 61) | static getTotalErrorCount(e) {
method log (line 72) | log(e, type = "log", chalkColor = "", forceToConsole = false, messages...
FILE: src/Errors/EleventyErrorUtil.js
class EleventyErrorUtil (line 4) | class EleventyErrorUtil {
method prefix (line 5) | static get prefix() {
method suffix (line 8) | static get suffix() {
method hasEmbeddedError (line 12) | static hasEmbeddedError(msg) {
method cleanMessage (line 20) | static cleanMessage(msg) {
method deconvertErrorToObject (line 32) | static deconvertErrorToObject(error) {
method convertErrorToString (line 51) | static convertErrorToString(error) {
method isPrematureTemplateContentError (line 59) | static isPrematureTemplateContentError(e) {
FILE: src/Errors/TemplateContentPrematureUseError.js
class TemplateContentPrematureUseError (line 3) | class TemplateContentPrematureUseError extends EleventyBaseError {}
FILE: src/Errors/TemplateContentUnrenderedTemplateError.js
class TemplateContentUnrenderedTemplateError (line 3) | class TemplateContentUnrenderedTemplateError extends EleventyBaseError {}
FILE: src/Errors/UsingCircularTemplateContentReferenceError.js
class UsingCircularTemplateContentReferenceError (line 3) | class UsingCircularTemplateContentReferenceError extends EleventyBaseErr...
FILE: src/FileSystemSearch.js
class FileSystemSearch (line 10) | class FileSystemSearch {
method constructor (line 11) | constructor() {
method getCacheKey (line 18) | getCacheKey(key, globs, options) {
method search (line 26) | search(key, globs, options = {}) {
method _modify (line 94) | _modify(path, setOperation) {
method add (line 111) | add(path) {
method delete (line 115) | delete(path) {
FILE: src/Filters/GetCollectionItem.js
function getCollectionItem (line 1) | function getCollectionItem(collection, page, modifier = 0) {
FILE: src/Filters/GetCollectionItemIndex.js
function getCollectionItemIndex (line 2) | function getCollectionItemIndex(collection, page) {
FILE: src/Filters/GetLocaleCollectionItem.js
function resolveRootPage (line 4) | function resolveRootPage(config, pageOverride, languageCode) {
function getLocaleCollectionItem (line 14) | function getLocaleCollectionItem(config, collection, pageOverride, langC...
FILE: src/GlobalDependencyMap.js
class GlobalDependencyMap (line 10) | class GlobalDependencyMap {
method isCollection (line 19) | static isCollection(entry) {
method getTagName (line 23) | static getTagName(entry) {
method getCollectionKeyForEntry (line 29) | static getCollectionKeyForEntry(entry) {
method reset (line 33) | reset() {
method setIsEsm (line 37) | setIsEsm(isEsm) {
method setTemplateConfig (line 41) | setTemplateConfig(templateConfig) {
method userConfigurationCollectionApiNames (line 50) | get userConfigurationCollectionApiNames() {
method initializeUserConfigurationApiCollections (line 57) | initializeUserConfigurationApiCollections() {
method setCollectionApiNames (line 62) | setCollectionApiNames(names = []) {
method addCollectionApiNames (line 66) | addCollectionApiNames(names = []) {
method filterOutLayouts (line 76) | filterOutLayouts(nodes = []) {
method filterOutCollections (line 85) | filterOutCollections(nodes = []) {
method removeLayoutNodes (line 89) | static removeLayoutNodes(graph, nodeList) {
method removeLayoutNodes (line 98) | removeLayoutNodes(normalizedLayouts) {
method addLayoutsToMap (line 115) | async addLayoutsToMap(layouts) {
method map (line 145) | get map() {
method map (line 154) | set map(graph) {
method normalizeNode (line 158) | normalizeNode(node) {
method normalizeLayoutsObject (line 176) | normalizeLayoutsObject(layouts) {
method getDependantsFor (line 185) | getDependantsFor(node) {
method hasNode (line 200) | hasNode(node) {
method findCollectionsRemovedFrom (line 204) | findCollectionsRemovedFrom(node, collectionNames) {
method resetNode (line 224) | resetNode(node) {
method getTemplatesThatConsumeCollections (line 241) | getTemplatesThatConsumeCollections(collectionNames) {
method isLayoutNode (line 259) | static isLayoutNode(graph, node) {
method getLayoutsUsedBy (line 266) | getLayoutsUsedBy(node) {
method getTemplatesRelevantToTemplateList (line 292) | getTemplatesRelevantToTemplateList(templatePaths) {
method getDependencies (line 320) | getDependencies(node, includeLayouts = true) {
method #addNode (line 335) | #addNode(name) {
method #addDependency (line 344) | #addDependency(from, toArray = []) {
method addDependency (line 360) | addDependency(from, toArray = []) {
method addNewNodeRelationships (line 367) | addNewNodeRelationships(from, consumes = [], publishes = []) {
method hasDependency (line 378) | hasDependency(from, to, includeLayouts) {
method isFileRelevantTo (line 391) | isFileRelevantTo(fullTemplateInputPath, comparisonFile, includeLayouts) {
method isFileUsedBy (line 414) | isFileUsedBy(parent, child, includeLayouts) {
method getTemplateOrder (line 422) | getTemplateOrder() {
method stringify (line 431) | stringify() {
method restore (line 446) | restore(persisted) {
FILE: src/LayoutCache.js
class LayoutCache (line 8) | class LayoutCache {
method constructor (line 9) | constructor() {
method clear (line 14) | clear() {
method removeAll (line 20) | removeAll() {
method size (line 27) | size() {
method add (line 31) | add(layoutTemplate) {
method has (line 59) | has(key) {
method get (line 63) | get(key) {
method remove (line 71) | remove(layoutFilePath) {
FILE: src/Plugins/HtmlBasePlugin.js
function addPathPrefixToUrl (line 7) | function addPathPrefixToUrl(url, pathPrefix, base) {
function transformUrl (line 23) | function transformUrl(url, base, opts = {}) {
function HtmlBasePlugin (line 54) | function HtmlBasePlugin(eleventyConfig, defaultOptions = {}) {
FILE: src/Plugins/HtmlRelativeCopyPlugin.js
function init (line 6) | function init(eleventyConfig, options) {
function HtmlRelativeCopyPlugin (line 49) | function HtmlRelativeCopyPlugin(eleventyConfig) {
FILE: src/Plugins/I18nPlugin.js
class LangUtils (line 14) | class LangUtils {
method getLanguageCodeFromInputPath (line 15) | static getLanguageCodeFromInputPath(filepath) {
method getLanguageCodeFromUrl (line 19) | static getLanguageCodeFromUrl(url) {
method swapLanguageCodeNoCheck (line 24) | static swapLanguageCodeNoCheck(str, langCode) {
method swapLanguageCode (line 39) | static swapLanguageCode(str, langCode) {
class Comparator (line 48) | class Comparator {
method isLangCode (line 51) | static isLangCode(code) {
method urlHasLangCode (line 62) | static urlHasLangCode(url, code) {
function normalizeInputPath (line 71) | function normalizeInputPath(inputPath, extensionMap) {
function getLocaleUrlsMap (line 92) | function getLocaleUrlsMap(urlToInputPath, extensionMap, options = {}) {
function I18nPlugin (line 157) | function I18nPlugin(eleventyConfig, opts = {}) {
FILE: src/Plugins/IdAttributePlugin.js
constant POSTHTML_PLUGIN_NAME (line 4) | const POSTHTML_PLUGIN_NAME = "11ty/eleventy/id-attribute";
function getTextNodeContent (line 6) | function getTextNodeContent(node) {
function IdAttributePlugin (line 29) | function IdAttributePlugin(eleventyConfig, options = {}) {
FILE: src/Plugins/InputPathToUrl.js
function getValidPath (line 5) | function getValidPath(contentMap, testPath) {
function normalizeInputPath (line 15) | function normalizeInputPath(targetInputPath, inputDir, sourceInputPath, ...
function parseFilePath (line 48) | function parseFilePath(filepath) {
function FilterPlugin (line 85) | function FilterPlugin(eleventyConfig) {
function TransformPlugin (line 124) | function TransformPlugin(eleventyConfig, defaultOptions = {}) {
FILE: src/Plugins/Pagination.js
class PaginationConfigError (line 12) | class PaginationConfigError extends EleventyBaseError {}
class PaginationError (line 13) | class PaginationError extends EleventyBaseError {}
class Pagination (line 15) | class Pagination {
method constructor (line 16) | constructor(tmpl, data, config) {
method inputPathForErrorMessages (line 27) | get inputPathForErrorMessages() {
method hasPagination (line 34) | static hasPagination(data) {
method hasPagination (line 38) | hasPagination() {
method circularReferenceCheck (line 47) | circularReferenceCheck(data) {
method setData (line 60) | setData(data) {
method setTemplate (line 87) | setTemplate(tmpl) {
method _getDataKey (line 91) | _getDataKey() {
method shouldResolveDataToObjectValues (line 95) | shouldResolveDataToObjectValues() {
method isFiltered (line 102) | isFiltered(value) {
method _has (line 115) | _has(target, key) {
method _get (line 121) | _get(target, key) {
method _resolveItems (line 132) | _resolveItems() {
method pagedItems (line 173) | get pagedItems() {
method getPageCount (line 188) | getPageCount() {
method getNormalizedItems (line 196) | getNormalizedItems(pageItems) {
method getOverrideDataPages (line 200) | getOverrideDataPages(items, pageNumber) {
method getOverrideDataLinks (line 214) | getOverrideDataLinks(pageNumber, templateCount, links) {
method getOverrideDataHrefs (line 233) | getOverrideDataHrefs(pageNumber, templateCount, hrefs) {
method getPageTemplates (line 256) | async getPageTemplates() {
FILE: src/Plugins/PreserveClosingTagsPlugin.js
constant POSTHTML_PLUGIN_NAME (line 1) | const POSTHTML_PLUGIN_NAME = "11ty/eleventy/preserve-closing-tags";
function PreserveClosingTagsPlugin (line 3) | function PreserveClosingTagsPlugin(eleventyConfig, options = {}) {
FILE: src/Plugins/RenderPlugin.js
class EleventyNunjucksError (line 16) | class EleventyNunjucksError extends EleventyBaseError {}
function compile (line 19) | async function compile(content, templateLang, options = {}) {
function compileFile (line 69) | async function compileFile(inputPath, options = {}, templateLang) {
function renderShortcodeFn (line 124) | async function renderShortcodeFn(fn, data) {
function RenderPlugin (line 164) | function RenderPlugin(eleventyConfig, options = {}) {
class RenderManager (line 415) | class RenderManager {
method constructor (line 421) | constructor() {
method templateConfig (line 426) | get templateConfig() {
method templateConfig (line 430) | set templateConfig(templateConfig) {
method init (line 447) | async init() {
method config (line 461) | config(callback) {
method initialGlobalData (line 468) | get initialGlobalData() {
method getData (line 477) | async getData(...data) {
method compile (line 485) | async compile(content, templateLang, options = {}) {
method render (line 497) | async render(fn, edgeData, buildTimeData) {
FILE: src/Template.js
class Template (line 34) | class Template extends TemplateContent {
method constructor (line 40) | constructor(templatePath, templateData, extensionMap, config) {
method #initFileSlug (line 72) | #initFileSlug() {
method resetCachedTemplate (line 79) | resetCachedTemplate({ templateData, extensionMap, eleventyConfig }) {
method fsManager (line 87) | get fsManager() {
method logger (line 94) | get logger() {
method logger (line 103) | set logger(logger) {
method isRenderable (line 107) | isRenderable() {
method isRenderableDisabled (line 111) | isRenderableDisabled() {
method isRenderableOptional (line 115) | isRenderableOptional() {
method setRenderableOverride (line 122) | setRenderableOverride(renderableOverride) {
method reset (line 126) | reset() {
method resetCaches (line 131) | resetCaches(types) {
method setOutputFormat (line 152) | setOutputFormat(to) {
method setIsVerbose (line 157) | setIsVerbose(isVerbose) {
method setDryRunViaIncremental (line 162) | setDryRunViaIncremental(isIncremental) {
method setDryRun (line 167) | setDryRun(isDryRun) {
method setExtraOutputSubdirectory (line 171) | setExtraOutputSubdirectory(dir) {
method getTemplateSubfolder (line 175) | getTemplateSubfolder() {
method templateUsesLayouts (line 188) | templateUsesLayouts(pageData) {
method getLayout (line 197) | getLayout(layoutKey) {
method baseFile (line 209) | get baseFile() {
method _getLink (line 213) | async _getLink(data) {
method usePermalinkRoot (line 315) | async usePermalinkRoot() {
method getOutputLocations (line 326) | async getOutputLocations(data) {
method getRawOutputPath (line 349) | async getRawOutputPath(data) {
method getOutputHref (line 356) | async getOutputHref(data) {
method getOutputPath (line 363) | async getOutputPath(data) {
method _testGetAllLayoutFrontMatterData (line 372) | async _testGetAllLayoutFrontMatterData() {
method #getData (line 382) | async #getData() {
method getData (line 433) | async getData() {
method addPage (line 442) | async addPage(data) {
method render (line 469) | async render() {
method renderLayout (line 474) | async renderLayout() {
method renderDirect (line 478) | async renderDirect(str, data, bypassMarkdown) {
method renderPageEntryWithoutLayout (line 483) | async renderPageEntryWithoutLayout(pageEntry) {
method setLinters (line 493) | setLinters(linters) {
method addLinter (line 504) | addLinter(callback) {
method runLinters (line 508) | async runLinters(str, page) {
method setTransforms (line 528) | setTransforms(transforms) {
method runTransforms (line 535) | async runTransforms(str, pageEntry) {
method #renderComputedUnit (line 541) | async #renderComputedUnit(entry, data) {
method _addComputedEntry (line 561) | _addComputedEntry(computedData, obj, parentKey, declaredDependencies) {
method addComputedData (line 592) | async addComputedData(data) {
method resolveRemainingComputedData (line 657) | async resolveRemainingComputedData(data) {
method augmentWithTemplateContentProperty (line 665) | static augmentWithTemplateContentProperty(obj) {
method runPreprocessors (line 718) | async runPreprocessors(data) {
method getTemplates (line 727) | async getTemplates(data) {
method _write (line 803) | async _write({ url, outputPath, data, rawInput }, finalContent) {
method #renderPageEntryWithLayoutsAndTransforms (line 860) | async #renderPageEntryWithLayoutsAndTransforms(pageEntry) {
method renderPageEntry (line 881) | async renderPageEntry(pageEntry) {
method retrieveDataForJsonOutput (line 891) | retrieveDataForJsonOutput(data, selectors) {
method generateMapEntry (line 905) | async generateMapEntry(mapEntry, to) {
method clone (line 958) | async clone() {
method getWriteCount (line 979) | getWriteCount() {
method getRenderCount (line 983) | getRenderCount() {
method getInputFileStat (line 987) | getInputFileStat() {
method _getDateInstance (line 996) | async _getDateInstance(key = "birthtimeMs") {
method getMappedDate (line 1020) | async getMappedDate(data) {
method getTemplateMapEntries (line 1122) | async getTemplateMapEntries(data) {
FILE: src/TemplateBehavior.js
class TemplateBehavior (line 3) | class TemplateBehavior {
method constructor (line 6) | constructor(config) {
method isRenderableDisabled (line 18) | isRenderableDisabled() {
method isRenderableOptional (line 22) | isRenderableOptional() {
method setRenderableOverride (line 27) | setRenderableOverride(renderableOverride) {
method isRenderable (line 38) | isRenderable() {
method setOutputFormat (line 42) | setOutputFormat(format) {
method isRenderForced (line 46) | isRenderForced() {
method isWriteable (line 50) | isWriteable() {
method setRenderViaDataCascade (line 55) | setRenderViaDataCascade(data) {
method setFromPermalink (line 78) | setFromPermalink(templatePermalink) {
FILE: src/TemplateCollection.js
class TemplateCollection (line 7) | class TemplateCollection extends Sortable {
method constructor (line 8) | constructor() {
method getAll (line 14) | getAll() {
method getAllSorted (line 18) | getAllSorted() {
method getSortedByDate (line 22) | getSortedByDate() {
method getGlobs (line 26) | getGlobs(globs) {
method getFilteredByGlob (line 36) | getFilteredByGlob(globs) {
method getFilteredByTag (line 58) | getFilteredByTag(tagName) {
method getFilteredByTags (line 67) | getFilteredByTags(...tags) {
FILE: src/TemplateConfig.js
class EleventyConfigError (line 32) | class EleventyConfigError extends EleventyBaseError {}
class EleventyPluginError (line 38) | class EleventyPluginError extends EleventyBaseError {}
class TemplateConfig (line 46) | class TemplateConfig {
method constructor (line 57) | constructor(customRootConfig, projectConfigPath) {
method setPreviousBuildModifiedFile (line 118) | setPreviousBuildModifiedFile(inputPath, metadata = {}) {
method getPreviousBuildModifiedFile (line 122) | getPreviousBuildModifiedFile() {
method userConfig (line 126) | get userConfig() {
method aggregateBenchmark (line 130) | get aggregateBenchmark() {
method setLogger (line 135) | setLogger(logger) {
method setDirectories (line 141) | setDirectories(directories) {
method setTemplateFormats (line 147) | setTemplateFormats(templateFormats) {
method templateFormats (line 151) | get templateFormats() {
method inputDir (line 159) | get inputDir() {
method setRunMode (line 163) | setRunMode(runMode) {
method shouldSpiderJavaScriptDependencies (line 167) | shouldSpiderJavaScriptDependencies() {
method getLocalProjectConfigFile (line 181) | getLocalProjectConfigFile() {
method getLocalProjectConfigFiles (line 189) | getLocalProjectConfigFiles() {
method getActiveConfigPath (line 197) | getActiveConfigPath() {
method setProjectUsingEsm (line 204) | setProjectUsingEsm(isEsmProject) {
method getIsProjectUsingEsm (line 209) | getIsProjectUsingEsm() {
method reset (line 216) | async reset() {
method resetOnWatch (line 235) | resetOnWatch() {
method hasInitialized (line 239) | hasInitialized() {
method init (line 246) | async init(overrides) {
method forceReloadConfig (line 262) | async forceReloadConfig() {
method getConfig (line 272) | getConfig() {
method setProjectConfigPath (line 285) | async setProjectConfigPath(path) {
method setPathPrefix (line 306) | setPathPrefix(pathPrefix) {
method getPathPrefix (line 318) | getPathPrefix() {
method initializeRootConfig (line 333) | async initializeRootConfig() {
method appendToRootConfig (line 352) | appendToRootConfig(obj) {
method processPlugins (line 361) | async processPlugins({ dir, pathPrefix }) {
method requireLocalConfigFile (line 399) | async requireLocalConfigFile() {
method mergeConfig (line 465) | async mergeConfig() {
method usesGraph (line 579) | get usesGraph() {
method uses (line 591) | get uses() {
method existsCache (line 601) | get existsCache() {
FILE: src/TemplateContent.js
class TemplateContentFrontMatterError (line 21) | class TemplateContentFrontMatterError extends EleventyBaseError {}
class TemplateContentCompileError (line 22) | class TemplateContentCompileError extends EleventyBaseError {}
class TemplateContentRenderError (line 23) | class TemplateContentRenderError extends EleventyBaseError {}
class TemplateContent (line 25) | class TemplateContent {
method constructor (line 34) | constructor(inputPath, templateConfig) {
method asyncTemplateInitialization (line 42) | async asyncTemplateInitialization() {
method resetCachedTemplate (line 59) | resetCachedTemplate({ eleventyConfig }) {
method dirs (line 63) | get dirs() {
method inputDir (line 67) | get inputDir() {
method outputDir (line 71) | get outputDir() {
method getResetTypes (line 75) | getResetTypes(types) {
method resetCaches (line 95) | resetCaches(types) {
method extensionMap (line 108) | get extensionMap() {
method extensionMap (line 115) | set extensionMap(map) {
method eleventyConfig (line 119) | set eleventyConfig(config) {
method eleventyConfig (line 129) | get eleventyConfig() {
method config (line 136) | get config() {
method bench (line 144) | get bench() {
method engine (line 148) | get engine() {
method templateRender (line 152) | get templateRender() {
method hasTemplateRender (line 160) | hasTemplateRender() {
method getTemplateRender (line 164) | async getTemplateRender() {
method frontMatter (line 178) | get frontMatter() {
method frontMatter (line 189) | set frontMatter(contentOverride) {
method getInputPath (line 193) | getInputPath() {
method getInputDir (line 197) | getInputDir() {
method isVirtualTemplate (line 201) | isVirtualTemplate() {
method getVirtualTemplateDefinition (line 206) | getVirtualTemplateDefinition() {
method getFrontMatterParsingOptions (line 212) | getFrontMatterParsingOptions() {
method #read (line 245) | async #read() {
method read (line 308) | async read() {
method cache (line 324) | static cache(path, content) {
method getCached (line 328) | static getCached(path) {
method deleteFromInputCache (line 332) | static deleteFromInputCache(path) {
method setInputContent (line 337) | setInputContent(content) {
method getInputContent (line 341) | async getInputContent() {
method _testGetFrontMatter (line 385) | async _testGetFrontMatter() {
method getPreRender (line 391) | async getPreRender() {
method #getFrontMatterData (line 397) | async #getFrontMatterData() {
method getFrontMatterData (line 427) | async getFrontMatterData() {
method getEngineNames (line 436) | getEngineNames(engineOverride) {
method getEngineOverride (line 440) | async getEngineOverride() {
method isTemplateCacheable (line 447) | isTemplateCacheable() {
method _getCompileCache (line 454) | _getCompileCache(str) {
method compile (line 474) | async compile(str, options = {}) {
method getParseForSymbolsFunction (line 547) | getParseForSymbolsFunction(str) {
method _renderFunction (line 573) | async _renderFunction(fn, ...args) {
method renderComputedData (line 585) | async renderComputedData(str, data) {
method renderPermalink (line 596) | async renderPermalink(permalink, data) {
method render (line 632) | async render(str, data, bypassMarkdown) {
method _getPaginationLogSuffix (line 639) | _getPaginationLogSuffix(data) {
method _render (line 655) | async _render(str, data, options = {}) {
method getExtensionEntries (line 711) | getExtensionEntries() {
method isFileRelevantToThisTemplate (line 715) | isFileRelevantToThisTemplate(incrementalFile, metadata = {}) {
FILE: src/TemplateFileSlug.js
class TemplateFileSlug (line 4) | class TemplateFileSlug {
method constructor (line 5) | constructor(inputPath, extensionMap, eleventyConfig) {
method getFullPathWithoutExtension (line 23) | getFullPathWithoutExtension() {
method _getRawSlug (line 27) | _getRawSlug() {
method _stripDateFromSlug (line 33) | _stripDateFromSlug(slug) {
method getSlug (line 42) | getSlug() {
FILE: src/TemplateGlob.js
class TemplateGlob (line 3) | class TemplateGlob {
method normalizePath (line 4) | static normalizePath(...paths) {
method normalize (line 13) | static normalize(path) {
method map (line 22) | static map(files) {
FILE: src/TemplateLayout.js
class CdataWrapper (line 12) | class CdataWrapper {
method constructor (line 16) | constructor(pageTemplateSyntax = "", layoutTemplateSyntax = "") {
method isEligible (line 21) | static isEligible(templateSyntax, layoutTemplateSyntax) {
method wrap (line 27) | wrap(content) {
method unwrap (line 34) | unwrap(content) {
class TemplateLayout (line 43) | class TemplateLayout extends TemplateContent {
method constructor (line 44) | constructor(key, extensionMap, eleventyConfig) {
method getKey (line 64) | getKey() {
method getFullKey (line 68) | getFullKey() {
method getCacheKeys (line 72) | getCacheKeys() {
method resolveFullKey (line 76) | static resolveFullKey(key, inputDir) {
method getTemplate (line 80) | static getTemplate(key, eleventyConfig, extensionMap) {
method getTemplateLayoutMapEntry (line 100) | async getTemplateLayoutMapEntry() {
method #getTemplateLayoutMap (line 111) | async #getTemplateLayoutMap() {
method getTemplateLayoutMap (line 153) | async getTemplateLayoutMap() {
method getLayoutChain (line 161) | async getLayoutChain() {
method #getData (line 169) | async #getData() {
method getData (line 183) | async getData() {
method #getCachedCompiledLayoutFunction (line 191) | async #getCachedCompiledLayoutFunction() {
method getCachedCompiledLayoutFunction (line 197) | async getCachedCompiledLayoutFunction() {
method getCompiledLayoutFunctions (line 205) | async getCompiledLayoutFunctions() {
method render (line 241) | async render() {
method renderPageEntry (line 248) | async renderPageEntry(pageEntry) {
method resetCaches (line 272) | resetCaches(types) {
FILE: src/TemplateLayoutPathResolver.js
class TemplateLayoutPathResolver (line 5) | class TemplateLayoutPathResolver {
method constructor (line 6) | constructor(path, extensionMap, templateConfig) {
method getVirtualTemplate (line 27) | getVirtualTemplate(layoutPath) {
method dirs (line 33) | get dirs() {
method inputDir (line 37) | get inputDir() {
method layoutsDir (line 41) | get layoutsDir() {
method getLayoutsDir (line 46) | getLayoutsDir() {
method setAliases (line 50) | setAliases() {
method config (line 55) | set config(cfg) {
method config (line 60) | get config() {
method exists (line 68) | exists(layoutPath) {
method init (line 81) | init() {
method addLayoutAlias (line 100) | addLayoutAlias(from, to) {
method getFileName (line 104) | getFileName() {
method getFullPath (line 114) | getFullPath() {
method findFileName (line 124) | findFileName() {
method getNormalizedLayoutKey (line 132) | getNormalizedLayoutKey() {
FILE: src/TemplateMap.js
constant EXTENSIONLESS_URL_ALLOWLIST (line 14) | const EXTENSIONLESS_URL_ALLOWLIST = [
constant SPECIAL_COLLECTION_NAMES (line 21) | const SPECIAL_COLLECTION_NAMES = {
class TemplateMap (line 26) | class TemplateMap {
method constructor (line 29) | constructor(eleventyConfig) {
method userConfig (line 42) | set userConfig(config) {
method userConfig (line 46) | get userConfig() {
method config (line 55) | get config() {
method add (line 62) | async add(template) {
method getMap (line 81) | getMap() {
method _addToInputPathMap (line 85) | _addToInputPathMap(mapEntry) {
method getTagTarget (line 91) | getTagTarget(str) {
method getPaginationTagTarget (line 107) | getPaginationTagTarget(entry) {
method #addEntryToGlobalDependencyGraph (line 113) | #addEntryToGlobalDependencyGraph(entry) {
method addAllToGlobalDependencyGraph (line 132) | addAllToGlobalDependencyGraph() {
method setCollectionByTagName (line 143) | async setCollectionByTagName(tagName) {
method initDependencyMap (line 164) | async initDependencyMap(fullTemplateOrder) {
method #initDependencyMapEntry (line 199) | async #initDependencyMapEntry(map) {
method getTemplateOrder (line 240) | getTemplateOrder() {
method cache (line 262) | async cache() {
method generateInputUrlContentMap (line 308) | generateInputUrlContentMap(orderedMap) {
method generateUrlMap (line 316) | generateUrlMap(orderedMap) {
method hasMapEntryForInputPath (line 330) | hasMapEntryForInputPath(inputPath) {
method getMapEntryForInputPath (line 334) | getMapEntryForInputPath(inputPath) {
method #removeTagsFromTemplateOrder (line 339) | #removeTagsFromTemplateOrder(maps) {
method runDataSchemas (line 343) | async runDataSchemas(orderedMap) {
method populateContentDataInMap (line 365) | async populateContentDataInMap(orderedMap) {
method getTaggedCollection (line 433) | getTaggedCollection(tag) {
method isUserConfigCollectionName (line 449) | isUserConfigCollectionName(name) {
method getUserConfigCollectionNames (line 454) | getUserConfigCollectionNames() {
method getUserConfigCollection (line 458) | async getUserConfigCollection(name) {
method populateCollectionsWithContent (line 470) | populateCollectionsWithContent() {
method resolveRemainingComputedData (line 496) | async resolveRemainingComputedData() {
method generateLayoutsMap (line 508) | async generateLayoutsMap() {
method #onEachPage (line 540) | #onEachPage(callback) {
method checkForDuplicatePermalinks (line 548) | checkForDuplicatePermalinks() {
method checkForMissingFileExtensions (line 594) | checkForMissingFileExtensions() {
method _testGetAllTags (line 626) | _testGetAllTags() {
method _testGetUserConfigCollectionsData (line 639) | async _testGetUserConfigCollectionsData() {
method _testGetTaggedCollectionsData (line 652) | async _testGetTaggedCollectionsData() {
method _testGetAllCollectionsData (line 665) | async _testGetAllCollectionsData() {
method _testGetCollectionsData (line 676) | async _testGetCollectionsData() {
FILE: src/TemplatePassthrough.js
class TemplatePassthroughError (line 15) | class TemplatePassthroughError extends EleventyBaseError {}
class TemplatePassthrough (line 17) | class TemplatePassthrough {
method factory (line 25) | static factory(inputPath, outputPath, opts = {}) {
method constructor (line 38) | constructor(path, templateConfig) {
method benchmarks (line 57) | get benchmarks() {
method config (line 67) | get config() {
method directories (line 71) | get directories() {
method inputDir (line 76) | get inputDir() {
method outputDir (line 80) | get outputDir() {
method setIsAlreadyNormalized (line 85) | setIsAlreadyNormalized(isNormalized) {
method setCheckSourceDirectory (line 89) | setCheckSourceDirectory(check) {
method getPath (line 94) | getPath() {
method getOutputPath (line 98) | async getOutputPath(inputFileFromGlob) {
method getOutputPathForGlobFile (line 149) | async getOutputPathForGlobFile(inputFileFromGlob) {
method setDryRun (line 156) | setDryRun(isDryRun) {
method setRunMode (line 160) | setRunMode(runMode) {
method setFileSystemSearch (line 164) | setFileSystemSearch(fileSystemSearch) {
method getFiles (line 168) | async getFiles(glob) {
method isExists (line 190) | isExists(filePath) {
method isDirectory (line 194) | isDirectory(filePath) {
method normalizeIfDirectory (line 200) | normalizeIfDirectory(input) {
method getFileMap (line 217) | async getFileMap() {
method copy (line 255) | async copy(src, dest, copyOptions) {
method write (line 322) | async write() {
FILE: src/TemplatePassthroughManager.js
class TemplatePassthroughManagerCopyError (line 12) | class TemplatePassthroughManagerCopyError extends EleventyBaseError {}
class TemplatePassthroughManager (line 14) | class TemplatePassthroughManager {
method constructor (line 20) | constructor(templateConfig) {
method reset (line 45) | reset() {
method extensionMap (line 54) | set extensionMap(extensionMap) {
method extensionMap (line 58) | get extensionMap() {
method inputDir (line 65) | get inputDir() {
method outputDir (line 69) | get outputDir() {
method setDryRun (line 73) | setDryRun(isDryRun) {
method setRunMode (line 77) | setRunMode(runMode) {
method setIncrementalFile (line 81) | setIncrementalFile(path) {
method resetIncrementalFile (line 87) | resetIncrementalFile() {
method _normalizePaths (line 91) | _normalizePaths(path, outputPath, copyOptions = {}) {
method getConfigPaths (line 99) | getConfigPaths() {
method getConfigPathGlobs (line 110) | getConfigPathGlobs() {
method getNonTemplatePaths (line 116) | getNonTemplatePaths(paths) {
method getCopyCount (line 127) | getCopyCount() {
method getCopySize (line 131) | getCopySize() {
method getMetadata (line 135) | getMetadata() {
method setFileSystemSearch (line 142) | setFileSystemSearch(fileSystemSearch) {
method getTemplatePassthroughForPath (line 146) | getTemplatePassthroughForPath(path) {
method copyPassthrough (line 156) | async copyPassthrough(pass) {
method isPassthroughCopyFile (line 229) | isPassthroughCopyFile(paths, changedFile) {
method getAllNormalizedPaths (line 257) | getAllNormalizedPaths(paths = []) {
method getAliasesFromPassthroughResults (line 300) | getAliasesFromPassthroughResults(result) {
method #waitForTemplatesRendered (line 311) | async #waitForTemplatesRendered() {
method enqueueCopy (line 320) | enqueueCopy(source, target, copyOptions) {
method copyAll (line 341) | async copyAll(templateExtensionPaths) {
FILE: src/TemplatePermalink.js
class TemplatePermalink (line 4) | class TemplatePermalink {
method constructor (line 8) | constructor(link, extraSubdir, isDynamicPermalinkEnabled = true) {
method setUrlTransforms (line 67) | setUrlTransforms(transforms) {
method urlTransforms (line 71) | get urlTransforms() {
method _addDefaultLinkFilename (line 75) | _addDefaultLinkFilename(link) {
method toOutputPath (line 79) | toOutputPath() {
method getUrlStem (line 91) | static getUrlStem(original) {
method normalizePathToUrl (line 99) | static normalizePathToUrl(original) {
method toHref (line 121) | toHref() {
method toPath (line 142) | toPath(outputDir) {
method toPathFromRoot (line 156) | toPathFromRoot() {
method _hasDuplicateFolder (line 170) | static _hasDuplicateFolder(dir, base) {
method generate (line 178) | static generate(
FILE: src/TemplatePreprocessors.js
class TemplatePreprocessors (line 1) | class TemplatePreprocessors {
method constructor (line 2) | constructor(preprocessors) {
method runAll (line 6) | async runAll(template, data) {
FILE: src/TemplateRender.js
class TemplateRenderUnknownEngineError (line 7) | class TemplateRenderUnknownEngineError extends EleventyBaseError {}
class TemplateRender (line 10) | class TemplateRender {
method constructor (line 14) | constructor(tmplPath, config) {
method #setConfig (line 31) | #setConfig(config) {
method dirs (line 40) | get dirs() {
method inputDir (line 44) | get inputDir() {
method includesDir (line 48) | get includesDir() {
method getIncludesDir (line 53) | getIncludesDir() {
method config (line 57) | get config() {
method config (line 61) | set config(config) {
method extensionMap (line 65) | set extensionMap(extensionMap) {
method extensionMap (line 69) | get extensionMap() {
method getEngineByName (line 76) | async getEngineByName(name) {
method init (line 82) | async init(engineNameOrPath) {
method engineName (line 106) | get engineName() {
method engine (line 113) | get engine() {
method parseEngineOverrides (line 120) | static parseEngineOverrides(engineName) {
method getReadableEnginesList (line 169) | getReadableEnginesList() {
method getReadableEnginesListDifferingFromFileExtension (line 173) | getReadableEnginesListDifferingFromFileExtension() {
method getPreprocessorEngineName (line 202) | getPreprocessorEngineName() {
method getEnginesList (line 214) | getEnginesList(engineOverride) {
method setEngineOverride (line 231) | async setEngineOverride(engineName, bypassMarkdown) {
method getEngineName (line 255) | getEngineName() {
method isEngine (line 259) | isEngine(engine) {
method setUseMarkdown (line 263) | setUseMarkdown(useMarkdown) {
method setMarkdownEngine (line 268) | setMarkdownEngine(markdownEngine) {
method setHtmlEngine (line 273) | setHtmlEngine(htmlEngineName) {
method _testRender (line 277) | async _testRender(str, data) {
method getCompiledTemplate (line 281) | async getCompiledTemplate(str) {
FILE: src/TemplateWriter.js
class TemplateWriterMissingConfigArgError (line 13) | class TemplateWriterMissingConfigArgError extends EleventyBaseError {}
class EleventyPassthroughCopyError (line 14) | class EleventyPassthroughCopyError extends EleventyBaseError {}
class EleventyTemplateError (line 15) | class EleventyTemplateError extends EleventyBaseError {}
class TemplateWriter (line 17) | class TemplateWriter {
method constructor (line 23) | constructor(
method dirs (line 48) | get dirs() {
method inputDir (line 52) | get inputDir() {
method outputDir (line 56) | get outputDir() {
method templateFormats (line 60) | get templateFormats() {
method templateFormats (line 64) | set templateFormats(value) {
method errorHandler (line 69) | get errorHandler() {
method logger (line 80) | get logger() {
method logger (line 90) | set logger(logger) {
method overrideConfig (line 95) | overrideConfig(config) {
method restart (line 99) | restart() {
method extensionMap (line 105) | set extensionMap(extensionMap) {
method extensionMap (line 109) | get extensionMap() {
method setPassthroughManager (line 116) | setPassthroughManager(mgr) {
method setEleventyFiles (line 120) | setEleventyFiles(eleventyFiles) {
method getPassthroughGlobs (line 125) | getPassthroughGlobs() {
method getPathsWithVirtualTemplates (line 129) | getPathsWithVirtualTemplates(paths) {
method _getAllPaths (line 167) | async _getAllPaths() {
method _createTemplate (line 178) | _createTemplate(path, to = "fs") {
method _addToTemplateMapIncrementalBuild (line 211) | async _addToTemplateMapIncrementalBuild(incrementalFileShape, paths, t...
method _addToTemplateMapFullBuild (line 328) | async _addToTemplateMapFullBuild(paths, to = "fs") {
method getFileShape (line 355) | getFileShape(paths, incrementalFile) {
method _addToTemplateMap (line 364) | async _addToTemplateMap(paths, to = "fs") {
method _createTemplateMap (line 394) | async _createTemplateMap(paths, to) {
method _generateTemplate (line 404) | async _generateTemplate(mapEntry, to) {
method writePassthroughCopy (line 414) | async writePassthroughCopy(templateExtensionPaths) {
method generateTemplates (line 425) | async generateTemplates(paths, to = "fs") {
method writeTemplates (line 469) | async writeTemplates() {
method write (line 485) | async write() {
method getJSON (line 515) | async getJSON(to = "json") {
method setVerboseOutput (line 532) | setVerboseOutput(isVerbose) {
method setDryRun (line 537) | setDryRun(isDryRun) {
method setRunInitialBuild (line 541) | setRunInitialBuild(runInitialBuild) {
method setIncrementalBuild (line 544) | setIncrementalBuild(isIncremental) {
method setIncrementalFile (line 547) | setIncrementalFile(incrementalFile) {
method resetIncrementalFile (line 551) | resetIncrementalFile() {
method getMetadata (line 556) | getMetadata() {
method caches (line 566) | get caches() {
FILE: src/UserConfig.js
class UserConfigError (line 17) | class UserConfigError extends EleventyBaseError {}
class UserConfig (line 23) | class UserConfig {
method constructor (line 34) | constructor() {
method _getUniqueId (line 64) | _getUniqueId() {
method reset (line 68) | reset() {
method versionCheck (line 218) | versionCheck(compatibleRange) {
method on (line 232) | on(eventName, callback) {
method once (line 236) | once(eventName, callback) {
method emit (line 240) | emit(eventName, ...args) {
method setEventEmitterMode (line 244) | setEventEmitterMode(mode) {
method getFilter (line 251) | getFilter(name) {
method getFilters (line 256) | getFilters(options = {}) {
method getShortcode (line 267) | getShortcode(name) {
method getShortcodes (line 271) | getShortcodes(options = {}) {
method getPairedShortcode (line 282) | getPairedShortcode(name) {
method getPairedShortcodes (line 286) | getPairedShortcodes(options = {}) {
method #add (line 299) | #add(target, originalName, callback, options) {
method #decorateCallback (line 322) | #decorateCallback(type, callback) {
method addMarkdownHighlighter (line 333) | addMarkdownHighlighter(highlightFn) {
method setMarkdownTemplateEngine (line 337) | setMarkdownTemplateEngine(engineName) {
method setHtmlTemplateEngine (line 341) | setHtmlTemplateEngine(engineName) {
method addLiquidFilter (line 349) | addLiquidFilter(name, callback) {
method addNunjucksAsyncFilter (line 356) | addNunjucksAsyncFilter(name, callback) {
method addNunjucksFilter (line 364) | addNunjucksFilter(name, callback, isAsync = false) {
method addJavaScriptFilter (line 376) | addJavaScriptFilter(name, callback) {
method addFilter (line 386) | addFilter(name, callback) {
method addAsyncFilter (line 418) | addAsyncFilter(name, callback) {
method addShortcode (line 443) | addShortcode(name, callback) {
method addAsyncShortcode (line 460) | addAsyncShortcode(name, callback) {
method addNunjucksAsyncShortcode (line 472) | addNunjucksAsyncShortcode(name, callback) {
method addNunjucksShortcode (line 479) | addNunjucksShortcode(name, callback, isAsync = false) {
method addLiquidShortcode (line 490) | addLiquidShortcode(name, callback) {
method addPairedShortcode (line 497) | addPairedShortcode(name, callback) {
method addPairedAsyncShortcode (line 515) | addPairedAsyncShortcode(name, callback) {
method addPairedNunjucksAsyncShortcode (line 526) | addPairedNunjucksAsyncShortcode(name, callback) {
method addPairedNunjucksShortcode (line 533) | addPairedNunjucksShortcode(name, callback, isAsync = false) {
method addPairedLiquidShortcode (line 544) | addPairedLiquidShortcode(name, callback) {
method addJavaScriptShortcode (line 551) | addJavaScriptShortcode(name, callback) {
method addPairedJavaScriptShortcode (line 561) | addPairedJavaScriptShortcode(name, callback) {
method addJavaScriptFunction (line 572) | addJavaScriptFunction(name, callback) {
method addLiquidTag (line 584) | addLiquidTag(name, tagFn) {
method addNunjucksTag (line 597) | addNunjucksTag(name, tagFn) {
method _enablePluginExecution (line 615) | _enablePluginExecution() {
method _disablePluginExecution (line 620) | _disablePluginExecution() {
method isPluginExecution (line 625) | isPluginExecution() {
method addPlugin (line 642) | addPlugin(plugin, options = {}) {
method resolvePlugin (line 662) | resolvePlugin(name) {
method hasPlugin (line 667) | hasPlugin(plugin) {
method addNunjucksLoader (line 678) | addNunjucksLoader(options) {
method _getPluginName (line 687) | _getPluginName(plugin) {
method _executePlugin (line 700) | _executePlugin(plugin, options) {
method getNamespacedName (line 731) | getNamespacedName(name) {
method namespace (line 735) | async namespace(pluginNamespace, callback) {
method addPassthroughCopy (line 759) | addPassthroughCopy(fileOrDir, copyOptions = {}) {
method setTemplateFormats (line 790) | setTemplateFormats(templateFormats) {
method addTemplateFormats (line 795) | addTemplateFormats(templateFormats) {
method setLibrary (line 802) | setLibrary(engineName, libraryInstance) {
method amendLibrary (line 817) | amendLibrary(engineName, callback) {
method setLiquidOptions (line 826) | setLiquidOptions(options) {
method setLiquidParameterParsing (line 830) | setLiquidParameterParsing(behavior) {
method setNunjucksEnvironmentOptions (line 839) | setNunjucksEnvironmentOptions(options) {
method setNunjucksPrecompiledTemplates (line 843) | setNunjucksPrecompiledTemplates(templates) {
method setDynamicPermalinks (line 847) | setDynamicPermalinks(enabled) {
method setUseGitIgnore (line 851) | setUseGitIgnore(enabled) {
method addWatchTarget (line 855) | addWatchTarget(additionalWatchTargets, options = {}) {
method setWatchJavaScriptDependencies (line 864) | setWatchJavaScriptDependencies(watchEnabled) {
method setServerOptions (line 868) | setServerOptions(options = {}, override = false) {
method setChokidarConfig (line 876) | setChokidarConfig(options = {}) {
method setWatchThrottleWaitTime (line 880) | setWatchThrottleWaitTime(time = 0) {
method setFrontMatterParsingOptions (line 885) | setFrontMatterParsingOptions(options = {}) {
method _setQuietModeOverride (line 890) | _setQuietModeOverride(quietMode) {
method setQuietMode (line 895) | setQuietMode(quietMode) {
method addEngine (line 908) | addEngine(fileExtension, classInstance) {
method addExtension (line 919) | addExtension(fileExtension, options = {}) {
method addDataExtension (line 956) | addDataExtension(extensionList, parser) {
method setUseTemplateCache (line 980) | setUseTemplateCache(bypass) {
method setPrecompiledCollections (line 984) | setPrecompiledCollections(collections) {
method setServerPassthroughCopyBehavior (line 990) | setServerPassthroughCopyBehavior(behavior) {
method addUrlTransform (line 995) | addUrlTransform(callback) {
method setDataFileSuffixes (line 999) | setDataFileSuffixes(suffixArray) {
method setDataFileBaseName (line 1003) | setDataFileBaseName(baseName) {
method addTemplate (line 1007) | addTemplate(virtualInputPath, content, data) {
method isVirtualTemplate (line 1026) | isVirtualTemplate(virtualInputPath) {
method #setDirectory (line 1030) | #setDirectory(key, dir) {
method setInputDirectory (line 1039) | setInputDirectory(dir) {
method setOutputDirectory (line 1043) | setOutputDirectory(dir) {
method setDataDirectory (line 1047) | setDataDirectory(dir) {
method setIncludesDirectory (line 1051) | setIncludesDirectory(dir) {
method setLayoutsDirectory (line 1055) | setLayoutsDirectory(dir) {
method setFreezeReservedData (line 1060) | setFreezeReservedData(bool) {
method addDateParsing (line 1064) | addDateParsing(callback) {
method addGlobalData (line 1073) | addGlobalData(name, data) {
method addNunjucksGlobal (line 1088) | addNunjucksGlobal(name, globalType) {
method addTransform (line 1105) | addTransform(name, callback) {
method addPreprocessor (line 1111) | addPreprocessor(name, fileExtensions, callback) {
method addLinter (line 1120) | addLinter(name, callback) {
method addLayoutAlias (line 1126) | addLayoutAlias(from, to) {
method setLayoutResolution (line 1130) | setLayoutResolution(resolution) {
method enableLayoutResolution (line 1135) | enableLayoutResolution() {
method configureErrorReporting (line 1139) | configureErrorReporting(options = {}) {
method getCollections (line 1149) | getCollections() {
method addCollection (line 1153) | addCollection(name, callback) {
method augmentFunctionContext (line 1165) | augmentFunctionContext(fn, options) {
method setConcurrency (line 1176) | setConcurrency(number) {
method getConcurrency (line 1184) | getConcurrency() {
method getMergingConfigObject (line 1188) | getMergingConfigObject() {
method DateTime (line 1277) | get DateTime() {
method _normalizeTemplateFormats (line 1283) | _normalizeTemplateFormats() {
method setBrowserSyncConfig (line 1287) | setBrowserSyncConfig() {
method configureTemplateHandling (line 1294) | configureTemplateHandling(options = {}) {
method setDataDeepMerge (line 1299) | setDataDeepMerge(deepMerge) {
method addHandlebarsHelper (line 1308) | addHandlebarsHelper() {}
method setPugOptions (line 1309) | setPugOptions() {}
method setEjsOptions (line 1310) | setEjsOptions() {}
method addHandlebarsShortcode (line 1311) | addHandlebarsShortcode() {}
method addPairedHandlebarsShortcode (line 1312) | addPairedHandlebarsShortcode() {}
method isDataDeepMergeModified (line 1316) | isDataDeepMergeModified() {}
FILE: src/Util/ArrayUtil.js
function arrayDelete (line 1) | function arrayDelete(arr, match) {
FILE: src/Util/AsyncEventEmitter.js
class AsyncEventEmitter (line 10) | class AsyncEventEmitter extends EventEmitter {
method constructor (line 14) | constructor(...args) {
method reset (line 18) | reset() {
method emit (line 34) | async emit(type, ...args) {
method emitLazy (line 61) | async emitLazy(type, ...args) {
method setHandlerMode (line 83) | setHandlerMode(mode) {
FILE: src/Util/Compatibility.js
class Compatibility (line 7) | class Compatibility {
method constructor (line 12) | constructor(compatibleRange) {
method projectPackageJson (line 16) | static get projectPackageJson() {
method normalizeIdentifier (line 24) | static normalizeIdentifier(identifier) {
method getCompatibilityValue (line 28) | static getCompatibilityValue(compatibleRange) {
method isCompatible (line 39) | isCompatible() {
method satisfies (line 43) | static satisfies(version, compatibleRange) {
method getErrorMessage (line 53) | getErrorMessage() {
FILE: src/Util/ConsoleLogger.js
class ConsoleLogger (line 10) | class ConsoleLogger {
method constructor (line 18) | constructor() {}
method isLoggingEnabled (line 20) | isLoggingEnabled() {
method isVerbose (line 27) | get isVerbose() {
method isVerbose (line 31) | set isVerbose(verbose) {
method isChalkEnabled (line 35) | get isChalkEnabled() {
method isChalkEnabled (line 39) | set isChalkEnabled(enabled) {
method overrideLogger (line 43) | overrideLogger(logger) {
method logger (line 47) | get logger() {
method log (line 52) | log(msg) {
method logWithOptions (line 65) | logWithOptions({ message, type, prefix, color, force }) {
method forceLog (line 70) | forceLog(msg) {
method info (line 75) | info(msg) {
method warn (line 80) | warn(msg) {
method error (line 85) | error(msg) {
method message (line 97) | message(
FILE: src/Util/DateParse.js
function fromISOtoDateUTC (line 6) | function fromISOtoDateUTC(dateValue, inputPath) {
FILE: src/Util/EsmResolver.js
function initialize (line 8) | async function initialize({ port }) {
function resolve (line 17) | async function resolve(specifier, context, nextResolve) {
FILE: src/Util/EventBusUtil.js
class EventBusUtil (line 6) | class EventBusUtil {
method debugCurrentListenerCounts (line 7) | static debugCurrentListenerCounts() {
FILE: src/Util/ExistsCache.js
class ExistsCache (line 5) | class ExistsCache {
method constructor (line 9) | constructor() {
method reset (line 13) | reset() {
method size (line 18) | get size() {
method has (line 22) | has(path) {
method set (line 26) | set(path, isExist) {
method exists (line 34) | exists(path) {
method isDirectory (line 48) | isDirectory(path) {
FILE: src/Util/FeatureTests.cjs
function canRequireTypeScript (line 1) | function canRequireTypeScript() {
constant TYPESCRIPT_ENABLED (line 14) | const TYPESCRIPT_ENABLED = canRequireTypeScript();
FILE: src/Util/FilePathUtil.js
class FilePathUtil (line 1) | class FilePathUtil {
method isMatchingExtension (line 2) | static isMatchingExtension(filepath, fileExtension) {
method getFileExtension (line 14) | static getFileExtension(filepath) {
FILE: src/Util/FileSize.js
function readableFileSize (line 1) | function readableFileSize(bytes) {
FILE: src/Util/FileSystemManager.js
class FileSystemManager (line 4) | class FileSystemManager {
method constructor (line 5) | constructor(templateConfig) {
method exists (line 14) | exists(pathname) {
method createDirectoryForFileSync (line 18) | createDirectoryForFileSync(filePath) {
method writeFileSync (line 27) | writeFileSync(filePath, content) {
FILE: src/Util/GetJavaScriptData.js
class JavaScriptInvalidDataFormatError (line 3) | class JavaScriptInvalidDataFormatError extends EleventyBaseError {}
FILE: src/Util/GlobMatcher.client.js
function isGlobMatch (line 1) | function isGlobMatch() {
function isDynamicPattern (line 8) | function isDynamicPattern(pattern) {
FILE: src/Util/GlobMatcher.js
function isGlobMatch (line 5) | function isGlobMatch(filepath, globs = [], options = undefined) {
function isDynamicPattern (line 24) | function isDynamicPattern(pattern) {
FILE: src/Util/GlobRemap.js
constant SEP (line 7) | const SEP = "/";
class GlobRemap (line 9) | class GlobRemap {
method constructor (line 10) | constructor(paths = []) {
method getCwd (line 15) | getCwd() {
method getRemapped (line 19) | getRemapped(paths) {
method getInput (line 23) | getInput() {
method getOutput (line 27) | getOutput(paths = []) {
method getParentDirPrefix (line 31) | static getParentDirPrefix(filePath = "") {
method getLongestParentDirPrefix (line 48) | static getLongestParentDirPrefix(filePaths) {
method getCwd (line 64) | static getCwd(filePaths) {
method remapInput (line 68) | static remapInput(entry, cwd) {
method remapOutput (line 77) | static remapOutput(entry, cwd) {
FILE: src/Util/GlobStripper.js
class GlobStripper (line 4) | class GlobStripper {
method parse (line 9) | static parse(pattern = "") {
FILE: src/Util/HtmlRelativeCopy.js
class HtmlRelativeCopy (line 8) | class HtmlRelativeCopy {
method isEnabled (line 19) | isEnabled() {
method setFailOnError (line 23) | setFailOnError(failOnError) {
method setCopyOptions (line 27) | setCopyOptions(opts) {
method setUserConfig (line 33) | setUserConfig(userConfig) {
method addPaths (line 42) | addPaths(paths = []) {
method matchingGlobs (line 48) | get matchingGlobs() {
method addMatchingGlob (line 57) | addMatchingGlob(glob) {
method isSkippableHref (line 70) | isSkippableHref(rawRef) {
method isCopyableTarget (line 82) | isCopyableTarget(target) {
method exists (line 90) | exists(filePath) {
method getAliasedPath (line 94) | getAliasedPath(ref) {
method getFilePathRelativeToProjectRoot (line 103) | getFilePathRelativeToProjectRoot(ref, contextFilePath) {
method copy (line 108) | copy(fileRef, tmplInputPath, tmplOutputPath) {
FILE: src/Util/HtmlTransformer.js
class HtmlTransformer (line 7) | class HtmlTransformer {
method constructor (line 13) | constructor() {
method aggregateBench (line 23) | get aggregateBench() {
method setUserConfig (line 30) | setUserConfig(config) {
method prioritySort (line 34) | static prioritySort(a, b) {
method _getPosthtmlInstance (line 45) | static _getPosthtmlInstance(callbacks = [], plugins = [], context = {}) {
method _add (line 72) | _add(extensions, addType, value, options = {}) {
method addPosthtmlPlugin (line 100) | addPosthtmlPlugin(extensions, plugin, options = {}) {
method remove (line 105) | remove(extensions, match) {
method addUrlTransform (line 113) | addUrlTransform(extensions, callback, options = {}) {
method setPosthtmlProcessOptions (line 117) | setPosthtmlProcessOptions(options) {
method isTransformable (line 121) | isTransformable(extension, context) {
method getCallbacks (line 127) | getCallbacks(extension, context) {
method getPlugins (line 137) | getPlugins(extension) {
method transformStandalone (line 147) | static async transformStandalone(content, callback, posthtmlProcessOpt...
method transformContent (line 158) | async transformContent(outputPath, content, context) {
FILE: src/Util/ImportJsonSync.js
function findFilePathInParentDirs (line 9) | function findFilePathInParentDirs(dir, filename) {
function getEleventyPackageJson (line 26) | function getEleventyPackageJson() {
function getModulePackageJson (line 31) | function getModulePackageJson(dir) {
function getWorkingProjectPackageJsonPath (line 43) | function getWorkingProjectPackageJsonPath() {
function getWorkingProjectPackageJson (line 48) | function getWorkingProjectPackageJson() {
FILE: src/Util/IsAsyncFunction.js
function isAsyncFunction (line 3) | function isAsyncFunction(fn) {
FILE: src/Util/JavaScriptDependencies.core.js
class JavaScriptDependencies (line 1) | class JavaScriptDependencies {
method getDependencies (line 2) | static async getDependencies() {
FILE: src/Util/JavaScriptDependencies.js
class JavaScriptDependencies (line 13) | class JavaScriptDependencies {
method getErrorMessage (line 14) | static getErrorMessage(file, type) {
method getFlavor (line 18) | static getFlavor(filePath, isProjectUsingEsm) {
method isTypeScript (line 35) | static isTypeScript(filePath) {
method getCommonJsDependencies (line 39) | static async getCommonJsDependencies(inputFiles, isProjectUsingEsm) {
method getEsmDependencies (line 68) | static async getEsmDependencies(inputFiles, isProjectUsingEsm) {
method getDependencies (line 87) | static async getDependencies(inputFiles, isProjectUsingEsm) {
method getEsmGraph (line 93) | static async getEsmGraph(inputFiles, isProjectUsingEsm) {
FILE: src/Util/NewLineAdapter.core.js
constant EOL (line 1) | const EOL = "\n";
FILE: src/Util/Objects/DeepFreeze.js
function DeepFreeze (line 5) | function DeepFreeze(obj, topLevelExceptions) {
FILE: src/Util/Objects/ObjectFilter.js
function objectFilter (line 1) | function objectFilter(obj, callback) {
FILE: src/Util/Objects/ProxyWrap.js
function wrapObject (line 8) | function wrapObject(target, fallback) {
function ProxyWrap (line 114) | function ProxyWrap(target, fallback) {
FILE: src/Util/Objects/Sortable.js
class Sortable (line 1) | class Sortable {
method constructor (line 2) | constructor() {
method length (line 16) | get length() {
method add (line 20) | add(item) {
method sort (line 25) | sort(sortFunction) {
method sortAscending (line 48) | sortAscending() {
method sortDescending (line 52) | sortDescending() {
method setSortDescending (line 56) | setSortDescending(isDescending = true) {
method setSortAscending (line 60) | setSortAscending(isAscending = true) {
method setSortNumeric (line 64) | setSortNumeric(isNumeric) {
method sortFunctionNumericAscending (line 69) | static sortFunctionNumericAscending(a, b) {
method sortFunctionNumericDescending (line 73) | static sortFunctionNumericDescending(a, b) {
method sortFunctionAscending (line 77) | static sortFunctionAscending(a, b) {
method sortFunctionDescending (line 86) | static sortFunctionDescending(a, b) {
method sortFunctionAlphabeticAscending (line 90) | static sortFunctionAlphabeticAscending(a, b) {
method sortFunctionAlphabeticDescending (line 94) | static sortFunctionAlphabeticDescending(a, b) {
method sortFunctionDate (line 98) | static sortFunctionDate(mapA, mapB) {
method sortFunctionDateInputPath (line 102) | static sortFunctionDateInputPath(mapA, mapB) {
method getSortFunction (line 111) | getSortFunction() {
method getSortFunctionAscending (line 119) | getSortFunctionAscending() {
method getSortFunctionDescending (line 127) | getSortFunctionDescending() {
FILE: src/Util/Objects/Unique.js
function Unique (line 1) | function Unique(arr) {
FILE: src/Util/PassthroughCopyBehaviorCheck.js
function isUsingEleventyDevServer (line 1) | function isUsingEleventyDevServer(config) {
FILE: src/Util/PathNormalizer.js
class PathNormalizer (line 5) | class PathNormalizer {
method getParts (line 6) | static getParts(inputPath) {
method getAllPaths (line 21) | static getAllPaths(inputPath) {
method normalizeSeperator (line 34) | static normalizeSeperator(inputPath) {
method addTrailingSlashToDirectory (line 41) | static addTrailingSlashToDirectory(dir) {
method getDirectoryFromFilePath (line 50) | static getDirectoryFromFilePath(filePath) {
method fullNormalization (line 55) | static fullNormalization(inputPath) {
FILE: src/Util/PathPrefixer.js
class PathPrefixer (line 5) | class PathPrefixer {
method normalizePathPrefix (line 6) | static normalizePathPrefix(pathPrefix) {
method joinUrlParts (line 16) | static joinUrlParts(...parts) {
FILE: src/Util/ProjectDirectories.js
class ProjectDirectories (line 9) | class ProjectDirectories {
method normalizePath (line 30) | static normalizePath(fileOrDir) {
method normalizeDirectory (line 36) | static normalizeDirectory(dir) {
method normalizeDirectoryPathRelativeToInputDirectory (line 40) | normalizeDirectoryPathRelativeToInputDirectory(filePath) {
method addTrailingSlash (line 44) | static addTrailingSlash(path) {
method freeze (line 52) | freeze() {
method setViaConfigObject (line 56) | setViaConfigObject(configDirs = {}) {
method updateInputDependencies (line 112) | updateInputDependencies() {
method #setInputRaw (line 124) | #setInputRaw(dirOrFile, inputDir = undefined) {
method setInput (line 180) | setInput(dirOrFile, inputDir = undefined) {
method setIncludes (line 186) | setIncludes(dir) {
method setLayouts (line 198) | setLayouts(dir) {
method setData (line 209) | setData(dir) {
method setOutput (line 221) | setOutput(dir) {
method input (line 239) | get input() {
method data (line 243) | get data() {
method includes (line 247) | get includes() {
method layouts (line 251) | get layouts() {
method output (line 256) | get output() {
method isTemplateFile (line 260) | isTemplateFile(filePath) {
method getInputPath (line 280) | getInputPath(filePathRelativeToInputDir) {
method getInputPathRelativeToInputDirectory (line 289) | getInputPathRelativeToInputDirectory(filePathRelativeToInputDir) {
method getLayoutPath (line 297) | getLayoutPath(filePathRelativeToLayoutDir) {
method getLayoutPathRelativeToInputDirectory (line 307) | getLayoutPathRelativeToInputDirectory(filePathRelativeToLayoutDir) {
method getProjectPath (line 315) | getProjectPath(filePath) {
method isFileInProjectFolder (line 321) | isFileInProjectFolder(filePath) {
method isFileInOutputFolder (line 325) | isFileInOutputFolder(filePath) {
method getRelativeTo (line 329) | static getRelativeTo(targetPath, cwd) {
method getUserspaceInstance (line 334) | getUserspaceInstance() {
method toString (line 362) | toString() {
FILE: src/Util/ProjectTemplateFormats.js
class ProjectTemplateFormats (line 4) | class ProjectTemplateFormats {
method union (line 10) | static union(...sets) {
method #normalize (line 25) | #normalize(formats) {
method isWildcard (line 47) | isWildcard() {
method #isUseAll (line 52) | #isUseAll(rawFormats) {
method setViaCommandLine (line 69) | setViaCommandLine(formats) {
method setViaConfig (line 81) | setViaConfig(formats) {
method addViaConfig (line 92) | addViaConfig(formats) {
method getAllTemplateFormats (line 108) | getAllTemplateFormats() {
method getTemplateFormats (line 112) | getTemplateFormats() {
FILE: src/Util/PromiseUtil.js
function withResolvers (line 1) | function withResolvers() {
FILE: src/Util/Require.js
class EleventyImportError (line 11) | class EleventyImportError extends EleventyBaseError {}
function isCommonJSTypeScript (line 15) | function isCommonJSTypeScript(filePath, type) {
function getImportErrorMessage (line 19) | function getImportErrorMessage(filePath, type) {
function loadContents (line 29) | function loadContents(path, options = {}) {
function dynamicImportAbsolutePath (line 75) | async function dynamicImportAbsolutePath(absolutePath, options = {}) {
function dynamicImport (line 198) | async function dynamicImport(localPath, type, options = {}) {
function dynamicImportRaw (line 207) | async function dynamicImportRaw(localPath, type) {
FILE: src/Util/RequireUtils.core.js
function clearRequireCache (line 9) | function clearRequireCache() {}
function requireCommonJsTypeScript (line 12) | function requireCommonJsTypeScript() {
function importJsonSync (line 16) | function importJsonSync(path) {
FILE: src/Util/RequireUtils.js
function clearRequireCache (line 8) | function clearRequireCache(absolutePath) {
function importJsonSync (line 15) | function importJsonSync(filePath) {
function requireCommonJsTypeScript (line 23) | function requireCommonJsTypeScript(filePath) {
FILE: src/Util/ReservedData.js
class EleventyReservedDataError (line 1) | class EleventyReservedDataError extends TypeError {}
class ReservedData (line 3) | class ReservedData {
method getReservedKeys (line 31) | static getReservedKeys(data, globalProperties = this.fullProperties) {
method #check (line 55) | static #check(data, sourceLocation, propertiesList) {
method check (line 67) | static check(data, sourceLocation) {
method checkSubset (line 71) | static checkSubset(data, sourceLocation) {
method getError (line 75) | static getError(options = {}) {
method isFrozenError (line 93) | static isFrozenError(e) {
method isReservedDataError (line 101) | static isReservedDataError(e) {
FILE: src/Util/ResolvePlugin.client.js
function resolvePlugin (line 1) | function resolvePlugin() {
FILE: src/Util/ResolvePlugin.js
function resolvePlugin (line 4) | function resolvePlugin(name) {
FILE: src/Util/RetrieveGlobals.client.js
function RetrieveGlobals (line 1) | async function RetrieveGlobals(code, filePath) {
FILE: src/Util/RetrieveGlobals.core.js
function RetrieveGlobals (line 3) | async function RetrieveGlobals(code, filePath) {
FILE: src/Util/RetrieveGlobals.js
function RetrieveGlobals (line 5) | async function RetrieveGlobals(code, filePath, options = {}) {
FILE: src/Util/SemverCoerce.js
function coerce (line 3) | function coerce(version) {
FILE: src/Util/SetUtil.js
function union (line 1) | function union(...sets) {
FILE: src/Util/TemplateDepGraph.js
constant COLLECTION_PREFIX (line 6) | const COLLECTION_PREFIX = "__collection:";
class TemplateDepGraph (line 8) | class TemplateDepGraph extends DependencyGraph {
method constructor (line 13) | constructor() {
method uses (line 28) | uses(from, to) {
method addTag (line 32) | addTag(tagName, type) {
method addConfigCollectionName (line 51) | addConfigCollectionName(collectionName) {
method cleanupCollectionNames (line 60) | cleanupCollectionNames(collectionNames = []) {
method addTemplate (line 80) | addTemplate(filePath, consumes = [], publishesTo = []) {
method addDependency (line 123) | addDependency(from, to) {
method unfilteredOrder (line 133) | unfilteredOrder() {
method overallOrder (line 142) | overallOrder() {
FILE: src/Util/TransformsUtil.js
class EleventyTransformError (line 7) | class EleventyTransformError extends EleventyBaseError {}
class TransformsUtil (line 9) | class TransformsUtil {
method changeTransformsToArray (line 10) | static changeTransformsToArray(transformsObj) {
method runAll (line 21) | static async runAll(content, pageData, transforms = {}, options = {}) {
FILE: src/Util/UrlUtil.js
function isValidUrl (line 1) | function isValidUrl(url) {
function getDirectoryFromUrl (line 11) | function getDirectoryFromUrl(url) {
FILE: src/Util/importer.client.js
function importer (line 1) | function importer(relPath) {
FILE: src/Util/importer.core.js
function importer (line 7) | function importer(relPath) {
FILE: src/Util/importer.js
function importer (line 1) | function importer(relPath) {
FILE: src/Util/spawn.core.js
function spawnAsync (line 1) | function spawnAsync() {
FILE: src/Util/spawn.js
function spawnAsync (line 4) | function spawnAsync(command, args, options) {
FILE: src/Watch.js
class Watch (line 10) | class Watch {
method constructor (line 18) | constructor(config) {
method getChokidarConfig (line 25) | getChokidarConfig() {
method add (line 46) | add(targets = []) {
method watchTargets (line 50) | watchTargets(targets = []) {
method addIgnores (line 65) | addIgnores(ignores) {
method #isDirectory (line 71) | #isDirectory(path) {
method start (line 75) | async start() {
method on (line 121) | on(event, callback) {
method close (line 125) | async close() {
FILE: src/WatchQueue.js
class WatchQueue (line 10) | class WatchQueue {
method constructor (line 11) | constructor() {
method isBuildRunning (line 17) | isBuildRunning() {
method setBuildRunning (line 21) | setBuildRunning() {
method setBuildFinished (line 28) | setBuildFinished() {
method getIncrementalFile (line 33) | getIncrementalFile() {
method getActiveQueue (line 44) | getActiveQueue() {
method _queueMatches (line 56) | _queueMatches(file) {
method hasAllQueueFiles (line 67) | hasAllQueueFiles(file) {
method hasQueuedFile (line 73) | hasQueuedFile(file) {
method hasQueuedFiles (line 80) | hasQueuedFiles(files) {
method pendingQueue (line 89) | get pendingQueue() {
method pendingQueue (line 96) | set pendingQueue(value) {
method addToPendingQueue (line 100) | addToPendingQueue(path) {
method getPendingQueueSize (line 107) | getPendingQueueSize() {
method getPendingQueue (line 111) | getPendingQueue() {
method getActiveQueueSize (line 115) | getActiveQueueSize() {
method popNextActiveQueue (line 120) | popNextActiveQueue() {
FILE: src/WatchTargets.js
class WatchTargets (line 8) | class WatchTargets {
method constructor (line 11) | constructor(templateConfig) {
method setProjectUsingEsm (line 21) | setProjectUsingEsm(isEsmProject) {
method isJavaScriptDependency (line 25) | isJavaScriptDependency(path) {
method reset (line 29) | reset() {
method addToDependencyGraph (line 33) | addToDependencyGraph(parent, deps) {
method uses (line 45) | uses(parent, dep) {
method getDependenciesOf (line 49) | getDependenciesOf(parent) {
method getDependantsOf (line 56) | getDependantsOf(child) {
method addRaw (line 63) | addRaw(targets, isDependency) {
method toArray (line 78) | static toArray(targets) {
method add (line 89) | add(targets) {
method normalizeToGlobs (line 93) | static normalizeToGlobs(targets) {
method addDependencies (line 100) | async addDependencies(targets, filterCallback) {
method setWriter (line 138) | setWriter(templateWriter) {
method clearImportCacheFor (line 142) | clearImportCacheFor(filePathArray) {
method getNewTargetsSinceLastReset (line 168) | getNewTargetsSinceLastReset() {
method getTargets (line 172) | getTargets() {
FILE: test/EleventyAddGlobalDataTest.js
method testing (line 55) | testing(data) {
method other (line 61) | other(data) {
FILE: test/EleventyErrorUtilTest.js
constant SAMPLE_ERROR (line 4) | const SAMPLE_ERROR = new Error("Nothing to see here");
FILE: test/EleventyExtensionMapTest.js
function getExtensionMap (line 6) | async function getExtensionMap(formats, config = new TemplateConfig()) {
FILE: test/EleventyServeTest.js
function getServerInstance (line 6) | async function getServerInstance(eleventyConfig) {
FILE: test/EleventyTest.js
function sortResultsBy (line 697) | function sortResultsBy(results, key = "content") {
function CustomExtension (line 1363) | function CustomExtension() {
method permalink (line 1583) | permalink(inputContent, inputPath) {
FILE: test/EleventyVirtualTemplatesTest.js
method data (line 243) | data() { return {} }
method render (line 256) | render() { return "Hello!" }
method data (line 270) | data() { return { key: "world" }; }
method render (line 271) | render(data) { return `Hello ${data.key}!` }
FILE: test/HtmlBasePluginTest.js
function getContentFor (line 7) | function getContentFor(results, filename) {
FILE: test/I18nPluginTest.js
function getContentFor (line 76) | function getContentFor(results, filename) {
FILE: test/InputPathToUrlPluginTest.js
constant OUTPUT_HTML_STD (line 8) | const OUTPUT_HTML_STD = `<!doctype html>
constant OUTPUT_HTML_BASE (line 29) | const OUTPUT_HTML_BASE = `<!doctype html>
function getContentFor (line 50) | function getContentFor(results, filename) {
FILE: test/Issue3788Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3797Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3808Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3816Test.js
method config (line 11) | config(eleventyConfig) {
FILE: test/Issue3818Test.js
method config (line 7) | config(eleventyConfig) {
method config (line 23) | config(eleventyConfig) {
method config (line 63) | config(eleventyConfig) {
method config (line 101) | config(eleventyConfig) {
FILE: test/Issue3823Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3825Test.js
method config (line 6) | config(eleventyConfig) {
method config (line 47) | config(eleventyConfig) {
method config (line 87) | config(eleventyConfig) {
FILE: test/Issue3831Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3833Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3850Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3860Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/Issue3870IncrementalTest.js
method config (line 21) | config(eleventyConfig) {
FILE: test/Issue3870Test.js
method config (line 21) | config(eleventyConfig) {
FILE: test/Issue3875Test.js
method config (line 6) | config(eleventyConfig) {
method config (line 20) | config(eleventyConfig) {
method config (line 38) | config(eleventyConfig) {
method config (line 53) | config(eleventyConfig) {
method config (line 68) | config(eleventyConfig) {
FILE: test/Issue434Test.js
method config (line 6) | config(eleventyConfig) {
method config (line 19) | config(eleventyConfig) {
FILE: test/Issue775Test.js
method config (line 6) | config(eleventyConfig) {
FILE: test/ProjectTemplateFormatsTest.js
function getTestInstance (line 4) | function getTestInstance() {
FILE: test/TemplateCollectionTest.js
function getNewTemplate (line 10) | function getNewTemplate(filename, input, output, eleventyConfig) {
function getNewTemplateByNumber (line 14) | function getNewTemplateByNumber(num, eleventyConfig) {
function addTemplate (line 27) | async function addTemplate(collection, template) {
function isMatch (line 263) | function isMatch(filepath, globs) {
FILE: test/TemplateDataTest.js
function testGetLocalData (line 15) | async function testGetLocalData(tmplData, templatePath) {
FILE: test/TemplateFileSlugTest.js
function getNewSlugInstance (line 8) | async function getNewSlugInstance(path, inputDir) {
FILE: test/TemplateLayoutPathResolverTest.js
function getResolverInstance (line 8) | async function getResolverInstance(path, inputDir, { eleventyConfig, map...
FILE: test/TemplateLayoutTest.js
function getTemplateLayoutInstance (line 10) | async function getTemplateLayoutInstance(key, inputDir, map) {
FILE: test/TemplateMapTest.js
function getNewTemplate (line 13) | function getNewTemplate(filename, input, output, eleventyConfig) {
function getNewTemplateByNumber (line 17) | function getNewTemplateByNumber(num, eleventyConfig) {
function testRenderWithoutLayouts (line 26) | async function testRenderWithoutLayouts(template, data) {
function addTemplate (line 34) | async function addTemplate(collection, template) {
FILE: test/TemplatePassthroughTest.js
function getTemplatePassthrough (line 8) | async function getTemplatePassthrough(path, outputDir, inputDir) {
FILE: test/TemplateRenderCustomTest.js
function getNewTemplateRender (line 15) | async function getNewTemplateRender(name, inputDir, eleventyConfig, exte...
FILE: test/TemplateRenderHTMLTest.js
function getNewTemplateRender (line 8) | async function getNewTemplateRender(name, inputDir) {
FILE: test/TemplateRenderJavaScriptTest.js
function getNewTemplateRender (line 10) | async function getNewTemplateRender(name, inputDir, extendedConfig) {
FILE: test/TemplateRenderLiquidTest.js
function getNewTemplateRender (line 11) | async function getNewTemplateRender(name, inputDir, userConfig = {}) {
function getPromise (line 26) | async function getPromise(resolveTo) {
class CustomDrop (line 926) | class CustomDrop extends Drop {
method valueOf (line 927) | valueOf() {
FILE: test/TemplateRenderMarkdownPluginTest.js
function getNewTemplateRender (line 10) | async function getNewTemplateRender(name, inputDir) {
FILE: test/TemplateRenderMarkdownTest.js
function getNewTemplateRender (line 15) | async function getNewTemplateRender(name, inputDir, eleventyConfig) {
FILE: test/TemplateRenderNunjucksTest.js
function getNewTemplateRender (line 11) | async function getNewTemplateRender(name, inputDir, eleventyConfig) {
function getPromise (line 28) | async function getPromise(resolveTo) {
function root (line 1038) | function root(env, context, frame, runtime, cb) {
FILE: test/TemplateRenderPluginTest.js
function getTestOutput (line 13) | async function getTestOutput(input, configCallback = function () {}) {
function getTestOutputForFile (line 34) | async function getTestOutputForFile(inputFile, configCallback) {
FILE: test/TemplateRenderTest.js
function getNewTemplateRender (line 9) | async function getNewTemplateRender(name, inputDir) {
FILE: test/TemplateTest-ComputedData.js
function getRenderedData (line 11) | async function getRenderedData(tmpl, pageNumber = 0) {
FILE: test/TemplateTest-Dates.js
function getRenderedData (line 4) | async function getRenderedData(tmpl, pageNumber = 0) {
FILE: test/TemplateTest.js
function getRenderedData (line 18) | async function getRenderedData(tmpl, pageNumber = 0) {
function cleanHtml (line 24) | function cleanHtml(str) {
function _testCompleteRender (line 28) | async function _testCompleteRender(tmpl) {
method templateContent (line 1304) | get templateContent() {
method templateContent (line 1374) | get templateContent() {
FILE: test/TemplateTest_Permalink.js
function writeMapEntries (line 9) | async function writeMapEntries(mapEntries) {
function getTemplateMapEntriesWithContent (line 19) | async function getTemplateMapEntriesWithContent(template, data) {
FILE: test/Util/normalizeNewLines.js
function normalizeNewLines (line 3) | function normalizeNewLines(str) {
function localizeNewLines (line 7) | function localizeNewLines(str) {
FILE: test/Util/normalizeSeparators.js
function normalizeSeparatorString (line 3) | function normalizeSeparatorString(str) {
function normalizeSeparatorArray (line 7) | function normalizeSeparatorArray(arr) {
FILE: test/_getNewTemplateForTests.js
function getNewTemplate (line 8) | async function getNewTemplate(
FILE: test/_getRenderedTemplates.js
function getRenderedTemplates (line 1) | async function getRenderedTemplates(template, data) {
function renderLayout (line 13) | async function renderLayout(tmpl, tmplData) {
function renderLayoutViaLayout (line 27) | async function renderLayoutViaLayout(layout, tmplData, templateContent) {
function renderTemplate (line 34) | async function renderTemplate(tmpl, tmplData) {
FILE: test/_issues/0/issue-0-test.js
constant CURRENT_DIR (line 6) | const CURRENT_DIR = parse(fileURLToPath(import.meta.url)).dir;
FILE: test/_issues/3932/issue-3932-test.js
constant CURRENT_DIR (line 6) | const CURRENT_DIR = parse(fileURLToPath(import.meta.url)).dir;
FILE: test/_issues/975/975-test.js
function getNewTemplate (line 7) | function getNewTemplate(filename, input, output, eleventyConfig) {
FILE: test/_testHelpers.js
function getTemplateConfigInstance (line 13) | async function getTemplateConfigInstance(configObj, dirs, configObjOverr...
function getTemplateConfigInstanceCustomCallback (line 43) | async function getTemplateConfigInstanceCustomCallback(dirObject, config...
function getTemplateWriterInstance (line 57) | function getTemplateWriterInstance(formats, templateConfig) {
function getEleventyFilesInstance (line 82) | function getEleventyFilesInstance(formats, templateConfig) {
function sortEleventyResults (line 105) | function sortEleventyResults(a, b) {
function deleteDirectory (line 114) | function deleteDirectory(dir) {
FILE: test/stubs-3807/Issue3807test.js
method config (line 36) | config(eleventyConfig) {
FILE: test/stubs-fancyjs/test.11ty.tsx
function render (line 3) | function render(data: object) {
FILE: test/stubs-render-plugin/liquid-md.11ty.cjs
class Tmpl (line 1) | class Tmpl {
method data (line 2) | data() {
method render (line 11) | async render(data) {
FILE: test/stubs-render-plugin/nunjucks.11ty.cjs
class Tmpl (line 1) | class Tmpl {
method data (line 2) | data() {
method render (line 11) | async render(data) {
FILE: test/stubs/class-async-data-fn.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | async data() {
method render (line 12) | render({ name }) {
FILE: test/stubs/class-async-filter.11ty.cjs
class Test (line 1) | class Test {
method returnsTed (line 2) | static returnsTed() {
method returnsBill (line 6) | returnsBill() {
method render (line 10) | async render({ name }) {
FILE: test/stubs/class-async.11ty.cjs
class Test (line 1) | class Test {
method render (line 2) | async render({ name }) {
FILE: test/stubs/class-buffer.11ty.cjs
class Test (line 1) | class Test {
method returnsBill (line 2) | returnsBill() {
method returnsTed (line 6) | static returnsTed() {
method render (line 10) | render({ name }) {
FILE: test/stubs/class-data-filter.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-data-fn-filter.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-data-fn-shorthand.11ty.cjs
function Test (line 1) | function Test() {}
FILE: test/stubs/class-data-fn.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-data-permalink-async-fn.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 15) | render({ name }) {
FILE: test/stubs/class-data-permalink-buffer.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-data-permalink-fn-buffer.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 9) | render({ name }) {
FILE: test/stubs/class-data-permalink-fn-filter.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 11) | render({ name }) {
FILE: test/stubs/class-data-permalink-fn.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 9) | render({ name }) {
FILE: test/stubs/class-data-permalink.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-data.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | get data() {
method render (line 8) | render({ name }) {
FILE: test/stubs/class-filter.11ty.cjs
class Test (line 1) | class Test {
method returnsTed (line 2) | static returnsTed() {
method returnsBill (line 6) | returnsBill() {
method render (line 10) | render({ name }) {
FILE: test/stubs/class-fns-has-page.11ty.cjs
class TestWithPage (line 1) | class TestWithPage {
method page (line 2) | get page() {
method render (line 6) | render(data) {
FILE: test/stubs/class-fns.11ty.cjs
class Test (line 1) | class Test {
method render (line 2) | render({ avaTest }) {
FILE: test/stubs/class-norender.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | data() {
FILE: test/stubs/class-with-dep.11ty.cjs
class Test (line 3) | class Test {
method returnsBill (line 4) | returnsBill() {
method returnsTed (line 7) | static returnsTed() {
method render (line 10) | render({ name }) {
FILE: test/stubs/class.11ty.cjs
class Test (line 1) | class Test {
method returnsBill (line 2) | returnsBill() {
method returnsTed (line 6) | static returnsTed() {
method render (line 10) | render({ name }) {
FILE: test/stubs/classfields-data.11ty.cjs
class Test (line 1) | class Test {
method render (line 6) | render({ name }) {
FILE: test/stubs/default-class-export-and-others.11ty.js
class IndexPage (line 1) | class IndexPage {
method render (line 2) | render(data) {
function world (line 8) | function world() {
FILE: test/stubs/default-function-export-and-named-data.11ty.js
function data (line 1) | function data() {
FILE: test/stubs/function-filter.11ty.cjs
function myFunction (line 1) | function myFunction({ name }) {
FILE: test/stubs/function-prototype.11ty.cjs
function myFunction (line 1) | function myFunction() {}
FILE: test/stubs/oneinstance.11ty.cjs
class Test (line 1) | class Test {
method constructor (line 2) | constructor() {
method data (line 6) | get data() {
method render (line 13) | render({ name }) {
FILE: test/stubs/test-override-js-markdown.11ty.cjs
class Test (line 1) | class Test {
method data (line 2) | data() {
method render (line 9) | render(data) {
FILE: test_node/3824-incremental/3824-incremental-test.js
function getInputContent (line 13) | function getInputContent(str = "") {
function getOutputContent (line 27) | function getOutputContent(str = "") {
method config (line 59) | config(eleventyConfig) {
FILE: test_node/3824-incremental/_includes/head.tsx
type HeadProps (line 3) | type HeadProps = {
function Head (line 7) | function Head(props: HeadProps): JSX.Element {
FILE: test_node/3824-incremental/index.11ty.tsx
type IndexProps (line 5) | type IndexProps = {
function Index (line 10) | function Index(props: IndexProps): JSX.Element {
function render (line 19) | function render(props: ViewProps): JSX.Element {
FILE: test_node/3824/3824-test.js
function getInputContent (line 13) | function getInputContent(str = "") {
function getOutputContent (line 27) | function getOutputContent(str = "") {
method config (line 59) | config(eleventyConfig) {
FILE: test_node/3824/_includes/head.tsx
type HeadProps (line 3) | type HeadProps = {
function Head (line 7) | function Head(props: HeadProps): JSX.Element {
FILE: test_node/3824/index.11ty.tsx
type IndexProps (line 5) | type IndexProps = {
function Index (line 10) | function Index(props: IndexProps): JSX.Element {
function render (line 19) | function render(props: ViewProps): JSX.Element {
Condensed preview — 997 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,724K chars).
[
{
"path": ".editorconfig",
"chars": 275,
"preview": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\ncharset"
},
{
"path": ".git-blame-ignore-revs",
"chars": 102,
"preview": "# Switch the entire codebase to tabs, for accessibility #3098\n358ec48f779fa34e14abef057cc1fa0c1a10aa45"
},
{
"path": ".github/CODEOWNERS",
"chars": 148,
"preview": "# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/ab"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 898,
"preview": "contact_links:\n - name: I have a question about Eleventy\n url: https://github.com/11ty/eleventy/discussions/\n abo"
},
{
"path": ".github/ISSUE_TEMPLATE/possible-bug.yml",
"chars": 1773,
"preview": "name: I’m having trouble with Eleventy\ndescription: Have a problem? It might be a bug! Create a report to help us improv"
},
{
"path": ".github/dependabot.yml",
"chars": 817,
"preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
},
{
"path": ".github/opencollective.yml",
"chars": 379,
"preview": "collective: 11ty\ntiers:\n - tiers: '*'\n labels: [\"oc-supporter\"]\n message: \"Hey <author>, thanks for supporting us"
},
{
"path": ".github/workflows/ci.yml",
"chars": 1192,
"preview": "name: Unit Tests\non: push\npermissions: read-all\njobs:\n server:\n name: Node.js v${{ matrix.node }} on ${{ matrix.os }"
},
{
"path": ".github/workflows/codeql.yml",
"chars": 4515,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/release.yml",
"chars": 941,
"preview": "name: Publish Release to npm\non:\n release:\n types: [published]\npermissions: read-all\njobs:\n release:\n # see http"
},
{
"path": ".github/workflows/scorecard.yml",
"chars": 3102,
"preview": "# This workflow uses actions that are not certified by GitHub. They are provided\n# by a third-party and are governed by "
},
{
"path": ".gitignore",
"chars": 408,
"preview": "# Generated files\ndist/\npackages/*/visualize/*\n\n# Ignore installed npm modules\nnode_modules/\n\n# Ignore build tool output"
},
{
"path": ".npmignore",
"chars": 75,
"preview": "docs\ndocs-src\ntest\ntest_node\ncoverage\neslint.config.js\n.*\npackages/client/\n"
},
{
"path": ".nvmrc",
"chars": 3,
"preview": "22\n"
},
{
"path": ".prettierignore",
"chars": 5,
"preview": "test\n"
},
{
"path": ".prettierrc.json",
"chars": 125,
"preview": "{\n\t\"useTabs\": true,\n\t\"singleQuote\": false,\n\t\"semi\": true,\n\t\"endOfLine\": \"lf\",\n\t\"arrowParens\": \"always\",\n\t\"printWidth\": 1"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3315,
"preview": "# Eleventy Community Code of Conduct\n\nView the [Code of Conduct](https://www.11ty.dev/docs/code-of-conduct/) on 11ty.dev"
},
{
"path": "LICENSE",
"chars": 1087,
"preview": "MIT License\n\nCopyright (c) 2017–2024 Zach Leatherman @zachleat\n\nPermission is hereby granted, free of charge, to any per"
},
{
"path": "README.md",
"chars": 2436,
"preview": "<p align=\"center\"><img src=\"https://www.11ty.dev/img/logo-github.svg\" width=\"200\" height=\"200\" alt=\"eleventy Logo\"></p>\n"
},
{
"path": "SECURITY.md",
"chars": 462,
"preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nPrivately report a security issue by navigating to https://github.com/1"
},
{
"path": "cmd.cjs",
"chars": 4290,
"preview": "#!/usr/bin/env node\n\n// This file intentionally uses older code conventions to be as friendly\n// as possible with error "
},
{
"path": "docs/coverage.md",
"chars": 12572,
"preview": "# Code Coverage for Eleventy v3.1.2\n\n| Filename | % Lines | % Statemen"
},
{
"path": "docs/coverage.njk",
"chars": 362,
"preview": "---\npermalink: coverage.md\n---\n# Code Coverage for Eleventy v{{ pkg.version }}\n\n| Filename | % Lines | % Statements | % "
},
{
"path": "docs/eleventy.coverage.js",
"chars": 498,
"preview": "import { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\""
},
{
"path": "docs/release-instructions.md",
"chars": 2902,
"preview": "# Dependency notes\n\n- (dev dep only) `@iarna/toml` has a 3.0 that we have never been on but it was released the same day"
},
{
"path": "eslint.config.js",
"chars": 1064,
"preview": "import globals from \"globals\";\nimport pluginJs from \"@eslint/js\";\nimport stylisticJs from \"@stylistic/eslint-plugin-js\";"
},
{
"path": "package.json",
"chars": 4342,
"preview": "{\n\t\"name\": \"@11ty/eleventy\",\n\t\"version\": \"4.0.0-alpha.6\",\n\t\"description\": \"A simpler static site generator.\",\n\t\"publishC"
},
{
"path": "packages/client/README.md",
"chars": 1154,
"preview": "<p align=\"center\"><img src=\"https://www.11ty.dev/img/logo-github.svg\" width=\"200\" height=\"200\" alt=\"eleventy Logo\"></p>\n"
},
{
"path": "packages/client/generate-bundle.js",
"chars": 2934,
"preview": "import fs from \"node:fs\";\nimport { default as bundleClient } from \"@11ty/package-bundler\";\n\nimport pkg from \"../../packa"
},
{
"path": "packages/client/package.json",
"chars": 1307,
"preview": "{\n \"name\": \"@11ty/client\",\n \"description\": \"Run Eleventy in your browser.\",\n \"version\": \"PRIVATE\",\n \"private\": true,"
},
{
"path": "packages/client/src/BundleCore.js",
"chars": 172,
"preview": "// see BundleEleventy.js for Core WITH bundled Eleventy core plugins\nimport \"./shims/shim-core.js\";\n\nexport { MinimalCor"
},
{
"path": "packages/client/src/BundleEleventy.js",
"chars": 1095,
"preview": "import \"./shims/shim-core.js\";\n\n// @11ty/eleventy-plugin-bundle is not exported here (differing from Node package) but *"
},
{
"path": "packages/client/src/BundleI18nPlugin.js",
"chars": 76,
"preview": "export { default as I18nPlugin } from \"../../../src/Plugins/I18nPlugin.js\";\n"
},
{
"path": "packages/client/src/BundleLiquid.js",
"chars": 68,
"preview": "export { default as Liquid } from \"../../../src/Engines/Liquid.js\";\n"
},
{
"path": "packages/client/src/BundleMarkdown.js",
"chars": 72,
"preview": "export { default as Markdown } from \"../../../src/Engines/Markdown.js\";\n"
},
{
"path": "packages/client/src/BundleNunjucks.js",
"chars": 72,
"preview": "export { default as Nunjucks } from \"../../../src/Engines/Nunjucks.js\";\n"
},
{
"path": "packages/client/src/shims/process.cjs",
"chars": 5506,
"preview": "// MIT Licensed\n// https://github.com/defunctzombie/node-process/blob/master/browser.js\n// shim for using process in bro"
},
{
"path": "packages/client/src/shims/shim-core.js",
"chars": 429,
"preview": "import * as process from \"./process.cjs\";\n\n// `path` polyfill needs this\nwindow.process = globalThis.process = process;\n"
},
{
"path": "packages/client/test/client-core.test.js",
"chars": 122,
"preview": "import { Eleventy } from \"../dist/eleventy.core.js\";\nimport sharedTests from \"./shared-tests.js\";\n\nsharedTests(Eleventy)"
},
{
"path": "packages/client/test/client-eleventy.test.js",
"chars": 117,
"preview": "import { Eleventy } from \"../dist/eleventy.js\";\nimport sharedTests from \"./shared-tests.js\";\n\nsharedTests(Eleventy);\n"
},
{
"path": "packages/client/test/shared-tests.js",
"chars": 3883,
"preview": "import { assert, test } from \"vitest\";\nimport { Markdown } from \"../dist/formats/eleventy-markdown.js\";\nimport { Liquid "
},
{
"path": "packages/client/update-package-json.js",
"chars": 765,
"preview": "// Intended to run from repository root in release.sh script\n\nimport fs from \"node:fs\";\nimport corePkg from \"../../packa"
},
{
"path": "packages/client/vitest.config.js",
"chars": 494,
"preview": "import { defineConfig } from \"vitest/config\";\nimport { playwright } from \"@vitest/browser-playwright\";\nimport os from \"n"
},
{
"path": "scripts/release-dryrun.sh",
"chars": 175,
"preview": "export NPM_PUBLISH_TAG=\"canary\"\nexport DRY_RUN=\"--dry-run\" # leave that space as-is\n\necho \"Running @11ty/eleventy and @1"
},
{
"path": "scripts/release.sh",
"chars": 734,
"preview": "if ! npm ci; then\n\techo 'Release error: npm ci command failed.'\n\texit 1\nfi\n\nif ! npx playwright install; then\n\techo 'Rel"
},
{
"path": "src/Adapters/Engines/Liquid.core.js",
"chars": 68,
"preview": "// Must load dynamically in standard core\nexport default undefined;\n"
},
{
"path": "src/Adapters/Engines/Liquid.js",
"chars": 51,
"preview": "export { default } from \"../../Engines/Liquid.js\";\n"
},
{
"path": "src/Adapters/Engines/Markdown.core.js",
"chars": 68,
"preview": "// Must load dynamically in standard core\nexport default undefined;\n"
},
{
"path": "src/Adapters/Engines/Markdown.js",
"chars": 53,
"preview": "export { default } from \"../../Engines/Markdown.js\";\n"
},
{
"path": "src/Adapters/Engines/Nunjucks.core.js",
"chars": 68,
"preview": "// Must load dynamically in standard core\nexport default undefined;\n"
},
{
"path": "src/Adapters/Engines/Nunjucks.js",
"chars": 53,
"preview": "export { default } from \"../../Engines/Nunjucks.js\";\n"
},
{
"path": "src/Adapters/Packages/chalk.client.js",
"chars": 122,
"preview": "function noop(arg) {\n\treturn arg;\n}\nexport default {\n\tbold: noop,\n\tred: noop,\n\tgray: noop,\n\tcyan: noop,\n\tyellow: noop,\n}"
},
{
"path": "src/Adapters/Packages/chalk.js",
"chars": 50,
"preview": "import chalk from \"kleur\";\n\nexport default chalk;\n"
},
{
"path": "src/Adapters/Packages/inspect.core.js",
"chars": 77,
"preview": "export function inspect(target) {\n\treturn JSON.stringify(target, null, 2);\n}\n"
},
{
"path": "src/Adapters/Packages/inspect.js",
"chars": 154,
"preview": "import { inspect as nodeInspect } from \"node:util\";\n\nexport function inspect(target) {\n\treturn nodeInspect(target, { sho"
},
{
"path": "src/Adapters/Packages/semver.client.js",
"chars": 83,
"preview": "export function satisfies(version, range) {\n\t// Always return true\n\treturn true;\n}\n"
},
{
"path": "src/Adapters/Packages/semver.js",
"chars": 119,
"preview": "// Costs ~18 KB\nimport semverSatisfies from \"semver/functions/satisfies.js\";\n\nexport { semverSatisfies as satisfies };\n"
},
{
"path": "src/Adapters/Packages/url.core.js",
"chars": 646,
"preview": "import path from \"node:path\";\n\n// TODO move this into package-bundler as a shim?\n// Thank you bare-url!\n// Apache-2.0 LI"
},
{
"path": "src/Adapters/Packages/url.js",
"chars": 42,
"preview": "export { fileURLToPath } from \"node:url\";\n"
},
{
"path": "src/Adapters/getDefaultConfig.core.js",
"chars": 170,
"preview": "import defaultConfig from \"../defaultConfig.js\";\n\n// Standard and minimal bundle import directly for bundling\nexport def"
},
{
"path": "src/Adapters/getDefaultConfig.js",
"chars": 115,
"preview": "// Standard\nexport default async function () {\n\treturn import(\"../defaultConfig.js\").then((mod) => mod.default);\n}\n"
},
{
"path": "src/Benchmark/Benchmark.js",
"chars": 922,
"preview": "export default class Benchmark {\n\tconstructor() {\n\t\t// TypeScript slop\n\t\tthis.timeSpent = 0;\n\t\tthis.timesCalled = 0;\n\t\tt"
},
{
"path": "src/Benchmark/BenchmarkGroup.js",
"chars": 3378,
"preview": "import debugUtil from \"debug\";\n\nimport ConsoleLogger from \"../Util/ConsoleLogger.js\";\nimport isAsyncFunction from \"../Ut"
},
{
"path": "src/Benchmark/BenchmarkManager.js",
"chars": 1474,
"preview": "import BenchmarkGroup from \"./BenchmarkGroup.js\";\n\n// TODO this should not be a singleton, it belongs in the config or s"
},
{
"path": "src/Core.js",
"chars": 1767,
"preview": "import { MinimalCore } from \"./CoreMinimal.js\";\nimport FileSystemSearch from \"./FileSystemSearch.js\";\nimport EleventyFil"
},
{
"path": "src/CoreMinimal.js",
"chars": 24816,
"preview": "import debugUtil from \"debug\";\nimport { isPlainObject, TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport chalk from \"."
},
{
"path": "src/Data/ComputedData.js",
"chars": 3709,
"preview": "import lodash from \"@11ty/lodash-custom\";\nimport debugUtil from \"debug\";\n\nimport ComputedDataQueue from \"./ComputedDataQ"
},
{
"path": "src/Data/ComputedDataProxy.js",
"chars": 3271,
"preview": "import lodash from \"@11ty/lodash-custom\";\nimport { isPlainObject } from \"@11ty/eleventy-utils\";\n\nconst { set: lodashSet,"
},
{
"path": "src/Data/ComputedDataQueue.js",
"chars": 1251,
"preview": "import { DepGraph as DependencyGraph } from \"dependency-graph\";\n\n/* Keeps track of the dependency graph between computed"
},
{
"path": "src/Data/ComputedDataTemplateString.js",
"chars": 1998,
"preview": "import lodash from \"@11ty/lodash-custom\";\nimport debugUtil from \"debug\";\n\nconst { set: lodashSet } = lodash;\nconst debug"
},
{
"path": "src/Data/TemplateData.js",
"chars": 21628,
"preview": "import path from \"node:path\";\nimport lodash from \"@11ty/lodash-custom\";\nimport { Merge, TemplatePath, isPlainObject } fr"
},
{
"path": "src/Data/TemplateDataInitialGlobalData.js",
"chars": 1317,
"preview": "import lodash from \"@11ty/lodash-custom\";\n\nimport ReservedData from \"../Util/ReservedData.js\";\nimport EleventyBaseError "
},
{
"path": "src/Eleventy.js",
"chars": 18236,
"preview": "import { relative } from \"node:path\";\nimport debugUtil from \"debug\";\n\nimport { TemplatePath } from \"@11ty/eleventy-utils"
},
{
"path": "src/EleventyCommonJs.cjs",
"chars": 1701,
"preview": "function canRequireModules() {\n\t// via --experimental-require-module or newer than Node 22 support when this flag is no "
},
{
"path": "src/EleventyExtensionMap.js",
"chars": 7561,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport { isTypeScriptSupported } from \"./Util/FeatureTests.cjs\";\n\n"
},
{
"path": "src/EleventyFiles.js",
"chars": 11442,
"preview": "import { existsSync, statSync, readFileSync } from \"node:fs\";\n\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimpo"
},
{
"path": "src/EleventyServe.js",
"chars": 9088,
"preview": "import debugUtil from \"debug\";\nimport { Merge, TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport { Watch } from \"./Wat"
},
{
"path": "src/Engines/Custom.js",
"chars": 9256,
"preview": "import TemplateEngine from \"./TemplateEngine.js\";\nimport getJavaScriptData from \"../Util/GetJavaScriptData.js\";\n\nexport "
},
{
"path": "src/Engines/FrontMatter/JavaScript.js",
"chars": 588,
"preview": "import { RetrieveGlobals } from \"../../Util/RetrieveGlobals.js\";\n\n// `javascript` Front Matter Type\nexport default funct"
},
{
"path": "src/Engines/Html.js",
"chars": 725,
"preview": "import TemplateEngine from \"./TemplateEngine.js\";\n\nexport default class Html extends TemplateEngine {\n\tconstructor(name,"
},
{
"path": "src/Engines/JavaScript.js",
"chars": 6803,
"preview": "import { TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\n\nimport TemplateEngine from \"./TemplateEngine.js\";\ni"
},
{
"path": "src/Engines/Liquid.js",
"chars": 9011,
"preview": "import moo from \"moo\";\nimport { Tokenizer, TokenKind, evalToken, Liquid as LiquidJs } from \"liquidjs\";\nimport { Template"
},
{
"path": "src/Engines/Markdown.js",
"chars": 2458,
"preview": "import markdownIt from \"markdown-it\";\n\nimport TemplateEngine from \"./TemplateEngine.js\";\n\nexport default class Markdown "
},
{
"path": "src/Engines/Nunjucks.js",
"chars": 14700,
"preview": "import debugUtil from \"debug\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\n\n// Direct reference to avoid use of"
},
{
"path": "src/Engines/TemplateEngine.js",
"chars": 4429,
"preview": "import debugUtil from \"debug\";\nimport EleventyBaseError from \"../Errors/EleventyBaseError.js\";\n\nclass TemplateEngineConf"
},
{
"path": "src/Engines/TemplateEngineManager.js",
"chars": 6872,
"preview": "import debugUtil from \"debug\";\nimport EleventyBaseError from \"../Errors/EleventyBaseError.js\";\n\nconst debug = debugUtil("
},
{
"path": "src/Engines/Util/ContextAugmenter.js",
"chars": 1516,
"preview": "const DATA_KEYS = [\"page\", \"eleventy\"];\n\nfunction augmentFunction(fn, options = {}) {\n\tlet t = typeof fn;\n\tif (t !== \"fu"
},
{
"path": "src/Errors/DuplicatePermalinkOutputError.js",
"chars": 234,
"preview": "import EleventyBaseError from \"./EleventyBaseError.js\";\n\nclass DuplicatePermalinkOutputError extends EleventyBaseError {"
},
{
"path": "src/Errors/EleventyBaseError.js",
"chars": 651,
"preview": "/**\n * This class serves as basis for all Eleventy-specific errors.\n * @ignore\n */\nclass EleventyBaseError extends Error"
},
{
"path": "src/Errors/EleventyErrorHandler.js",
"chars": 3210,
"preview": "import debugUtil from \"debug\";\n\nimport { inspect } from \"../Adapters/Packages/inspect.js\";\nimport ConsoleLogger from \".."
},
{
"path": "src/Errors/EleventyErrorUtil.js",
"chars": 1974,
"preview": "import TemplateContentPrematureUseError from \"./TemplateContentPrematureUseError.js\";\n\n/* Hack to workaround the variety"
},
{
"path": "src/Errors/TemplateContentPrematureUseError.js",
"chars": 175,
"preview": "import EleventyBaseError from \"./EleventyBaseError.js\";\n\nclass TemplateContentPrematureUseError extends EleventyBaseErro"
},
{
"path": "src/Errors/TemplateContentUnrenderedTemplateError.js",
"chars": 187,
"preview": "import EleventyBaseError from \"./EleventyBaseError.js\";\n\nclass TemplateContentUnrenderedTemplateError extends EleventyBa"
},
{
"path": "src/Errors/UsingCircularTemplateContentReferenceError.js",
"chars": 195,
"preview": "import EleventyBaseError from \"./EleventyBaseError.js\";\n\nclass UsingCircularTemplateContentReferenceError extends Eleven"
},
{
"path": "src/EventBus.js",
"chars": 604,
"preview": "import debugUtil from \"debug\";\n\nimport EventEmitter from \"./Util/AsyncEventEmitter.js\";\n\nconst debug = debugUtil(\"Eleven"
},
{
"path": "src/FileSystemSearch.js",
"chars": 2827,
"preview": "import { glob } from \"tinyglobby\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\n"
},
{
"path": "src/Filters/GetCollectionItem.js",
"chars": 460,
"preview": "export default function getCollectionItem(collection, page, modifier = 0) {\n\tlet j = 0;\n\tlet index;\n\tfor (let item of co"
},
{
"path": "src/Filters/GetCollectionItemIndex.js",
"chars": 354,
"preview": "// TODO locale-friendly, see GetLocaleCollectionItem.js)\nexport default function getCollectionItemIndex(collection, page"
},
{
"path": "src/Filters/GetLocaleCollectionItem.js",
"chars": 1743,
"preview": "import getCollectionItem from \"./GetCollectionItem.js\";\n\n// Work with I18n Plugin src/Plugins/I18nPlugin.js to retrieve "
},
{
"path": "src/Filters/Url.js",
"chars": 1301,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport { isValidUrl } from \"../Util/UrlUtil.js\";\n\n// Note: This fi"
},
{
"path": "src/GlobalDependencyMap.js",
"chars": 11368,
"preview": "import debugUtil from \"debug\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport JavaScriptDependencies from "
},
{
"path": "src/LayoutCache.js",
"chars": 2400,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport eventBus from \"./EventBus.js\";\n\n// Note: this is only used "
},
{
"path": "src/Plugins/HtmlBasePlugin.js",
"chars": 4732,
"preview": "import { DeepCopy } from \"@11ty/eleventy-utils\";\nimport urlFilter from \"../Filters/Url.js\";\nimport PathPrefixer from \".."
},
{
"path": "src/Plugins/HtmlRelativeCopyPlugin.js",
"chars": 1796,
"preview": "import { HtmlRelativeCopy } from \"../Util/HtmlRelativeCopy.js\";\n\n// https://github.com/11ty/eleventy/pull/3573\n\n// one H"
},
{
"path": "src/Plugins/I18nPlugin.js",
"chars": 9457,
"preview": "import { bcp47Normalize } from \"bcp-47-normalize\";\nimport iso639 from \"iso-639-1\";\nimport { DeepCopy } from \"@11ty/eleve"
},
{
"path": "src/Plugins/IdAttributePlugin.js",
"chars": 2918,
"preview": "import matchHelper from \"posthtml-match-helper\";\nimport { decodeHTML } from \"entities\";\n\nconst POSTHTML_PLUGIN_NAME = \"1"
},
{
"path": "src/Plugins/InputPathToUrl.js",
"chars": 4987,
"preview": "import path from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimport { isValidUrl } from \"../Util/U"
},
{
"path": "src/Plugins/Pagination.js",
"chars": 10227,
"preview": "import { isPlainObject } from \"@11ty/eleventy-utils\";\nimport lodash from \"@11ty/lodash-custom\";\nimport { DeepCopy } from"
},
{
"path": "src/Plugins/PreserveClosingTagsPlugin.js",
"chars": 861,
"preview": "const POSTHTML_PLUGIN_NAME = \"11ty/eleventy/preserve-closing-tags\";\n\nexport function PreserveClosingTagsPlugin(eleventyC"
},
{
"path": "src/Plugins/RenderPlugin.js",
"chars": 15624,
"preview": "import { readFileSync } from \"node:fs\";\nimport { Merge, TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\n\n// T"
},
{
"path": "src/Template.js",
"chars": 32023,
"preview": "import { parse } from \"node:path\";\nimport { statSync } from \"node:fs\";\n\nimport lodash from \"@11ty/lodash-custom\";\nimport"
},
{
"path": "src/TemplateBehavior.js",
"chars": 2071,
"preview": "import { isPlainObject } from \"@11ty/eleventy-utils\";\n\nclass TemplateBehavior {\n\t#isRenderOptional;\n\n\tconstructor(config"
},
{
"path": "src/TemplateCollection.js",
"chars": 1779,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport TemplateData from \"./Data/TemplateData.js\";\nimport Sortable"
},
{
"path": "src/TemplateConfig.js",
"chars": 16173,
"preview": "import { Merge, TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\nimport chalk "
},
{
"path": "src/TemplateContent.js",
"chars": 21345,
"preview": "import { readFileSync } from \"node:fs\";\nimport matter from \"@11ty/gray-matter\";\nimport lodash from \"@11ty/lodash-custom\""
},
{
"path": "src/TemplateFileSlug.js",
"chars": 1495,
"preview": "import path from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\n\nclass TemplateFileSlug {\n\tconstructo"
},
{
"path": "src/TemplateGlob.js",
"chars": 826,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nclass TemplateGlob {\n\tstatic normalizePath(...paths) {\n\t\tif (paths"
},
{
"path": "src/TemplateLayout.js",
"chars": 7743,
"preview": "import { Merge, TemplatePath } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\nimport TemplateLayoutPathRes"
},
{
"path": "src/TemplateLayoutPathResolver.js",
"chars": 3313,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n// import debugUtil from \"debug\";\n// const debug = debugUtil(\"Eleve"
},
{
"path": "src/TemplateMap.js",
"chars": 20154,
"preview": "import { isPlainObject, TemplatePath } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\nimport TemplateColle"
},
{
"path": "src/TemplatePassthrough.js",
"chars": 10245,
"preview": "import path from \"node:path\";\n\nimport copy from \"@11ty/recursive-copy\";\nimport { TemplatePath } from \"@11ty/eleventy-uti"
},
{
"path": "src/TemplatePassthroughManager.js",
"chars": 9705,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\nimport EleventyBaseError from \"./Er"
},
{
"path": "src/TemplatePermalink.js",
"chars": 5006,
"preview": "import path from \"node:path\";\nimport { TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\n\nclass TemplatePermali"
},
{
"path": "src/TemplatePreprocessors.js",
"chars": 1575,
"preview": "export class TemplatePreprocessors {\n\tconstructor(preprocessors) {\n\t\tthis.preprocessors = preprocessors || [];\n\t}\n\n\tasyn"
},
{
"path": "src/TemplateRender.js",
"chars": 8092,
"preview": "import debugUtil from \"debug\";\nimport EleventyBaseError from \"./Errors/EleventyBaseError.js\";\nimport TemplateEngineManag"
},
{
"path": "src/TemplateWriter.js",
"chars": 16425,
"preview": "import { TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\nimport debugUtil from \"debug\";\n\nimport Template from"
},
{
"path": "src/UserConfig.js",
"chars": 36783,
"preview": "import debugUtil from \"debug\";\n\nimport { DeepCopy, TemplatePath, isPlainObject } from \"@11ty/eleventy-utils\";\n\nimport ch"
},
{
"path": "src/Util/ArrayUtil.js",
"chars": 398,
"preview": "export function arrayDelete(arr, match) {\n\tif (!Array.isArray(arr)) {\n\t\treturn [];\n\t}\n\n\tif (!match) {\n\t\treturn arr;\n\t}\n\n"
},
{
"path": "src/Util/AsyncEventEmitter.js",
"chars": 2081,
"preview": "import { EventEmitter } from \"node:events\";\n\n/**\n * This class emits events asynchronously.\n *\n * Note that Eleventy has"
},
{
"path": "src/Util/Compatibility.js",
"chars": 1699,
"preview": "import { satisfies } from \"../Adapters/Packages/semver.js\";\nimport { getEleventyPackageJson, getWorkingProjectPackageJso"
},
{
"path": "src/Util/ConsoleLogger.js",
"chars": 2503,
"preview": "import debugUtil from \"debug\";\nimport chalk from \"../Adapters/Packages/chalk.js\";\n\nconst debug = debugUtil(\"Eleventy:Log"
},
{
"path": "src/Util/DateParse.js",
"chars": 622,
"preview": "import debugUtil from \"debug\";\nimport { IsoDate } from \"@11ty/parse-date-strings\";\n\nconst debug = debugUtil(\"Eleventy:Da"
},
{
"path": "src/Util/DirContains.js",
"chars": 319,
"preview": "import path from \"node:path\";\n\n// Returns true if subfolder is in parent (accepts absolute or relative paths for both)\ne"
},
{
"path": "src/Util/EsmResolver.js",
"chars": 1900,
"preview": "import debugUtil from \"debug\";\nimport { fileURLToPath } from \"../Adapters/Packages/url.js\";\nimport PathNormalizer from \""
},
{
"path": "src/Util/EsmResolverPortAdapter.core.js",
"chars": 83,
"preview": "// This is optional (and featured tested upstream)\nexport const port1 = undefined;\n"
},
{
"path": "src/Util/EsmResolverPortAdapter.js",
"chars": 653,
"preview": "import module from \"node:module\";\nimport { MessageChannel } from \"node:worker_threads\";\n\nconst { port1, port2 } = new Me"
},
{
"path": "src/Util/EventBusUtil.js",
"chars": 331,
"preview": "import eventBus from \"../EventBus.js\";\nimport debugUtil from \"debug\";\n\nconst debug = debugUtil(\"Eleventy:EventBus\");\n\ncl"
},
{
"path": "src/Util/ExistsCache.js",
"chars": 1208,
"preview": "import { existsSync, statSync } from \"node:fs\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\n\n// Checks both fil"
},
{
"path": "src/Util/FeatureTests.cjs",
"chars": 460,
"preview": "function canRequireTypeScript() {\n\ttry {\n\t\tlet res = require(\"./TypeScript/TypeScriptSample.cts\");\n\t\treturn typeof res ="
},
{
"path": "src/Util/FeatureTests.core.cjs",
"chars": 69,
"preview": "module.exports.isTypeScriptSupported = function() {\n\treturn false;\n}\n"
},
{
"path": "src/Util/FilePathUtil.js",
"chars": 374,
"preview": "class FilePathUtil {\n\tstatic isMatchingExtension(filepath, fileExtension) {\n\t\tif (!fileExtension) {\n\t\t\treturn false;\n\t\t}"
},
{
"path": "src/Util/FileSize.js",
"chars": 291,
"preview": "export function readableFileSize(bytes) {\n\t// Uses kilobytes and not kibibytes\n\tlet entries = [\n\t\t[1e6, \"mB\"],\n\t\t[1e3, \""
},
{
"path": "src/Util/FileSystemManager.js",
"chars": 889,
"preview": "import path from \"node:path\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\n\nclass FileSystemManager {\n\tconstructo"
},
{
"path": "src/Util/GetJavaScriptData.js",
"chars": 821,
"preview": "import EleventyBaseError from \"../Errors/EleventyBaseError.js\";\n\nclass JavaScriptInvalidDataFormatError extends Eleventy"
},
{
"path": "src/Util/Git.js",
"chars": 906,
"preview": "import { spawnAsync } from \"./spawn.js\";\nimport memoize from \"./MemoizeFunction.js\";\n\nconst getCreatedTimestamp = memoiz"
},
{
"path": "src/Util/GlobMatcher.client.js",
"chars": 337,
"preview": "export function isGlobMatch() {\n\tthrow new Error(\n\t\t\"Glob matching (e.g. getFilteredByGlob collection API method) is not"
},
{
"path": "src/Util/GlobMatcher.js",
"chars": 664,
"preview": "// picomatch costs ~50KB minified\nimport picomatch from \"picomatch\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\""
},
{
"path": "src/Util/GlobRemap.js",
"chars": 1789,
"preview": "import path from \"node:path\";\nimport ProjectDirectories from \"./ProjectDirectories.js\";\nimport PathNormalizer from \"./Pa"
},
{
"path": "src/Util/GlobStripper.js",
"chars": 831,
"preview": "// import { TemplatePath } from \"@11ty/eleventy-utils\";\nimport { isDynamicPattern } from \"./GlobMatcher.js\";\n\nexport cla"
},
{
"path": "src/Util/HtmlRelativeCopy.js",
"chars": 3333,
"preview": "import path from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimport { isValidUrl } from \"./UrlUtil"
},
{
"path": "src/Util/HtmlTransformer.js",
"chars": 4527,
"preview": "import posthtml from \"posthtml\";\nimport urls from \"@11ty/posthtml-urls\";\nimport { FilePathUtil } from \"./FilePathUtil.js"
},
{
"path": "src/Util/ImportJsonSync.js",
"chars": 1793,
"preview": "import { existsSync } from \"node:fs\";\nimport debugUtil from \"debug\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\""
},
{
"path": "src/Util/IsAsyncFunction.js",
"chars": 158,
"preview": "const ComparisonAsyncFunction = (async () => {}).constructor;\n\nexport default function isAsyncFunction(fn) {\n\treturn fn "
},
{
"path": "src/Util/JavaScriptDependencies.core.js",
"chars": 189,
"preview": "class JavaScriptDependencies {\n\tstatic async getDependencies() {\n\t\tthrow new Error(\"This feature is not supported in `@1"
},
{
"path": "src/Util/JavaScriptDependencies.js",
"chars": 3515,
"preview": "import dependencyTree from \"@11ty/dependency-tree\";\nimport { find, findGraph, mergeGraphs } from \"@11ty/dependency-tree-"
},
{
"path": "src/Util/MemoizeFunction.js",
"chars": 628,
"preview": "export default function (callback, options = {}) {\n\tlet { bench, name } = options;\n\tlet cache = new Map();\n\n\treturn (..."
},
{
"path": "src/Util/NewLineAdapter.core.js",
"chars": 25,
"preview": "export const EOL = \"\\n\";\n"
},
{
"path": "src/Util/NewLineAdapter.js",
"chars": 31,
"preview": "export { EOL } from \"node:os\";\n"
},
{
"path": "src/Util/Objects/DeepFreeze.js",
"chars": 470,
"preview": "import { isPlainObject } from \"@11ty/eleventy-utils\";\n\n// via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Re"
},
{
"path": "src/Util/Objects/ObjectFilter.js",
"chars": 215,
"preview": "export default function objectFilter(obj, callback) {\n\tlet newObject = {};\n\tfor (let [key, value] of Object.entries(obj "
},
{
"path": "src/Util/Objects/ProxyWrap.js",
"chars": 2896,
"preview": "import debugUtil from \"debug\";\nimport { isPlainObject } from \"@11ty/eleventy-utils\";\n\nconst debug = debugUtil(\"Dev:Eleve"
},
{
"path": "src/Util/Objects/SampleModule.mjs",
"chars": 19,
"preview": "export default {};\n"
},
{
"path": "src/Util/Objects/Sortable.js",
"chars": 2950,
"preview": "class Sortable {\n\tconstructor() {\n\t\tthis.isSortAscending = true;\n\t\tthis.isSortNumeric = false;\n\t\tthis.items = [];\n\t\tthis"
},
{
"path": "src/Util/Objects/Unique.js",
"chars": 74,
"preview": "export default function Unique(arr) {\n\treturn Array.from(new Set(arr));\n}\n"
},
{
"path": "src/Util/PassthroughCopyBehaviorCheck.js",
"chars": 465,
"preview": "function isUsingEleventyDevServer(config) {\n\treturn (\n\t\t!config.serverOptions.module || config.serverOptions.module === "
},
{
"path": "src/Util/PathNormalizer.js",
"chars": 1735,
"preview": "import { parse, sep } from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimport { fileURLToPath } fr"
},
{
"path": "src/Util/PathPrefixer.js",
"chars": 483,
"preview": "import path from \"node:path\";\n\nimport PathNormalizer from \"./PathNormalizer.js\";\n\nclass PathPrefixer {\n\tstatic normalize"
},
{
"path": "src/Util/Pluralize.js",
"chars": 107,
"preview": "export default function (count, singleWord, pluralWord) {\n\treturn count === 1 ? singleWord : pluralWord;\n}\n"
},
{
"path": "src/Util/ProjectDirectories.js",
"chars": 10050,
"preview": "import { existsSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleven"
},
{
"path": "src/Util/ProjectTemplateFormats.js",
"chars": 2849,
"preview": "import debugUtil from \"debug\";\nconst debug = debugUtil(\"Eleventy:Util:ProjectTemplateFormats\");\n\nclass ProjectTemplateFo"
},
{
"path": "src/Util/PromiseUtil.js",
"chars": 255,
"preview": "export function withResolvers() {\n\tif (\"withResolvers\" in Promise) {\n\t\treturn Promise.withResolvers();\n\t}\n\n\tlet resolve;"
},
{
"path": "src/Util/Require.js",
"chars": 6241,
"preview": "import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { TemplatePath } from \"@11ty/eleventy-utils"
},
{
"path": "src/Util/RequireUtils.core.js",
"chars": 870,
"preview": "import { EleventyLoadContent } from \"./Require.js\";\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference"
},
{
"path": "src/Util/RequireUtils.js",
"chars": 749,
"preview": "import { createRequire } from \"node:module\";\n\n// important to clear the require.cache in CJS projects\nconst require = cr"
},
{
"path": "src/Util/ReservedData.js",
"chars": 2712,
"preview": "class EleventyReservedDataError extends TypeError {}\n\nclass ReservedData {\n\tstatic fullProperties = [\n\t\t\"pkg\", // Object"
},
{
"path": "src/Util/ResolvePlugin.client.js",
"chars": 235,
"preview": "export function resolvePlugin() {\n\tthrow new Error(\n\t\t\"eleventyConfig.resolvePlugin() is not supported in the `@11ty/cli"
},
{
"path": "src/Util/ResolvePlugin.js",
"chars": 1090,
"preview": "import HtmlBasePlugin from \"../Plugins/HtmlBasePlugin.js\";\nimport InputPathToUrlPlugin from \"../Plugins/InputPathToUrl.j"
},
{
"path": "src/Util/RetrieveGlobals.client.js",
"chars": 491,
"preview": "export async function RetrieveGlobals(code, filePath) {\n\tlet target = `data:text/javascript;charset=utf-8,${encodeURICom"
},
{
"path": "src/Util/RetrieveGlobals.core.js",
"chars": 407,
"preview": "import { importFromString } from \"import-module-string\";\n\nexport async function RetrieveGlobals(code, filePath) {\n\tlet d"
},
{
"path": "src/Util/RetrieveGlobals.js",
"chars": 1515,
"preview": "import { RetrieveGlobals as NodeRetrieveGlobals } from \"node-retrieve-globals\";\nimport { parseCode, walkCode, importFrom"
},
{
"path": "src/Util/SemverCoerce.js",
"chars": 331,
"preview": "// This replaces use of semver/functions/coerce.js (which had more than we needed, we’re only targeting our local packag"
},
{
"path": "src/Util/SetUtil.js",
"chars": 151,
"preview": "export function union(...sets) {\n\tlet root = new Set();\n\tfor (let set of sets) {\n\t\tfor (let entry of set) {\n\t\t\troot.add("
},
{
"path": "src/Util/TemplateDepGraph.js",
"chars": 4306,
"preview": "import { DepGraph as DependencyGraph } from \"dependency-graph\";\nimport debugUtil from \"debug\";\n\nconst debug = debugUtil("
},
{
"path": "src/Util/TransformsUtil.js",
"chars": 1697,
"preview": "import EleventyBaseError from \"../Errors/EleventyBaseError.js\";\nimport { isPlainObject } from \"@11ty/eleventy-utils\";\nim"
},
{
"path": "src/Util/TypeScript/TypeScriptSample.cts",
"chars": 52,
"preview": "module.exports = function(b: boolean, s: string) {}\n"
},
{
"path": "src/Util/UrlUtil.js",
"chars": 363,
"preview": "export function isValidUrl(url) {\n\ttry {\n\t\tnew URL(url);\n\t\treturn true;\n\t} catch (e) {\n\t\t// invalid url OR local path\n\t\t"
},
{
"path": "src/Util/importer.client.js",
"chars": 303,
"preview": "export default function importer(relPath) {\n\t// TODO we could probably use a super streamlined version of import-module-"
},
{
"path": "src/Util/importer.core.js",
"chars": 1237,
"preview": "import { existsSync, readFileSync } from \"node:fs\";\nimport { importFromString } from \"import-module-string\";\n\nimport { f"
},
{
"path": "src/Util/importer.js",
"chars": 71,
"preview": "export default function importer(relPath) {\n\treturn import(relPath);\n}\n"
},
{
"path": "src/Util/spawn.core.js",
"chars": 111,
"preview": "export function spawnAsync() {\n\tthrow new Error(\"This feature is not supported in `@11ty/client` bundles.\");\n}\n"
},
{
"path": "src/Util/spawn.js",
"chars": 670,
"preview": "import { spawn } from \"node:child_process\";\nimport { withResolvers } from \"./PromiseUtil.js\";\n\nexport function spawnAsyn"
},
{
"path": "src/Watch.js",
"chars": 2927,
"preview": "import debugUtil from \"debug\";\nimport { TemplatePath } from \"@11ty/eleventy-utils\";\nimport chokidar from \"chokidar\";\n\nim"
},
{
"path": "src/WatchQueue.js",
"chars": 2569,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\n\nimport PathNormalizer from \"./Util/PathNormalizer.js\";\n\n/* Decides"
},
{
"path": "src/WatchTargets.js",
"chars": 4144,
"preview": "import { TemplatePath } from \"@11ty/eleventy-utils\";\nimport { DepGraph } from \"dependency-graph\";\nimport { mergeGraphs }"
},
{
"path": "src/defaultConfig.js",
"chars": 4343,
"preview": "import fullBundleDefaultConfig from \"./defaultConfigExtended.js\";\nimport TransformsUtil from \"./Util/TransformsUtil.js\";"
},
{
"path": "src/defaultConfigExtended.client.js",
"chars": 750,
"preview": "export default function (config) {\n\tconfig.addFilter(\"url\", () => {\n\t\tthrow new Error(\n\t\t\t\"The `url` filter is not inclu"
},
{
"path": "src/defaultConfigExtended.js",
"chars": 3953,
"preview": "import bundlePlugin from \"@11ty/eleventy-plugin-bundle\";\nimport slugify from \"@sindresorhus/slugify\";\n\nimport { HtmlTran"
},
{
"path": "test/ArrayUtilTest.js",
"chars": 1706,
"preview": "import test from \"ava\";\nimport {arrayDelete} from \"../src/Util/ArrayUtil.js\";\n\ntest(\"ArrayUtil.arrayDelete empties\", asy"
},
{
"path": "test/BenchmarkTest.js",
"chars": 1030,
"preview": "import test from \"ava\";\nimport Benchmark from \"../src/Benchmark/Benchmark.js\";\n\ntest(\"Standard Benchmark\", async (t) => "
},
{
"path": "test/BundlePluginTest.js",
"chars": 3462,
"preview": "import test from \"ava\";\nimport Eleventy from \"../src/Eleventy.js\";\n\ntest(\"addBundle\", async (t) => {\n let elev = new El"
}
]
// ... and 797 more files (download for full content)
About this extraction
This page contains the full source code of the 11ty/eleventy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 997 files (1.5 MB), approximately 444.9k tokens, and a symbol index with 1627 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.