diff --git a/options.ts b/options.ts index 6e4eb28..f63f5ff 100644 --- a/options.ts +++ b/options.ts @@ -178,9 +178,12 @@ const options: z.input = { }, }, thumbnail: ({ src, width, height }) => { + if (src.endsWith('.svg')) { + return src; + } if (isProd()) { // Add upyun thumbnail support. - return `${src}!upyun520/both/${width}x${height}/quality/100/unsharp/true/progressive/true`; + return `${src}!upyun520/both/${width}x${height}/format/webp/quality/100/unsharp/true/progressive/true`; } // See https://docs.astro.build/en/reference/image-service-reference/#local-services // Remember to add the localhost to you image service settings. diff --git a/package-lock.json b/package-lock.json index 319825d..78ebb70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,8 +42,8 @@ "resize-sensor": "^0.0.6", "rimraf": "^5.0.7", "sharp": "^0.33.4", - "typescript": "^5.4.5", - "unist-util-visit": "^5.0.0" + "typescript": "^5.5.2", + "unist-util-select": "^5.1.0" } }, "node_modules/@ampproject/remapping": { @@ -3290,6 +3290,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/bootstrap": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", @@ -3833,6 +3840,23 @@ "node": ">= 8" } }, + "node_modules/css-selector-parser": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.0.5.tgz", + "integrity": "sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -6701,6 +6725,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -8654,6 +8691,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-select/-/unist-util-select-5.1.0.tgz", + "integrity": "sha512-4A5mfokSHG/rNQ4g7gSbdEs+H586xyd24sdJqF1IWamqrLHvYb+DH48fzxowyOhOfK7YSqX+XlCojAyuuyyT2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.1.0", + "nth-check": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", diff --git a/package.json b/package.json index d5f5788..cd357fc 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "resize-sensor": "^0.0.6", "rimraf": "^5.0.7", "sharp": "^0.33.4", - "typescript": "^5.4.5", - "unist-util-visit": "^5.0.0" + "typescript": "^5.5.2", + "unist-util-select": "^5.1.0" } } diff --git a/plugins/images.ts b/plugins/images.ts index 72e42f2..ca17f08 100644 --- a/plugins/images.ts +++ b/plugins/images.ts @@ -1,8 +1,10 @@ import type { Literal, Node, Parent } from 'unist'; -import { visit } from 'unist-util-visit'; +import { selectAll } from 'unist-util-select'; +import options from '../options'; import { imageMetadata } from '../src/helpers/images'; +import { urlJoin } from '../src/helpers/tools'; -export type ImageNode = Parent & { +type ImageNode = Parent & { url: string; alt: string; name: string; @@ -11,43 +13,72 @@ export type ImageNode = Parent & { attributes: (Literal & { name: string })[]; }; +type MdxJsxAttribute = { + type: 'mdxJsxAttribute'; + name: string; + value: string; +}; + +type MdxJsxFlowElement = Parent & { + name: string; + attributes: MdxJsxAttribute[]; +}; + export const astroImage = () => { return async (tree: Node) => { - const images: ImageNode[] = []; - - // Find all the local image node. - visit(tree, 'image', (node: Node, _, __: Parent) => { - const imageNode = node as ImageNode; - // Skip remote images. - if (imageNode.url.startsWith('http')) { - return; + // Find all the img node. + const imgs = selectAll('mdxJsxFlowElement', tree) + .map((node) => node as MdxJsxFlowElement) + .filter((node) => node.name === 'img'); + for (const img of imgs) { + const srcAttribute = img.attributes.find((attribute) => attribute.name === 'src'); + if (srcAttribute) { + const src = srcAttribute.value; + if (src.startsWith('/')) { + srcAttribute.value = urlJoin(options.assetsPrefix(), src); + } } + } - images.push(imageNode); - }); + // Find all the image node. + const imageNodes = selectAll('image', tree) + .map((node) => node as ImageNode) + .filter((imageNode) => !imageNode.url.startsWith('http')) + .map(transformAstroImage); - // Process images. - await Promise.all(images.map(transformAstroImage)); + // Process image with blur metadata. + await Promise.all(imageNodes); return tree; }; }; const transformAstroImage = async (imageNode: ImageNode) => { - const metadata = await imageMetadata(imageNode.url); - if (metadata == null) { - throw new Error(`Failed to get image metadata: ${imageNode.url}`); - } - - // Convert original node to next/image imageNode.type = 'mdxJsxFlowElement'; imageNode.name = 'Image'; - imageNode.attributes = [ - { type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt }, - { type: 'mdxJsxAttribute', name: 'src', value: metadata.src }, - { type: 'mdxJsxAttribute', name: 'width', value: imageNode.width ?? metadata.width }, - { type: 'mdxJsxAttribute', name: 'height', value: imageNode.height ?? metadata.height }, - { type: 'mdxJsxAttribute', name: 'blurDataURL', value: metadata.blurDataURL }, - { type: 'mdxJsxAttribute', name: 'blurWidth', value: metadata.blurWidth }, - { type: 'mdxJsxAttribute', name: 'blurHeight', value: metadata.blurHeight }, - ]; + + try { + const metadata = await imageMetadata(imageNode.url); + if (metadata == null) { + throw new Error(`Failed to get image metadata: ${imageNode.url}`); + } + + imageNode.attributes = [ + { type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt }, + { type: 'mdxJsxAttribute', name: 'src', value: metadata.src }, + { type: 'mdxJsxAttribute', name: 'width', value: imageNode.width ?? metadata.width }, + { type: 'mdxJsxAttribute', name: 'height', value: imageNode.height ?? metadata.height }, + { type: 'mdxJsxAttribute', name: 'blurDataURL', value: metadata.blurDataURL }, + { type: 'mdxJsxAttribute', name: 'blurWidth', value: metadata.blurWidth }, + { type: 'mdxJsxAttribute', name: 'blurHeight', value: metadata.blurHeight }, + ]; + } catch (error) { + imageNode.attributes = [ + { type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt }, + { + type: 'mdxJsxAttribute', + name: 'src', + value: imageNode.url.startsWith('/') ? urlJoin(options.assetsPrefix(), imageNode.url) : imageNode.url, + }, + ]; + } }; diff --git a/public/images/2024/06/2024062101010412.jpg b/public/images/2024/06/2024062101010412.jpg new file mode 100644 index 0000000..e60b058 Binary files /dev/null and b/public/images/2024/06/2024062101010412.jpg differ diff --git a/src/components/page/post/PostCategory.astro b/src/components/page/post/PostCategory.astro index 40e395a..c1a8317 100644 --- a/src/components/page/post/PostCategory.astro +++ b/src/components/page/post/PostCategory.astro @@ -6,7 +6,7 @@ import options from '@/options'; const pinnedSlug = options.settings.post.category ?? []; const pinnedCategories = pinnedSlug .map((slug) => getCategory(undefined, slug)) - .flatMap((category) => (category !== undefined ? [category] : [])); + .filter((category) => category !== undefined); ---
diff --git a/src/content/posts/2024/2024-04-12-algo-find-the-lowest-costs.mdx b/src/content/posts/2024/2024-04-12-algo-find-the-lowest-costs.mdx index efb58db..5dffaca 100644 --- a/src/content/posts/2024/2024-04-12-algo-find-the-lowest-costs.mdx +++ b/src/content/posts/2024/2024-04-12-algo-find-the-lowest-costs.mdx @@ -46,28 +46,28 @@ cover: /images/2024/04/2024041405050511.png 这也使得这道题在弄懂原理后相当无趣,但考虑我这朋友确实经验尚浅,所以我还是给他继续讲下去,顺带着给了代码实现。这篇博客便是当时内容的摘录整理。 -{'Step +Step 1
做任何算法题,第一步是理解题意,第二步是设想最简单的情况,再慢慢推导到复杂情况。首先,我们先不考虑存在阻塞的情况。最简单场景里,顾客和维修点在一个 1 x 1 的格子的一条边上,这个时候他们间的最短距离为 1。
-{'Step +Step 2
然后我们更进一步,如果他们在一个格子的对角线上呢?他们间的最短路径有两条,为 2。
-{'Step +Step 3
结合初中的几何学知识,我们首先知道一个基本知识,两点之间,直线最短。所以,维修点和顾客在同一条直线上时,他们之间的距离就是直线距离。
-{'Step +Step 4
然后我们再稍微复杂一点,此时顾客和维修点之间是田字格,最短路径就有三条,距离为 3。
-{'Step +Step 5
等到田字格的时候,相信聪明的你已经发现了规律。那就是顾客到维修点的最短距离,等于他们所形成的矩形的横纵两条边边长的总和。按照上面右侧图片所示的箭头所行走的距离都等于这个最短路径。 @@ -75,7 +75,7 @@ cover: /images/2024/04/2024041405050511.png 一般情况下,面试场景的编码题已经可以开始写了。对应的编程思路就是,从维修点出发,在与顾客构成的矩形边界里面,不断逼近,只要能走通那么我们之间就有了最短距离。再把不同维修点到顾客的最短距离排序,选出最小的距离来进行计算费用。 -{'Step +Step 6 倘若以上面的推论作为最终编码的方式,虽然不能说完全错误,但是在当下这个面试很卷的时代,还是有可能被 PASS,为什么呢?因为我们还没有引入阻塞的概念。我们随便画两种阻塞的情况,并且假定这里都属于在当时条件下的最短路径,那么阁下又该如何应对?😆 @@ -88,11 +88,11 @@ cover: /images/2024/04/2024041405050511.png 以此为基础,我们就可以稍微来复习一下大学的算法知识了,贪心算法(贪婪算法)。贪心算法的定义网上随随便便都能找到,这里就不再复述,我们更多地是需要去思考在这个场景的贪心算法如何使用。 -{'Step +Step 7 贪心算法的第一步,就是找寻从顾客开始,所有可能能行走方向距离为 1 的点有哪些(图中蓝色的点)。接着,我们可以以这些距离为 1 的点为基础,去找寻所有距离为 2 的点(图中绿色的点)。以此类推,直到所有的点都没有下一个可以行走的点了。而每计算一次距离为 N 的点的时候,都可以尝试看看里面是否有对应的维修点,如果有,那么终止检索,这个 N 便是最短距离。 -{'Step +Step 8 如上图所示,在我们查找距离为 4 的点的时候,我们就能找到目标维修店,那么我们可以认定,起最短距离就是 4。 @@ -166,3 +166,5 @@ private boolean availablePoint(int[][] routines, int x, int y) { return x >= 0 && x < routines.length && y >= 0 && y <= routines[0].length && (routines[x][y] == 0 || routines[x][y] == -1); } ``` + +![Fin](/images/2024/06/2024062101010412.jpg) diff --git a/src/pages/search/index.astro b/src/pages/search/index.astro index 67d8bae..516fc67 100644 --- a/src/pages/search/index.astro +++ b/src/pages/search/index.astro @@ -13,7 +13,7 @@ const title = `${query} 查询结果`; const searchResults = searchPosts(query) .map((slug) => posts.find((post) => post.slug === slug)) - .flatMap((post) => (post == null ? [] : [post])) + .filter((post) => post !== undefined) .slice(0, options.settings.pagination.search); ---