@11ty/eleventy
Version:
A simpler static site generator.
161 lines (134 loc) • 4.65 kB
JavaScript
import { DeepCopy } from "@11ty/eleventy-utils";
import urlFilter from "../Filters/Url.js";
import PathPrefixer from "../Util/PathPrefixer.js";
import { HtmlTransformer } from "../Util/HtmlTransformer.js";
import isValidUrl from "../Util/ValidUrl.js";
function addPathPrefixToUrl(url, pathPrefix, base) {
let u;
if (base) {
u = new URL(url, base);
} else {
u = new URL(url);
}
// Add pathPrefix **after** url is transformed using base
if (pathPrefix) {
u.pathname = PathPrefixer.joinUrlParts(pathPrefix, u.pathname);
}
return u.toString();
}
// pathprefix is only used when overrideBase is a full URL
function transformUrl(url, base, opts = {}) {
let { pathPrefix, pageUrl, htmlContext } = opts;
// Warning, this will not work with HtmlTransformer, as we’ll receive "false" (string) here instead of `false` (boolean)
if (url === false) {
throw new Error(
`Invalid url transformed in the HTML \`<base>\` plugin.${url === false ? ` Did you attempt to link to a \`permalink: false\` page?` : ""} Received: ${url}`,
);
}
// full URL, return as-is
if (isValidUrl(url)) {
return url;
}
// Not a full URL, but with a full base URL
// e.g. relative urls like "subdir/", "../subdir", "./subdir"
if (isValidUrl(base)) {
// convert relative paths to absolute path first using pageUrl
if (pageUrl && !url.startsWith("/")) {
let urlObj = new URL(url, `http://example.com${pageUrl}`);
url = urlObj.pathname + (urlObj.hash || "");
}
return addPathPrefixToUrl(url, pathPrefix, base);
}
// Not a full URL, nor a full base URL (call the built-in `url` filter)
return urlFilter(url, base);
}
function eleventyHtmlBasePlugin(eleventyConfig, defaultOptions = {}) {
let opts = DeepCopy(
{
// eleventyConfig.pathPrefix is new in Eleventy 2.0.0-canary.15
// `base` can be a directory (for path prefix transformations)
// OR a full URL with origin and pathname
baseHref: eleventyConfig.pathPrefix,
extensions: "html",
},
defaultOptions,
);
// `filters` option to rename filters was removed in 3.0.0-alpha.13
// Renaming these would cause issues in other plugins (e.g. RSS)
if (opts.filters !== undefined) {
throw new Error(
"The `filters` option in the HTML Base plugin was removed to prevent future cross-plugin compatibility issues.",
);
}
if (opts.baseHref === undefined) {
throw new Error("The `baseHref` option is required in the HTML Base plugin.");
}
eleventyConfig.addFilter("addPathPrefixToFullUrl", function (url) {
return addPathPrefixToUrl(url, eleventyConfig.pathPrefix);
});
// Apply to one URL
eleventyConfig.addFilter(
"htmlBaseUrl",
/** @this {object} */
function (url, baseOverride, pageUrlOverride) {
let base = baseOverride || opts.baseHref;
// Do nothing with a default base
if (base === "/") {
return url;
}
return transformUrl(url, base, {
pathPrefix: eleventyConfig.pathPrefix,
pageUrl: pageUrlOverride || this.page?.url,
});
},
);
// Apply to a block of HTML
eleventyConfig.addAsyncFilter(
"transformWithHtmlBase",
/** @this {object} */
function (content, baseOverride, pageUrlOverride) {
let base = baseOverride || opts.baseHref;
// Do nothing with a default base
if (base === "/") {
return content;
}
return HtmlTransformer.transformStandalone(content, (url, htmlContext) => {
return transformUrl(url.trim(), base, {
pathPrefix: eleventyConfig.pathPrefix,
pageUrl: pageUrlOverride || this.page?.url,
htmlContext,
});
});
},
);
// Apply to all HTML output in your project
eleventyConfig.htmlTransformer.addUrlTransform(
opts.extensions,
/** @this {object} */
function (urlInMarkup, htmlContext) {
// baseHref override is via renderTransforms filter for adding the absolute URL (e.g. https://example.com/pathPrefix/) for RSS/Atom/JSON feeds
return transformUrl(urlInMarkup.trim(), this.baseHref || opts.baseHref, {
pathPrefix: eleventyConfig.pathPrefix,
pageUrl: this.url,
htmlContext,
});
},
{
priority: -2, // priority is descending, so this runs last (especially after AutoCopy and InputPathToUrl transform)
enabled: function (context) {
// Enabled when pathPrefix is non-default or via renderTransforms
return Boolean(context.baseHref) || opts.baseHref !== "/";
},
},
);
}
Object.defineProperty(eleventyHtmlBasePlugin, "eleventyPackage", {
value: "@11ty/eleventy/html-base-plugin",
});
Object.defineProperty(eleventyHtmlBasePlugin, "eleventyPluginOptions", {
value: {
unique: true,
},
});
export default eleventyHtmlBasePlugin;
export { transformUrl as applyBaseToUrl };