UNPKG

create-amp-page

Version:

Full fledged static side generator composed out of extendable gulp tasks, optimized for - but not limited to - AMP.

261 lines (235 loc) 10.1 kB
import { extendFilter, extendFunction, extendTest, extendTag } from 'twig' import { defaults } from 'email-comb' import { Options as HtmlMinifierOptions } from 'html-minifier' import { WatchOptions } from 'gulp' import { SassOptions, SassOutputStyle } from './cssTask/index.js' export type FmMapFile = { // the `tpl` file path tpl: string // if the content is created by the template pagesByTpl?: boolean base?: string cwd: string // the `front-matter` file path pathFm?: string // the `.json` file path pathData?: string pageId?: string } export type fmMapFn = ( // the `frontmatter` data fm: { attributes: Object body: string bodyBegin: number frontmatter: string }, // information for the current rendered file fmFile: FmMapFile, // the data object so far, e.g. global data and `json` file, // ONLY read this variable, the full `data` object is generated after `fmMap` data: Object | undefined, ) => Object export type fmMap = fmMapFn | ((...attr: Parameters<fmMapFn>) => ReturnType<fmMapFn>) export type customMerge = (data1: Object, data2: Object) => Object export interface CopyInfo { // array of paths / glob patterns that will be copied src: string[] // how many pf the leading path segments should be removed prefix: number } export interface TwigFunction { // name of function name: string // the actual implementation func: Function } export interface AmpCreatorOptionsPaths { // folder of .scss/.sass files styles: string // the pattern for which files need to be build inside the `styles` folder, defaults to `'**/*.{scss,sass}'` style?: string // injects this stylesheet into `<style amp-custom/>`, optional // relative name to style dist folder stylesInject?: string // root folder of .twig templates html: string // folders / glob that should be copied into dist copy?: CopyInfo | CopyInfo[] // absolute, but must begin with root `dist` folder, where everything is saved dist: string // relative to `dist`, where CSS files are saved distStyles: string } export interface AmpCreatorCollection { // path to content directory with `*` placeholder for file, is passed to `gulp.src`, supports any file [`front-matter`](https://www.npmjs.com/package/front-matter) supports // OR a function for `pages-by-tpl`: // receives the absolute path to the template file, must return path to front-matter file, for "file does not exist" without an error return `undefined` fm: string | (((file: string) => string | undefined) | undefined) // optional, experimental, only for `pages-by-tpl`, // async frontmatter loader, if `fm` is defined returns a `string` it is executed with that `string`, // if `fmLoad` is not defined, the standard read from json-file is executed fmLoad?: (fmPath: string) => Promise<{ [k: string]: any } | undefined> // path to the single template that will be used tpl: string // relative base to dist base: string // receives the absolute path to the `frontmatter` file, optional // must return path to JSON file to use as data for this template // for "file does not exist" without an error return `undefined` json?: (file: string) => string | undefined jsonFailOnMissing?: boolean // the loader is executed when `json` result is a `string`, receives the result of `json` jsonLoader?: (file: string) => Promise<any | undefined> // overwrite global `fmMap` for this collection fmMap?: fmMap // overwrite global `customMerge` for this collection customMerge?: customMerge // used extension, needed for file handling, defaults to `.md` ext?: string // used output extension, needed for file saving, defaults to `.html` extOut?: string // can be used for e.g. multi page routing pageId?: string } export interface AmpCreatorDataDefault { cssInject?: boolean ampEnabled: boolean injectNetlifyIdentity?: boolean serviceWorker?: { load?: boolean // activated logging on success and error loadDebug?: boolean // activates logging only on error: loadDebugError?: boolean } } export interface AmpCreatorOptions<D extends {} = AmpCreatorDataDefault> { // yeah, the port, used by the main browserSync instances, for multi pages use additionally `pages.%.port` port: number // if browserSync should open the server, if it is a `string`, will be used as start page open?: boolean | string // root folder for the dist/build folders, // also the root of static server dist: string // for SPA / PWA historyFallback?: string // root folder of media files that should be processed srcMedia: string // relative to `dist`, where media files are saved distMedia: string pages?: { [page: string]: { paths: AmpCreatorOptionsPaths } } // define content and template collections // - generate pages by *frontmatter*, uses one template for multiple data files // - `fm` as string with glob like `src/data/blog/*.md` // - `tpl` as string like `src/html/blog.twig` // - generate pages by *template*, uses one template for one data file // - `fm` as function(tplFilePath): string; which must return the non-glob path to the data file // - `tpl` as string with glob like `src/html/pages/*.twig` collections?: AmpCreatorCollection[] // which extensions should be removed for prettier URLs, like `/contact` instead of `/contact.html` prettyUrlExtensions?: string[] // middlewares passed to serve-static serveStaticMiddleware?: Function[] // data passed globally to the twig templates, optional data?: D & { [key: string]: any } // receives the front matter and absolute path, for mapping to template values; fmMap?: fmMap // merge function to produce data from multiple sources for twig, optional; // used for merging the three twig data sources: global (`twig.data`), `twig.json` and `twig.fm`; // like let data = customMerge(globalTwigData, jsonData); data = customMerge(data, fmData); customMerge?: customMerge // settings used for `gulp-twig` and related plugins twig?: { // extends Twig with new tags types, the `Twig` parameter is the internal Twig.js object; // https://github.com/twigjs/twig.js/wiki/Extending-twig.js-With-Custom-Tags extend?: ( Twig: { exports: { extendFilter: typeof extendFilter extendFunction: typeof extendFunction extendTest: typeof extendTest extendTag: typeof extendTag } } ) => void // add custom functions to Twig functions?: TwigFunction[] // add custom filters to Twig filters?: TwigFunction[] // a function that is reloaded every runtime and supplied additional twig logics, // for e.g. changing `functions` and `filters` without restarting the whole gulp process logicLoader?: () => { functions?: TwigFunction[] filters?: TwigFunction[] } | Promise<{ functions?: TwigFunction[] filters?: TwigFunction[] }> // output file extension including the '.' like path.extname(filename). Use true to keep source extname and a "falsy" value to drop the file extension outputExtname?: string | boolean // enables debug info logging debug?: boolean // enables tracing info logging trace?: boolean // enables the twig build cache cache?: boolean } // configuring the watched folders for the main tasks watchFolders?: { sass?: string[] twig?: string[] media?: string[] } watchOptions?: WatchOptions // enable the ampOptimizer, since 1.0.0-alpha.12 pass down an instance! ampOptimizer?: any // custom inject tag, for AMP / default: 'style amp-custom>' cssInjectTag?: string // if an `Error` should be thrown when exceeding `cssSizeLimit` cssFailOnSize?: boolean // maximum bytes for CSS file, after minimizing, before clean-unused, // defaults to `75000` bytes (AMP limit) cssSizeLimit?: number // configuration used for the sass > css > optimized css task sassConfig?: { outputStyle?: SassOutputStyle options?: SassOptions // when true activates `postcss`:`postcssImport` postImport?: boolean // when true activates `postcss`:`autoprefixer` postPrefix?: boolean // when true activates `postcss`:`cssnano` postNano?: boolean } // remove unused inline CSS cleanInlineCSS?: boolean // css selectors which must not be removed, `.classes`, `#ids`, `.simple-whitelist-*`, `h1`, `p` cleanInlineCSSWhitelist?: string[] // options for `email-comb` - run when `cleanInlineCSS` is `true`, // when `cleanInlineCSSOptions` specified the `cleanInlineCSSWhitelist` options does nothing cleanInlineCSSOptions?: Partial<typeof defaults> // minify HTML, when not using `ampOptimizer` minifyHtml?: boolean minifyHtmlOptions?: HtmlMinifierOptions // additional folders to delete cleanFolders?: string[] // overwrite config for the respective imagemin module // todo: add typings media?: { gif?: Object | { interlaced: boolean } jpg?: Object | { progressive: boolean } png?: Object | { optimizationLevel: number } svg?: Object | { plugins: Object[] } [k: string]: any } // add further imagemin plugins, a function which receives the `imagemin` instance and returns an array of plugins imageminPlugins?: (imagemin: any, media: AmpCreatorOptions['media']) => Function[] } export function getOptions(options: AmpCreatorOptions): AmpCreatorOptions