@@ -16,6 +16,7 @@ import {Resvg, initWasm as initResvgWasm, type ResvgRenderOptions} from "@resvg/
16
16
import { BlogPageInfoPlugin } from "./config/BlogPageInfoPlugin.js" ;
17
17
import { getApiReferenceSidebar } from "./config/apiReferenceSidebar.js" ;
18
18
import { ensureLocalImage } from "./utils/ensureLocalImage.js" ;
19
+ import { getExcerptFromMarkdownFile } from "./utils/getExcerptFromMarkdownFile.js" ;
19
20
import type { Element as HastElement , Parent } from "hast" ;
20
21
21
22
import type { Node as UnistNode } from "unist" ;
@@ -28,6 +29,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
28
29
const packageJson : typeof import ( "../package.json" ) = fs . readJsonSync ( path . join ( __dirname , ".." , "package.json" ) ) ;
29
30
const env = envVar . from ( process . env ) ;
30
31
32
+ const docsDir = path . join ( __dirname , ".." , "docs" ) ;
31
33
const urlBase = env . get ( "DOCS_URL_BASE" )
32
34
. asString ( ) ;
33
35
const packageVersion = env . get ( "DOCS_PACKAGE_VERSION" )
@@ -66,9 +68,9 @@ function resolveHref(href: string, withDomain: boolean = false): string {
66
68
}
67
69
68
70
const defaultImageMetaTags : HeadConfig [ ] = [
69
- [ "meta" , { name : "og:image" , content : socialPosterLink } ] ,
70
- [ "meta" , { name : "og:image:width" , content : "4096" } ] ,
71
- [ "meta" , { name : "og:image:height" , content : "2048" } ] ,
71
+ [ "meta" , { property : "og:image" , content : socialPosterLink } ] ,
72
+ [ "meta" , { property : "og:image:width" , content : "4096" } ] ,
73
+ [ "meta" , { property : "og:image:height" , content : "2048" } ] ,
72
74
[ "meta" , { name : "twitter:image" , content : socialPosterLink } ] ,
73
75
[ "meta" , { name : "twitter:card" , content : "summary_large_image" } ]
74
76
] ;
@@ -185,9 +187,9 @@ export default defineConfig({
185
187
[ "link" , { rel : "alternate" , title : "Blog" , type : "application/atom+xml" , href : resolveHref ( "/blog/feed.atom" , true ) } ] ,
186
188
[ "meta" , { name : "theme-color" , content : "#cd8156" } ] ,
187
189
[ "meta" , { name : "theme-color" , content : "#dd773e" , media : "(prefers-color-scheme: dark)" } ] ,
188
- [ "meta" , { name : "og:type" , content : "website" } ] ,
189
- [ "meta" , { name : "og:locale" , content : "en" } ] ,
190
- [ "meta" , { name : "og:site_name" , content : "node-llama-cpp" } ] ,
190
+ [ "meta" , { property : "og:type" , content : "website" } ] ,
191
+ [ "meta" , { property : "og:locale" , content : "en" } ] ,
192
+ [ "meta" , { property : "og:site_name" , content : "node-llama-cpp" } ] ,
191
193
[ "script" , { async : "" , src : "https://www.googletagmanager.com/gtag/js?id=G-Q2SWE5Z1ST" } ] ,
192
194
[
193
195
"script" ,
@@ -198,8 +200,10 @@ export default defineConfig({
198
200
[ "style" , { } ]
199
201
] ,
200
202
async transformHead ( { pageData, head} ) {
203
+ let description = pageData . description ;
201
204
if ( pageData . filePath === "index.md" ) {
202
205
head . push ( ...defaultImageMetaTags ) ;
206
+ description ||= defaultPageDescription ;
203
207
} else if ( pageData . relativePath === "404.md" )
204
208
head . push ( ...defaultImageMetaTags ) ;
205
209
@@ -209,7 +213,6 @@ export default defineConfig({
209
213
]
210
214
. filter ( Boolean )
211
215
. join ( " - " ) || defaultPageTitle ;
212
- const description = pageData . description || defaultPageDescription ;
213
216
214
217
if ( pageData . filePath . startsWith ( "blog/" ) && pageData . frontmatter . image != null ) {
215
218
let imageDir = pageData . filePath ;
@@ -220,7 +223,7 @@ export default defineConfig({
220
223
const coverImage = await ensureLocalImage ( pageData . frontmatter . image , "cover" , {
221
224
baseDestLocation : imageDir . split ( "/" )
222
225
} ) ;
223
- head . push ( [ "meta" , { name : "og:image" , content : resolveHref ( coverImage . urlPath . absolute , true ) } ] ) ;
226
+ head . push ( [ "meta" , { property : "og:image" , content : resolveHref ( coverImage . urlPath . absolute , true ) } ] ) ;
224
227
} else if ( typeof pageData . frontmatter . image === "object" ) {
225
228
const coverImage = typeof pageData . frontmatter . image . url === "string"
226
229
? await ensureLocalImage ( pageData . frontmatter . image . url , "cover" , {
@@ -230,28 +233,53 @@ export default defineConfig({
230
233
231
234
if ( typeof pageData . frontmatter . image . url === "string" )
232
235
head . push ( [ "meta" , {
233
- name : "og:image" ,
236
+ property : "og:image" ,
234
237
content : resolveHref ( coverImage ?. urlPath . absolute ?? pageData . frontmatter . image . url , true )
235
238
} ] ) ;
236
239
237
240
if ( pageData . frontmatter . image . width != null )
238
241
head . push ( [ "meta" , {
239
- name : "og:image:width" ,
242
+ property : "og:image:width" ,
240
243
content : String ( coverImage ?. width ?? pageData . frontmatter . image . width )
241
244
} ] ) ;
242
245
243
246
if ( pageData . frontmatter . image . height != null )
244
247
head . push ( [ "meta" , {
245
- name : "og:image:height" ,
248
+ property : "og:image:height" ,
246
249
content : String ( coverImage ?. height ?? pageData . frontmatter . image . height )
247
250
} ] ) ;
248
251
}
249
252
}
250
253
251
- head . push ( [ "meta" , { name : "og:title" , content : title } ] ) ;
252
- head . push ( [ "meta" , { name : "og:description" , content : description } ] ) ;
254
+ const markdownFilePath = path . join ( docsDir , pageData . filePath ) ;
255
+ if ( ( description == null || description === "" ) && await fs . pathExists ( markdownFilePath ) && ! pageData . filePath . startsWith ( "api/" ) ) {
256
+ const excerpt = await getExcerptFromMarkdownFile ( await fs . readFile ( markdownFilePath , "utf8" ) ) ;
257
+ if ( excerpt != null && excerpt !== "" )
258
+ description = excerpt . replaceAll ( '"' , "'" ) . replaceAll ( "\n" , " " ) ;
259
+ }
260
+
261
+ pageData . description = description ;
262
+
263
+ if ( description != null && description !== "" &&
264
+ ( pageData . frontmatter . description == null || pageData . frontmatter . description === "" )
265
+ ) {
266
+ pageData . frontmatter . description = description ;
267
+ for ( let i = 0 ; i < head . length ; i ++ ) {
268
+ const header = head [ i ] ! ;
269
+ if ( header [ 0 ] === "meta" && header [ 1 ] ?. name === "description" ) {
270
+ head [ i ] = [ "meta" , { name : "description" , content : description } ] ;
271
+ break ;
272
+ }
273
+ }
274
+ }
275
+
276
+ head . push ( [ "meta" , { property : "og:title" , content : title } ] ) ;
277
+ if ( description != null && description !== "" )
278
+ head . push ( [ "meta" , { property : "og:description" , content : description } ] ) ;
279
+
253
280
head . push ( [ "meta" , { name : "twitter:title" , content : title } ] ) ;
254
- head . push ( [ "meta" , { name : "twitter:description" , content : description } ] ) ;
281
+ if ( description != null && description !== "" )
282
+ head . push ( [ "meta" , { name : "twitter:description" , content : description } ] ) ;
255
283
} ,
256
284
transformPageData ( pageData ) {
257
285
if ( pageData . filePath . startsWith ( "api/" ) ) {
@@ -307,7 +335,7 @@ export default defineConfig({
307
335
plugins : [
308
336
GitChangelog ( {
309
337
repoURL : ( ) => "https://github.com/withcatai/node-llama-cpp" ,
310
- cwd : path . join ( __dirname , ".." , "docs" )
338
+ cwd : docsDir
311
339
} ) as VitepressPlugin ,
312
340
GitChangelogMarkdownSection ( {
313
341
exclude : ( id ) => (
@@ -703,19 +731,28 @@ export default defineConfig({
703
731
return bDate . getTime ( ) - aDate . getTime ( ) ;
704
732
} ) ;
705
733
706
- for ( const { url, excerpt, frontmatter, html} of blogPosts ) {
707
- const ogImageElement = findElementInHtml ( html , ( element ) => element . tagName === "meta" && element . properties ?. name === "og:imag" ) ;
734
+ for ( const { url, frontmatter, html, src, excerpt : originalExcerpt } of blogPosts ) {
735
+ const ogImageElement = findElementInHtml ( html , ( element ) => (
736
+ element . tagName === "meta" && ( element . properties ?. name === "og:image" || element . properties ?. property === "og:image" )
737
+ ) ) ;
708
738
const date = new Date ( frontmatter . date ) ;
709
739
if ( Number . isNaN ( date . getTime ( ) ) )
710
740
throw new Error ( `Invalid date for blog post: ${ url } ` ) ;
711
741
else if ( frontmatter . title == null || frontmatter . title === "" )
712
742
throw new Error ( `Invalid title for blog post: ${ url } ` ) ;
713
743
744
+ let description : string | undefined = frontmatter . description ;
745
+ if ( ( description == null || description == "" ) && src != null )
746
+ description = await getExcerptFromMarkdownFile ( src ) ;
747
+
748
+ if ( ( description == null || description === "" ) && originalExcerpt != null && originalExcerpt !== "" )
749
+ description = originalExcerpt ;
750
+
714
751
feed . addItem ( {
715
752
title : frontmatter . title ,
716
753
id : resolveHref ( url , true ) ,
717
754
link : resolveHref ( url , true ) ,
718
- description : excerpt || frontmatter . description || undefined ,
755
+ description,
719
756
content : html ,
720
757
author : [ {
721
758
name : frontmatter . author ?. name ,
0 commit comments