Skip to content

Commit 76dff05

Browse files
committed
mv AmpOptimizer to optional-peer-dep; add cleanHtmlCss options overwrites; configurable cssSizeLimit;
1 parent 1df1c2a commit 76dff05

File tree

10 files changed

+1116
-1107
lines changed

10 files changed

+1116
-1107
lines changed

Gulpfile.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path'
22
import gulp from 'gulp'
3-
import {ampCreator} from './src/index.js'
4-
import {getPageInfo} from './src/pageTools.js'
3+
import {getPageInfo, ampCreator} from './src/index.js'
4+
import AmpOptimizer from '@ampproject/toolbox-optimizer'
55

66
const port = 4488
77

@@ -47,7 +47,7 @@ const tasks = ampCreator({
4747
base: 'blog',
4848
pageId: 'example',
4949
}],
50-
ampOptimize: !isDev,
50+
ampOptimizer: !isDev ? AmpOptimizer.create({}) : undefined,
5151
// minifyHtml: false,
5252
cleanInlineCSS: !isDev,
5353
// for css injection of non-AMP pages:

package-lock.json

Lines changed: 997 additions & 1012 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-amp-page",
3-
"version": "1.0.0-alpha.11",
3+
"version": "1.0.0-beta.0",
44
"license": "MIT",
55
"homepage": "https://github.com/bemit/create-amp-page",
66
"author": "Michael Becker <https://mlbr.xyz>",
@@ -37,11 +37,20 @@
3737
"clean": "gulp clean"
3838
},
3939
"devDependencies": {
40-
"@formanta/sass": "^0.20.2"
40+
"@formanta/sass": "^0.20.2",
41+
"@ampproject/toolbox-optimizer": "^2.7.4"
42+
},
43+
"peerDependencies": {
44+
"@ampproject/toolbox-optimizer": "^2.7.4"
45+
},
46+
"peerDependenciesMeta": {
47+
"@ampproject/toolbox-optimizer": {
48+
"optional": true
49+
}
4150
},
4251
"dependencies": {
43-
"@ampproject/toolbox-optimizer": "^2.7.4",
4452
"@types/gulp": "^4.0.8",
53+
"@types/html-minifier": "^4.0.2",
4554
"@types/through2": "^2.0.36",
4655
"@types/twig": "^1.12.5",
4756
"autoprefixer": "^10.3.4",

src/AmpCreatorOptions.d.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { extendFilter, extendFunction, extendTest, extendTag } from 'twig'
2+
import { defaults } from 'email-comb'
3+
import { Options as HtmlMinifierOptions } from 'html-minifier'
24

35
export type FmMapFiles = {
46
// the `tpl` file path
@@ -75,8 +77,6 @@ export interface AmpCreatorOptions {
7577

7678
pages?: {
7779
[page: string]: {
78-
// starts a new proxy on this port
79-
//port?: number
8080
paths: AmpCreatorOptionsPaths
8181
}
8282
}
@@ -175,39 +175,28 @@ export interface AmpCreatorOptions {
175175
media?: string[]
176176
}
177177

178-
// auto use default configs with `true`;
179-
// or specify custom options, see all:
180-
// https://github.com/ampproject/amp-toolbox/tree/main/packages/optimizer#options
181-
ampOptimize?: boolean | {
182-
autoAddMandatoryTags?: boolean
183-
autoExtensionImport?: boolean
184-
extensionVersions?: Object
185-
format?: string | 'AMP' | 'AMP4EMAIL' | 'AMP4ADS'
186-
imageBasePath?: string | (
187-
/**
188-
* @param imgSrc the path used in `src`
189-
* @param params todo: correctly type this
190-
*/
191-
(imgSrc: string, params: any) => string)
192-
imageOptimizer?: (src: string, width: string | number) => string
193-
lts?: boolean
194-
markdown?: boolean
195-
minify?: boolean
196-
preloadHeroImage?: boolean
197-
verbose?: boolean
198-
}
178+
// enable the ampOptimizer, since 1.0.0-alpha.12 pass down an instance!
179+
ampOptimizer?: any
199180

200181
// custom inject tag, for AMP / default: 'style amp-custom>'
201182
cssInjectTag?: string
183+
// if an `Error` should be thrown when exceeding `cssSizeLimit`
202184
cssFailOnSize?: boolean
185+
// maximum bytes for CSS file, after minimizing, before clean-unused,
186+
// defaults to `75000` bytes (AMP limit)
187+
cssSizeLimit?: number
203188

204189
// remove unused inline CSS
205190
cleanInlineCSS?: boolean
206191
// css selectors which must not be removed, `.classes`, `#ids`, `.simple-whitelist-*`, `h1`, `p`
207192
cleanInlineCSSWhitelist?: string[]
193+
// options for `email-comb` - run when `cleanInlineCSS` is `true`,
194+
// when `cleanInlineCSSOptions` specified the `cleanInlineCSSWhitelist` options does nothing
195+
cleanInlineCSSOptions?: Partial<typeof defaults>
208196

209-
// minify HTML, when not using `ampOptimize`
197+
// minify HTML, when not using `ampOptimizer`
210198
minifyHtml?: boolean
199+
minifyHtmlOptions?: HtmlMinifierOptions
211200

212201
// additional folders to delete
213202
cleanFolders?: string[]

src/ampCreator.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ export function ampCreator(options, setup, wrap) {
3434
cleanFolders,
3535
// html / twig
3636
twig,
37-
ampOptimize,
38-
minifyHtml,
39-
cleanInlineCSS,
37+
ampOptimizer,
38+
minifyHtml, minifyHtmlOptions,
39+
cleanInlineCSS, cleanInlineCSSOptions,
4040
cleanInlineCSSWhitelist,
4141
cssInjectTag,
42-
cssFailOnSize,
42+
cssFailOnSize, cssSizeLimit,
4343
pages,
4444
collections,
4545
// media
@@ -100,13 +100,13 @@ export function ampCreator(options, setup, wrap) {
100100
srcMedia, distMedia,
101101
dist,
102102
twig,
103-
ampOptimize,
104-
minifyHtml,
103+
ampOptimizer,
104+
minifyHtml, minifyHtmlOptions,
105105
imageminPlugins,
106-
cleanInlineCSS,
106+
cleanInlineCSS, cleanInlineCSSOptions,
107107
cleanInlineCSSWhitelist,
108108
cssInjectTag,
109-
cssFailOnSize,
109+
cssFailOnSize, cssSizeLimit,
110110
collections: collections.filter(collection => collection.pageId === pageId || !collection.pageId),
111111
browsersync,
112112
}),

src/htmlTask/ampOptimizer.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
import through2 from 'through2'
2-
import AmpOptimizer from '@ampproject/toolbox-optimizer'
32

4-
let ampOptimizerRef = {current: null}
5-
const ampOptimizerLib = AmpOptimizer.create()
6-
7-
export function ampOptimizer(doOptimize) {
8-
if(!ampOptimizerRef.current) {
9-
ampOptimizerRef.current = AmpOptimizer.create(typeof doOptimize === 'object' ? doOptimize : undefined)
10-
}
11-
return through2.obj(async (file, _, cb) => {
3+
/**
4+
* @param {DomTransformer|undefined} ampOptimizerLib
5+
*/
6+
export function ampOptimizer(ampOptimizerLib) {
7+
return through2.obj((file, _, cb) => {
128
try {
13-
if(doOptimize && file.isBuffer()) {
14-
const optimizedHtml = await ampOptimizerLib.transformHtml(
15-
file.contents.toString(),
16-
{},
17-
)
18-
file.contents = Buffer.from(optimizedHtml)
9+
if(!ampOptimizerLib) {
10+
cb(null, file)
11+
return
12+
}
13+
if(file.isBuffer()) {
14+
ampOptimizerLib.transformHtml(
15+
file.contents.toString(),
16+
{},
17+
)
18+
.then((optimizedHtml) => {
19+
file.contents = Buffer.from(optimizedHtml)
20+
cb(null, file)
21+
})
22+
.catch((e) => {
23+
cb(e)
24+
})
25+
} else {
26+
cb(new Error('ampOptimizer received invalid file'))
1927
}
20-
cb(null, file)
2128
} catch(e) {
2229
cb(e)
2330
}

src/htmlTask/cleanHtmlCss.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,28 @@ import through2 from 'through2'
33
import {minify as htmlmin} from 'html-minifier'
44
import logger from 'gulplog'
55

6-
export function cleanHtmlCss({cleanInlineCSS, cleanInlineCSSWhitelist = [], minifyHtml}) {
6+
export function cleanHtmlCss(
7+
{
8+
cleanInlineCSS, cleanInlineCSSOptions, cleanInlineCSSWhitelist = [],
9+
minifyHtml, minifyHtmlOptions,
10+
},
11+
) {
712
return through2.obj(async (file, _, cb) => {
813
try {
914
let startHtmlCSSSize = null
1015
if((cleanInlineCSS || minifyHtml) && file.isBuffer()) {
1116
startHtmlCSSSize = Buffer.byteLength(file.contents.toString(), 'utf8')
12-
logger.info('HTML + CSS Size: ' + startHtmlCSSSize + ' bytes @' + (file.pathData || file.path).substr(file.cwd.length + 1))
17+
logger.info('HTML + CSS Size: ' + startHtmlCSSSize + ' bytes @' + (file.pathData || file.path).slice(file.cwd.length + 1))
1318
}
1419
let cleanedHtmlResult = null
1520
if(cleanInlineCSS && file.isBuffer()) {
16-
cleanedHtmlResult = comb(file.contents.toString(), {whitelist: cleanInlineCSSWhitelist})
21+
cleanedHtmlResult = comb(file.contents.toString(), cleanInlineCSSOptions || {
22+
whitelist: cleanInlineCSSWhitelist,
23+
})
1724
file.contents = Buffer.from(cleanedHtmlResult.result)
1825
}
1926
if(minifyHtml && file.isBuffer()) {
20-
file.contents = Buffer.from(htmlmin(file.contents.toString(), {
27+
file.contents = Buffer.from(htmlmin(file.contents.toString(), minifyHtmlOptions || {
2128
collapseBooleanAttributes: true,
2229
collapseInlineTagWhitespace: false,
2330
collapseWhitespace: true,
@@ -30,7 +37,7 @@ export function cleanHtmlCss({cleanInlineCSS, cleanInlineCSSWhitelist = [], mini
3037
if(cleanedHtmlResult) {
3138
logger.info('Removed CSS selectors: ' + cleanedHtmlResult.deletedFromBody.length + ' from body and ' + cleanedHtmlResult.deletedFromHead.length + ' from head')
3239
}
33-
logger.info('Cleaned HTML + CSS Size: ' + cleanedHtmlCSSSize + ' bytes, saved ' + (startHtmlCSSSize - cleanedHtmlCSSSize) + ' bytes @' + (file.pathData || file.path).substr(file.cwd.length))
40+
logger.info('Cleaned HTML + CSS Size: ' + cleanedHtmlCSSSize + ' bytes, saved ' + (startHtmlCSSSize - cleanedHtmlCSSSize) + ' bytes @' + (file.pathData || file.path).slice(file.cwd.length))
3441
}
3542
cb(null, file)
3643
} catch(e) {

src/htmlTask/htmlTask.d.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
import { AmpCreatorOptions } from '../AmpCreatorOptions'
1+
import { AmpCreatorOptions, AmpCreatorOptionsPaths } from '../AmpCreatorOptions'
22
import { TaskFunction } from 'undertaker'
33
import * as stream from 'stream'
44

55
export interface MakeTwigHandlerConfig {
66
twig: AmpCreatorOptions['twig']
7-
paths: AmpCreatorOptions['paths']
8-
ampOptimize: AmpCreatorOptions['ampOptimize']
7+
paths: AmpCreatorOptionsPaths
8+
dist: string
9+
srcMedia: string
10+
distMedia: string
11+
ampOptimizer: AmpCreatorOptions['ampOptimizer']
912
minifyHtml: AmpCreatorOptions['minifyHtml']
13+
minifyHtmlOptions: AmpCreatorOptions['minifyHtmlOptions']
1014
cleanInlineCSS: AmpCreatorOptions['cleanInlineCSS']
15+
cleanInlineCSSOptions: AmpCreatorOptions['cleanInlineCSSOptions']
1116
cleanInlineCSSWhitelist: AmpCreatorOptions['cleanInlineCSSWhitelist']
17+
cssFailOnSize?: boolean
18+
cssSizeLimit?: number
1219
cssInjectTag: AmpCreatorOptions['cssInjectTag']
1320
cssBuffer?: stream.Transform
1421
}
@@ -17,7 +24,7 @@ export function makeTwigHandler(config: MakeTwigHandlerConfig): () => Promise<()
1724

1825
export interface MakeHtmlTaskConfig extends MakeTwigHandlerConfig {
1926
twig: AmpCreatorOptions['twig']
20-
paths: AmpCreatorOptions['paths']
27+
paths: AmpCreatorOptionsPaths
2128
collections: AmpCreatorOptions['collections']
2229
browsersync: any | { stream: Function }
2330
additionalHtmlTasks: any[]

src/htmlTask/htmlTask.js

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,20 @@ import {getImage, resizeUsedImages, addImageSuffix} from './twigFnMedia.js'
1515

1616
const {parallel, series, ...gulp} = gulpBase
1717

18-
export const makeTwigHandler = ({
19-
srcMedia, distMedia,
20-
paths, twig,
21-
ampOptimize,
22-
minifyHtml,
23-
cleanInlineCSS,
24-
cleanInlineCSSWhitelist,
25-
cssInjectTag,
26-
cssFailOnSize,
27-
cssBuffer,
28-
}) => {
18+
export const makeTwigHandler = (
19+
{
20+
srcMedia, distMedia,
21+
paths, twig,
22+
ampOptimizer: ampOptimizerLib,
23+
minifyHtml, minifyHtmlOptions,
24+
cleanInlineCSS, cleanInlineCSSOptions,
25+
cleanInlineCSSWhitelist,
26+
cssInjectTag,
27+
cssFailOnSize,
28+
cssSizeLimit,
29+
cssBuffer,
30+
},
31+
) => {
2932
const extendedTwigFunctions = [
3033
getImage(srcMedia, distMedia),
3134
embedScript(paths.dist),
@@ -37,13 +40,8 @@ export const makeTwigHandler = ({
3740
// share twig logic for `twig-as-entrypoint` and `frontmatter-as-entrypoint` (collections)
3841
if(twig.logicLoader) {
3942
return twig.logicLoader()
40-
.then((logic) => {
41-
// const extraLogic = {
42-
// functions: undefined,
43-
// filters: undefined,
44-
// }
45-
return logic
46-
})
43+
// logic = { functions: undefined, filters: undefined }
44+
.then((logic) => logic)
4745
}
4846
return {}
4947
})
@@ -70,17 +68,23 @@ export const makeTwigHandler = ({
7068
// middlewares after twig compilation
7169
// middlewares for style injection
7270
.pipe(injectCSS({
73-
paths, injectTag: cssInjectTag,
71+
paths: {
72+
stylesInject: paths.stylesInject,
73+
dist: paths.dist,
74+
distStyles: paths.distStyles,
75+
},
76+
injectTag: cssInjectTag,
7477
failOnSize: cssFailOnSize,
78+
sizeLimit: cssSizeLimit,
7579
cssBuffer: cssBuffer,
7680
}))
7781
// middlewares after CSS injection
7882
.pipe(cleanHtmlCss({
79-
minifyHtml,
80-
cleanInlineCSS,
83+
minifyHtml, minifyHtmlOptions,
84+
cleanInlineCSS, cleanInlineCSSOptions,
8185
cleanInlineCSSWhitelist,
8286
}))
83-
.pipe(ampOptimizer(ampOptimize)),
87+
.pipe(ampOptimizer(ampOptimizerLib)),
8488
)
8589
})
8690
}

src/htmlTask/injectCSS.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,35 @@ import replace from 'gulp-replace'
1212
*/
1313
export function injectCSS(
1414
{
15-
paths,
15+
paths: {stylesInject, dist, distStyles} = {},
1616
failOnSize,
17+
sizeLimit = 75000,
1718
injectTag = 'style amp-custom>',
1819
cssBuffer = undefined,
1920
},
2021
) {
2122
return replace(new RegExp(injectTag, 'g'), function() {
22-
if(!paths.stylesInject) return injectTag
23+
if(!stylesInject) return injectTag
2324

2425
let style = ''
2526
try {
2627
if(!cssBuffer) {
27-
style = fs.readFileSync(paths.dist + '/' + paths.distStyles + '/' + paths.stylesInject, 'utf8')
28+
style = fs.readFileSync(dist + '/' + distStyles + '/' + stylesInject, 'utf8')
2829
} else {
2930
style = cssBuffer.contents.toString()
3031
}
31-
if(Buffer.byteLength(style, 'utf8') > 75000) {
32-
logger.error(colors.red('Style Size: ' + (Buffer.byteLength(style, 'utf8')) + ' bytes'))
33-
if(failOnSize) throw new Error('css file exceeds amp limit of 75kb')
34-
} else {
35-
logger.info('Style Size: ' + (Buffer.byteLength(style, 'utf8')) + ' bytes')
36-
}
3732
} catch(err) {
38-
if(failOnSize || err.code !== 'ENOENT') {
33+
if(err.code !== 'ENOENT') {
3934
// only throw if other error then file not-found
4035
throw err
4136
}
4237
}
38+
if(Buffer.byteLength(style, 'utf8') > sizeLimit) {
39+
logger.error(colors.red('Style Size: ' + (Buffer.byteLength(style, 'utf8')) + ' bytes'))
40+
if(failOnSize) throw new Error('css file exceeds amp limit of ' + (sizeLimit / 1000).toFixed(0) + 'kb')
41+
} else {
42+
logger.info('Style Size: ' + (Buffer.byteLength(style, 'utf8')) + ' bytes')
43+
}
4344
return injectTag + '\n' + style + '\n'
4445
})
4546
}

0 commit comments

Comments
 (0)