Skip to content

Commit

Permalink
chore(11ty): configをtsにする
Browse files Browse the repository at this point in the history
  • Loading branch information
yamadashy committed Aug 11, 2024
1 parent 3b2a3be commit 21a9fd1
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 53 deletions.
78 changes: 44 additions & 34 deletions .eleventy.js → eleventy.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
const htmlmin = require('html-minifier-terser');
const Image = require('@11ty/eleventy-img');
const path = require('path');
const ts = require('typescript');
const eleventyCacheOption = require('./src/common/eleventy-cache-option');
const CleanCSS = require("clean-css");
const EleventyFetch = require("@11ty/eleventy-fetch");
const sharpIco = require("sharp-ico");
const url = require('url');

Image.concurrency = 50;

const minifyHtmlTransform = (content, outputPath) => {
import htmlmin from 'html-minifier-terser';
import EleventyImage from '@11ty/eleventy-img';
import EleventyFetch from "@11ty/eleventy-fetch";
import path from 'path';
import ts from 'typescript';
import { imageCacheOptions } from './src/common/eleventy-cache-option';
import CleanCSS from "clean-css";
import { Sharp } from 'sharp';
import sharpIco, {ImageData} from "sharp-ico";
import url from 'url';
import Eleventy from '@11ty/eleventy';

const ELEVENTY_FETCH_CONCURRENCY = 50;

EleventyImage.concurrency = ELEVENTY_FETCH_CONCURRENCY;

const minifyHtmlTransform = (content: string, outputPath: string) => {
if(outputPath && outputPath.endsWith('.html')) {
return htmlmin.minify(content, {
// オプション参考: https://github.com/terser/html-minifier-terser#options-quick-reference
Expand All @@ -26,16 +30,16 @@ const minifyHtmlTransform = (content, outputPath) => {
return content;
}

const imageThumbnailShortcode = async (src, alt, pathPrefix = '') => {
let metadata = null;
const imageThumbnailShortcode = async (src: string, alt: string, pathPrefix: string = '') => {
let metadata: EleventyImage.Metadata;

try {
metadata = await Image(src, {
metadata = await EleventyImage(src, {
widths: [150, 450],
formats: ["webp", "jpeg"],
outputDir: 'public/images/feed-thumbnails',
urlPath: `${pathPrefix}images/feed-thumbnails/`,
cacheOptions: eleventyCacheOption,
cacheOptions: imageCacheOptions,
sharpWebpOptions: {
quality: 50,
},
Expand All @@ -49,27 +53,33 @@ const imageThumbnailShortcode = async (src, alt, pathPrefix = '') => {
return `<img src='${pathPrefix}images/alternate-feed-image.png' alt='${alt}' loading='lazy' width='256' height='256'>`
}

return Image.generateHTML(metadata, {
return EleventyImage.generateHTML(metadata, {
alt,
sizes: '100vw',
loading: 'lazy',
decoding: 'async',
});
}

const imageIconShortcode = async (src, alt, pathPrefix = '') => {
const imageIconShortcode = async (src: string, alt: string, pathPrefix: string = '') => {
const parsedUrl = url.parse(src);
const fileName = path.basename(parsedUrl.pathname);
const fileName = path.basename(parsedUrl.pathname || '');
const fileExtension = path.extname(fileName).toLowerCase();
let imageSrc = src;
let metadata = null;
let imageSrc: EleventyImage.ImageSource = src;
let metadata: EleventyImage.Metadata;

if (fileExtension === '.ico') {
try {
const icoBuffer = await EleventyFetch(src, eleventyCacheOption);
const sharpInstances = await sharpIco.sharpsFromIco(icoBuffer);
const sharpInstance = sharpInstances.sort((a, b) => b.width - a.width)[0];
imageSrc = await sharpInstance.png().toBuffer();
const icoBuffer = await EleventyFetch(src, {
type: 'buffer',
duration: imageCacheOptions.duration,
concurrency: ELEVENTY_FETCH_CONCURRENCY,
});
const sharpIcoImages = await sharpIco.sharpsFromIco(icoBuffer, {}, true) as ImageData[];
const sharpIcoImage = sharpIcoImages.sort((a, b) => b.width - a.width)[0];
if (sharpIcoImage.image) {
imageSrc = await sharpIcoImage.image.png().toBuffer();
}
} catch (error) {
// エラーが起きたら画像なし
console.error('[image-icon-short-code] Error processing ICO:', src, error);
Expand All @@ -78,12 +88,12 @@ const imageIconShortcode = async (src, alt, pathPrefix = '') => {
}

try {
metadata = await Image(imageSrc, {
metadata = await EleventyImage(imageSrc, {
widths: [16],
formats: ["png"],
outputDir: 'public/images/feed-icons',
urlPath: `${pathPrefix}images/feed-icons/`,
cacheOptions: eleventyCacheOption,
cacheOptions: imageCacheOptions,
sharpPngOptions: {
quality: 50,
}
Expand All @@ -94,27 +104,27 @@ const imageIconShortcode = async (src, alt, pathPrefix = '') => {
return ``
}

return Image.generateHTML(metadata, {
return EleventyImage.generateHTML(metadata, {
alt,
loading: 'lazy',
decoding: 'async',
});
}

const relativeUrlFilter = (url) => {
const relativeUrlFilter = (url: string) => {
const relativeUrl = path.relative(url, '/');
return relativeUrl === '' ? './' : `${relativeUrl}/`;
}

const minifyCssFilter = (css) => {
const minifyCssFilter = (css: string) => {
return new CleanCSS({}).minify(css).styles;
}

const supportTypeScriptTemplate = (eleventyConfig) => {
const supportTypeScriptTemplate = (eleventyConfig: Eleventy.UserConfig) => {
eleventyConfig.addTemplateFormats('ts');
eleventyConfig.addExtension('ts', {
outputFileExtension: 'js',
compile: async (inputContent) => {
compile: async (inputContent: string) => {
return async () => {
const result = ts.transpileModule(inputContent, { compilerOptions: { module: ts.ModuleKind.CommonJS }});
return result.outputText;
Expand All @@ -123,7 +133,7 @@ const supportTypeScriptTemplate = (eleventyConfig) => {
});
}

module.exports = function (eleventyConfig) {
module.exports = function (eleventyConfig: Eleventy.UserConfig) {
// static assets
eleventyConfig.addPassthroughCopy('src/site/images');
eleventyConfig.addPassthroughCopy('src/site/feeds');
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"build": "yarn feed-generate && yarn site-build",
"feed-generate": "node --require esbuild-register src/feed/generate-feed-command.ts",
"register-index": "node --require esbuild-register src/feed/register-index-command.ts",
"site-build": "eleventy",
"site-serve": "eleventy --serve",
"site-build": "node --require esbuild-register ./node_modules/.bin/eleventy --config=eleventy.config.ts",
"site-serve": "node --require esbuild-register ./node_modules/.bin/eleventy --config=eleventy.config.ts --serve",
"lint": "eslint ./src ./tests --max-warnings 0 --cache --format friendly --fix && tsc --noEmit",
"test": "vitest run",
"test-coverage": "vitest run --coverage",
Expand Down Expand Up @@ -41,6 +41,7 @@
"@supercharge/promise-pool": "^3.1.0",
"@types/11ty__eleventy-img": "^4.0.0",
"@types/async-retry": "^1.4.3",
"@types/clean-css": "^4.2.11",
"@types/eslint": "^9.0.0",
"@types/eslint-config-prettier": "^6.11.2",
"@types/eslint-plugin-prettier": "^3.1.0",
Expand All @@ -57,6 +58,7 @@
"async-retry": "^1.3.3",
"await-to-js": "^3.0.0",
"axios": "^1.6.0",
"clean-css": "^5.3.3",
"dayjs": "^1.11.10",
"esbuild-register": "^3.5.0",
"eslint": "^9.1.1",
Expand Down
24 changes: 24 additions & 0 deletions src/@types/eleventy-fetch.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
declare module '@11ty/eleventy-fetch' {
import { Buffer } from 'buffer';

export type FetchType = 'json' | 'buffer' | 'text';

export interface EleventyFetchOptions<TType extends FetchType = 'buffer'> {
type?: TType;
directory?: string;
concurrency?: number;
fetchOptions?: Node.RequestInit;
dryRun?: boolean;
removeUrlQueryParams?: boolean;
verbose?: boolean;
hashLength?: number;
duration?: string;
formatUrlForDisplay?: (url: string) => string;
}

export function EleventyFetch(url: string, options?: EleventyFetchOptions<'buffer'>): Promise<Buffer>;
export function EleventyFetch<T>(url: string, options: EleventyFetchOptions<'json'>): Promise<T>;
export function EleventyFetch(url: string, options: EleventyFetchOptions<'text'>): Promise<string>;

export default EleventyFetch;
}
1 change: 1 addition & 0 deletions src/common/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
const siteUrlStem = 'https://yamadashy.github.io/tech-blog-rss-feed';
const siteUrl = `${siteUrlStem}/`;

Expand Down
11 changes: 0 additions & 11 deletions src/common/eleventy-cache-option.js

This file was deleted.

12 changes: 12 additions & 0 deletions src/common/eleventy-cache-option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import constants from './constants';
import EleventyImage from '@11ty/eleventy-img';

export const imageCacheOptions: EleventyImage.CacheOptions = {
duration: '3d',
type: 'buffer',
fetchOptions: {
headers: {
'User-Agent': constants.requestUserAgent,
},
},
};
14 changes: 9 additions & 5 deletions src/feed/utils/feed-image-precacher.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PromisePool } from '@supercharge/promise-pool';
import { logger } from './logger';
import eleventyCacheOption from '../../common/eleventy-cache-option';
import { imageCacheOptions } from '../../common/eleventy-cache-option';
import { to } from 'await-to-js';
import { CustomRssParserFeed, CustomRssParserItem, OgObjectMap } from './feed-crawler';
const EleventyFetch = require('@11ty/eleventy-fetch');
import EleventyFetch from '@11ty/eleventy-fetch';

export class ImagePrecacher {
public async fetchAndCacheFeedImages(
Expand All @@ -29,12 +29,16 @@ export class ImagePrecacher {
const ogImageUrlsLength = ogImageUrls.length;
let fetchProcessCounter = 1;

EleventyFetch.concurrency = concurrency;

await PromisePool.for(ogImageUrls)
.withConcurrency(concurrency)
.process(async (ogImageUrl) => {
const [error] = await to(EleventyFetch(ogImageUrl, eleventyCacheOption));
const [error] = await to(
EleventyFetch(ogImageUrl, {
type: 'buffer',
duration: imageCacheOptions.duration,
concurrency,
}),
);
if (error) {
logger.error('[cache-og-image] error', `${fetchProcessCounter++}/${ogImageUrlsLength}`, ogImageUrl);
logger.trace(error);
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"src/**/*",
"tests/**/*",
"vitest.config.ts",
"eleventy.config.ts",
]
}
14 changes: 13 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3466,6 +3466,16 @@ __metadata:
languageName: node
linkType: hard

"@types/clean-css@npm:^4.2.11":
version: 4.2.11
resolution: "@types/clean-css@npm:4.2.11"
dependencies:
"@types/node": "npm:*"
source-map: "npm:^0.6.0"
checksum: 10/385337a881c7870664d8987f12b9c814d835104dcf5f1737b74ab759ca68424ce93636cbff73ea9c41290c3dc2a92a4cc6246869bd9982255cfa28dcc2ccec93
languageName: node
linkType: hard

"@types/connect@npm:*":
version: 3.4.38
resolution: "@types/connect@npm:3.4.38"
Expand Down Expand Up @@ -5134,7 +5144,7 @@ __metadata:
languageName: node
linkType: hard

"clean-css@npm:~5.3.2":
"clean-css@npm:^5.3.3, clean-css@npm:~5.3.2":
version: 5.3.3
resolution: "clean-css@npm:5.3.3"
dependencies:
Expand Down Expand Up @@ -12617,6 +12627,7 @@ __metadata:
"@supercharge/promise-pool": "npm:^3.1.0"
"@types/11ty__eleventy-img": "npm:^4.0.0"
"@types/async-retry": "npm:^1.4.3"
"@types/clean-css": "npm:^4.2.11"
"@types/eslint": "npm:^9.0.0"
"@types/eslint-config-prettier": "npm:^6.11.2"
"@types/eslint-plugin-prettier": "npm:^3.1.0"
Expand All @@ -12633,6 +12644,7 @@ __metadata:
async-retry: "npm:^1.3.3"
await-to-js: "npm:^3.0.0"
axios: "npm:^1.6.0"
clean-css: "npm:^5.3.3"
dayjs: "npm:^1.11.10"
esbuild-register: "npm:^3.5.0"
eslint: "npm:^9.1.1"
Expand Down

0 comments on commit 21a9fd1

Please sign in to comment.