1- import fs from "fs"
2- import path from "path"
3- import dotenv from "dotenv"
4- import { DateTime } from "luxon"
5- import hljs from "highlight.js"
6- import markdownIt from "markdown-it"
7- import anchor from "markdown-it-anchor"
8- import bracketedSpans from "markdown-it-bracketed-spans"
9- import attrs from "markdown-it-attrs"
10- import toc from "markdown-it-table-of-contents"
11- import mark from "markdown-it-mark"
12- import { eleventyImageTransformPlugin } from "@11ty/eleventy-img"
13- import rssPlugin from "@11ty/eleventy-plugin-rss"
14-
15- dotenv . config ( )
16-
17- export default function ( eleventyConfig ) {
18- const isDevelopment = process . env . NODE_ENV === "development"
19- const markdownItConfig = markdownIt ( {
20- html : true ,
21- linkify : true ,
22- typographer : true ,
23- highlight : function ( str , lang ) {
24- if ( lang && hljs . getLanguage ( lang ) ) {
25- try {
26- return hljs . highlight ( str , { language : lang } ) . value
27- } catch ( __ ) { }
28- }
29- return ""
30- } ,
31- } )
32- . use ( anchor , {
33- permalink : anchor . permalink . linkAfterHeader ( {
34- style : "visually-hidden" ,
35- assistiveText : ( title ) => `Link to heading “${ title } ”` ,
36- visuallyHiddenClass : "sr-only" ,
37- wrapper : [ '<div class="header-wrapper">' , '</div>' ] ,
38- } ) ,
39- } )
40- . use ( bracketedSpans )
41- . use ( attrs , {
42- leftDelimiter : "{" ,
43- rightDelimiter : "}" ,
44- allowedAttributes : [ ] ,
45- } )
46- . use ( toc , {
47- includeLevel : [ 1 , 2 , 3 ] ,
48- containerHeaderHtml : `<div class="toc-container-header">Table of Contents</div>` ,
49- } )
50- . use ( mark )
51-
52- eleventyConfig . setLibrary ( "md" , markdownItConfig )
53- eleventyConfig . addGlobalData ( "isDevelopment" , isDevelopment )
54-
55- eleventyConfig . addPlugin ( rssPlugin , {
56- posthtmlRenderOptions : {
57- closingSingleTag : "default" ,
58- } ,
59- } )
60-
61- eleventyConfig . addPlugin ( eleventyImageTransformPlugin ) ;
62-
63- eleventyConfig . addPassthroughCopy ( {
64- "src/assets/*.pdf" : "assets" ,
65- "src/assets/images" : "images" ,
66- "src/admin/*" : "admin" ,
67- "settings.json" : "settings.json" ,
68- "src/robots.txt" : "robots.txt" ,
69- "src/pretty-atom-feed .xsl" : "pretty-atom-feed.xsl "
70- } )
71-
72- if ( isDevelopment ) {
73- eleventyConfig . addPassthroughCopy ( {
74- "src/assets/js" : "js" ,
75- } )
76- }
77-
78- eleventyConfig . addFilter ( "postDate" , ( dateObj ) => {
79- if ( typeof dateObj !== "object" ) dateObj = new Date ( dateObj )
80- return DateTime . fromJSDate ( dateObj ) . toLocaleString ( DateTime . DATE_MED )
81- } )
82-
83- eleventyConfig . addFilter ( "reverseGroupedPosts" , ( object ) =>
84- Object . entries ( object ) . sort ( ( a , b ) => b [ 0 ] - a [ 0 ] )
85- )
86-
87- eleventyConfig . addFilter ( "htmlDateString" , ( dateObj ) => {
88- let date = new Date ( dateObj )
89- return date . toISOString ( )
90- } )
91-
92- eleventyConfig . addFilter ( "postYear" , ( dateObj ) => {
93- return DateTime . fromJSDate ( dateObj ) . toLocaleString ( { year : "numeric" } )
94- } )
95-
96- eleventyConfig . addFilter ( "sliceRecent" , ( array ) => {
97- return array . slice ( 0 , 3 )
98- } )
99-
100- eleventyConfig . addFilter ( "clipText" , ( string , size = 12 , separator = "-" ) => {
101- return string . split ( separator ) . splice ( 0 , size ) . join ( separator )
102- } )
103-
104- eleventyConfig . addFilter ( "serializeTitle" , ( string , yearSplice = 2 ) => {
105- const titleParts = string . split ( "-" )
106- const [ year , ...title ] = titleParts
107- const titleInitials = title . map ( ( title ) => title . split ( "" ) [ 0 ] ) . join ( "" )
108- const yearSuffix = year . slice ( - yearSplice )
109-
110- return `${ yearSuffix } -${ titleInitials } `
111- } )
112-
113- eleventyConfig . addFilter ( "development" , ( link ) => {
114- return isDevelopment ? "/" : link
115- } )
116-
117- eleventyConfig . addFilter ( "breakLine" , ( string , cutAt = 3 , maxSize = 30 ) => {
118- const titleWords = string . split ( " " )
119- const titleLength = string . length
120- const titlePreview = titleWords . slice ( 0 , cutAt ) . join ( " " )
121- const titleRemaining = titleWords . slice ( cutAt ) . join ( " " )
122-
123- const hasTitleRemaining = ! ! titleRemaining
124- const formattedTitleWithBreak = hasTitleRemaining
125- ? `${ titlePreview } <br/>${ titleRemaining } `
126- : titlePreview
127-
128- return titleLength <= maxSize || ! hasTitleRemaining
129- ? string
130- : formattedTitleWithBreak
131- } )
132-
133- eleventyConfig . addFilter ( "svg" , ( fileName , index ) => {
134- const filePath = path . join ( process . cwd ( ) , "src/assets/svg" , fileName )
135- try {
136- let svgContent = fs . readFileSync ( filePath , "utf8" )
137- if ( index ) {
138- svgContent = svgContent . replace (
139- "<svg" ,
140- `<svg data-animation="fade-in" data-delay=${ index } `
141- )
142- }
143- return svgContent
144- } catch ( error ) {
145- return `<!-- SVG ${ fileName } not found -->`
146- }
147- } )
148-
149- eleventyConfig . addFilter ( "renderMarkdown" , ( text ) => {
150- return markdownItConfig . render ( text )
151- } )
152-
153- eleventyConfig . addFilter ( "renderMarkdownInline" , ( text ) => {
154- return markdownItConfig . renderInline ( text )
155- } )
156-
157- eleventyConfig . addFilter ( "featuredDate" , ( string ) => {
158- let date = new Date ( string )
159- return date . toLocaleDateString ( "en-us" , {
160- year : "numeric" ,
161- month : "short" ,
162- day : "numeric" ,
163- } )
164- } )
165-
166- return {
167- templateFormats : [ "md" , "njk" , "html" , "liquid" ] ,
168- markdownTemplateEngine : "liquid" ,
169- htmlTemplateEngine : "njk" ,
170- dataTemplateEngine : "njk" ,
171- dir : {
172- data : "_data" ,
173- input : "src" ,
174- output : "public" ,
175- } ,
176- }
1+ import fs from "fs"
2+ import path from "path"
3+ import dotenv from "dotenv"
4+ import { DateTime } from "luxon"
5+ import hljs from "highlight.js"
6+ import markdownIt from "markdown-it"
7+ import anchor from "markdown-it-anchor"
8+ import bracketedSpans from "markdown-it-bracketed-spans"
9+ import attrs from "markdown-it-attrs"
10+ import toc from "markdown-it-table-of-contents"
11+ import mark from "markdown-it-mark"
12+ import { eleventyImageTransformPlugin } from "@11ty/eleventy-img"
13+ import rssPlugin from "@11ty/eleventy-plugin-rss"
14+
15+ dotenv . config ( )
16+
17+ export default function ( eleventyConfig ) {
18+ const isDevelopment = process . env . NODE_ENV === "development"
19+ const markdownItConfig = markdownIt ( {
20+ html : true ,
21+ linkify : true ,
22+ typographer : true ,
23+ highlight : function ( str , lang ) {
24+ if ( lang && hljs . getLanguage ( lang ) ) {
25+ try {
26+ return hljs . highlight ( str , { language : lang } ) . value
27+ } catch ( __ ) { }
28+ }
29+ return ""
30+ } ,
31+ } )
32+ . use ( anchor , {
33+ permalink : anchor . permalink . linkAfterHeader ( {
34+ style : "visually-hidden" ,
35+ assistiveText : ( title ) => `Link to heading “${ title } ”` ,
36+ visuallyHiddenClass : "sr-only" ,
37+ wrapper : [ '<div class="header-wrapper">' , '</div>' ] ,
38+ } ) ,
39+ } )
40+ . use ( bracketedSpans )
41+ . use ( attrs , {
42+ leftDelimiter : "{" ,
43+ rightDelimiter : "}" ,
44+ allowedAttributes : [ ] ,
45+ } )
46+ . use ( toc , {
47+ includeLevel : [ 1 , 2 , 3 ] ,
48+ containerHeaderHtml : `<div class="toc-container-header">Table of Contents</div>` ,
49+ } )
50+ . use ( mark )
51+
52+ eleventyConfig . setLibrary ( "md" , markdownItConfig )
53+ eleventyConfig . addGlobalData ( "isDevelopment" , isDevelopment )
54+
55+ eleventyConfig . addPlugin ( rssPlugin , {
56+ posthtmlRenderOptions : {
57+ closingSingleTag : "default" ,
58+ } ,
59+ } )
60+
61+ eleventyConfig . addPlugin ( eleventyImageTransformPlugin ) ;
62+
63+ eleventyConfig . addPassthroughCopy ( {
64+ "src/assets/*.pdf" : "assets" ,
65+ "src/assets/images" : "images" ,
66+ "src/admin/*" : "admin" ,
67+ "settings.json" : "settings.json" ,
68+ "src/robots.txt" : "robots.txt" ,
69+ "src/* .xsl" : "/ "
70+ } )
71+
72+ if ( isDevelopment ) {
73+ eleventyConfig . addPassthroughCopy ( {
74+ "src/assets/js" : "js" ,
75+ } )
76+ }
77+
78+ eleventyConfig . addFilter ( "postDate" , ( dateObj ) => {
79+ if ( typeof dateObj !== "object" ) dateObj = new Date ( dateObj )
80+ return DateTime . fromJSDate ( dateObj ) . toLocaleString ( DateTime . DATE_MED )
81+ } )
82+
83+ eleventyConfig . addFilter ( "reverseGroupedPosts" , ( object ) =>
84+ Object . entries ( object ) . sort ( ( a , b ) => b [ 0 ] - a [ 0 ] )
85+ )
86+
87+ eleventyConfig . addFilter ( "htmlDateString" , ( dateObj ) => {
88+ let date = new Date ( dateObj )
89+ return date . toISOString ( )
90+ } )
91+
92+ eleventyConfig . addFilter ( "postYear" , ( dateObj ) => {
93+ return DateTime . fromJSDate ( dateObj ) . toLocaleString ( { year : "numeric" } )
94+ } )
95+
96+ eleventyConfig . addFilter ( "sliceRecent" , ( array ) => {
97+ return array . slice ( 0 , 3 )
98+ } )
99+
100+ eleventyConfig . addFilter ( "clipText" , ( string , size = 12 , separator = "-" ) => {
101+ return string . split ( separator ) . splice ( 0 , size ) . join ( separator )
102+ } )
103+
104+ eleventyConfig . addFilter ( "serializeTitle" , ( string , yearSplice = 2 ) => {
105+ const titleParts = string . split ( "-" )
106+ const [ year , ...title ] = titleParts
107+ const titleInitials = title . map ( ( title ) => title . split ( "" ) [ 0 ] ) . join ( "" )
108+ const yearSuffix = year . slice ( - yearSplice )
109+
110+ return `${ yearSuffix } -${ titleInitials } `
111+ } )
112+
113+ eleventyConfig . addFilter ( "development" , ( link ) => {
114+ return isDevelopment ? "/" : link
115+ } )
116+
117+ eleventyConfig . addFilter ( "breakLine" , ( string , cutAt = 3 , maxSize = 30 ) => {
118+ const titleWords = string . split ( " " )
119+ const titleLength = string . length
120+ const titlePreview = titleWords . slice ( 0 , cutAt ) . join ( " " )
121+ const titleRemaining = titleWords . slice ( cutAt ) . join ( " " )
122+
123+ const hasTitleRemaining = ! ! titleRemaining
124+ const formattedTitleWithBreak = hasTitleRemaining
125+ ? `${ titlePreview } <br/>${ titleRemaining } `
126+ : titlePreview
127+
128+ return titleLength <= maxSize || ! hasTitleRemaining
129+ ? string
130+ : formattedTitleWithBreak
131+ } )
132+
133+ eleventyConfig . addFilter ( "svg" , ( fileName , index ) => {
134+ const filePath = path . join ( process . cwd ( ) , "src/assets/svg" , fileName )
135+ try {
136+ let svgContent = fs . readFileSync ( filePath , "utf8" )
137+ if ( index ) {
138+ svgContent = svgContent . replace (
139+ "<svg" ,
140+ `<svg data-animation="fade-in" data-delay=${ index } `
141+ )
142+ }
143+ return svgContent
144+ } catch ( error ) {
145+ return `<!-- SVG ${ fileName } not found -->`
146+ }
147+ } )
148+
149+ eleventyConfig . addFilter ( "renderMarkdown" , ( text ) => {
150+ return markdownItConfig . render ( text )
151+ } )
152+
153+ eleventyConfig . addFilter ( "renderMarkdownInline" , ( text ) => {
154+ return markdownItConfig . renderInline ( text )
155+ } )
156+
157+ eleventyConfig . addFilter ( "featuredDate" , ( string ) => {
158+ let date = new Date ( string )
159+ return date . toLocaleDateString ( "en-us" , {
160+ year : "numeric" ,
161+ month : "short" ,
162+ day : "numeric" ,
163+ } )
164+ } )
165+
166+ return {
167+ templateFormats : [ "md" , "njk" , "html" , "liquid" ] ,
168+ markdownTemplateEngine : "liquid" ,
169+ htmlTemplateEngine : "njk" ,
170+ dataTemplateEngine : "njk" ,
171+ dir : {
172+ data : "_data" ,
173+ input : "src" ,
174+ output : "public" ,
175+ } ,
176+ }
177177}
0 commit comments