@@ -23,34 +23,53 @@ const firstLine = (value) => (value ? String(value).split('\n').find((l) => l.tr
2323
2424const TITLE_SEP = ' - '
2525const capitalize = ( s ) => ( s ? s . charAt ( 0 ) . toUpperCase ( ) + s . slice ( 1 ) : s )
26+ const join = ( ...parts ) => parts . filter ( Boolean ) . join ( TITLE_SEP )
2627
27- // Build the page title and description, modelled on 4chan's:
28- // title: "/tv/ - Television & Film - <subject> - 5chan"
28+ // Split a directory title "/tv/ - Television & Film" into its code ("/tv/") and
29+ // name ("Television & Film") halves.
30+ const splitDirectoryTitle = ( title ) => {
31+ const i = title . indexOf ( TITLE_SEP )
32+ return i === - 1 ? { code : title , name : null } : { code : title . slice ( 0 , i ) , name : title . slice ( i + TITLE_SEP . length ) }
33+ }
34+
35+ // Build the page title and description, modelled on 4chan's. For a thread the
36+ // title leads with the directory code + post subject, then the board name, so
37+ // the reader sees what they care about (which board + the post) first:
38+ // title: "/tv/ - <subject> - Television & Film - 5chan"
2939// desc: "<post text> — "/tv/ - Television & Film" on 5chan, a serverless imageboard."
30- // `label ` is the board's display name (nice directory title, else the community
31- // address); it can be null for non-board pages .
32- const buildMeta = ( { kind, comment, label, siteName, tagline } ) => {
40+ // `boardTitle ` is the nice directory title (or null); `label` is the general
41+ // display label (boardTitle, else the community address); both can be null.
42+ const buildMeta = ( { kind, comment, boardTitle , label, siteName, tagline } ) => {
3343 const onSite = tagline ? `${ siteName } , ${ tagline } ` : siteName
3444 const context = label ? `"${ label } " on ${ onSite } ` : onSite // board clause for descriptions
35- const boardPart = label ? `${ label } ${ TITLE_SEP } ` : ''
3645
3746 if ( kind === 'thread' && comment ) {
38- const subject = truncate ( comment . title || firstLine ( comment . content ) , 65 )
39- const body = truncate ( comment . content || comment . title , 120 )
47+ // Display title: post subject, else a content excerpt, else the link URL — capped at 50.
48+ const subject = truncate ( comment . title || firstLine ( comment . content ) || comment . link , 50 )
49+ const body = truncate ( comment . content || comment . title || comment . link , 120 )
50+ let title
51+ if ( boardTitle && subject ) {
52+ const { code, name } = splitDirectoryTitle ( boardTitle )
53+ title = join ( code , subject , name , siteName ) // "/tv/ - <subject> - Television & Film - 5chan"
54+ } else if ( subject ) {
55+ title = join ( label , subject , siteName )
56+ } else {
57+ title = label ? join ( label , siteName ) : siteName
58+ }
4059 return {
41- title : subject ? ` ${ boardPart } ${ subject } ${ TITLE_SEP } ${ siteName } ` : ` ${ boardPart } ${ siteName } ` ,
60+ title,
4261 description : body ? `${ body } — ${ context } .` : `${ capitalize ( context ) } .` ,
4362 }
4463 }
4564 if ( kind === 'catalog' ) {
4665 return {
47- title : ` ${ boardPart } Catalog${ TITLE_SEP } ${ siteName } ` ,
66+ title : join ( label , ' Catalog' , siteName ) ,
4867 description : label ? `Browse the "${ label } " catalog on ${ onSite } .` : `Browse ${ onSite } .` ,
4968 }
5069 }
5170 // board home / fallback
5271 return {
53- title : label ? ` ${ label } ${ TITLE_SEP } ${ siteName } ` : siteName ,
72+ title : label ? join ( label , siteName ) : siteName ,
5473 description : `${ capitalize ( context ) } .` ,
5574 }
5675}
@@ -62,7 +81,7 @@ export const buildPreviewHtml = ({ client, appUrl, comment, board, boardTitle, i
6281 // Board display label: nice directory title > community address > /board/ > none.
6382 const label = boardTitle || comment ?. communityAddress || ( board ? `/${ board } /` : null )
6483
65- const { title, description } = buildMeta ( { kind, comment, label, siteName, tagline : client . tagline } )
84+ const { title, description } = buildMeta ( { kind, comment, boardTitle , label, siteName, tagline : client . tagline } )
6685
6786 const twitterCard = image ? 'summary_large_image' : 'summary'
6887 const favicon = `${ client . appBaseUrl } /favicon.ico`
0 commit comments