1- import { ContentType , ContentPublished , type Lesson , type Podcast } from '$lib/types' ;
1+ import { ContentType , ContentPublished , type Lesson , type Podcast , type Author } from '$lib/types' ;
22import type { Content , Course } from '$lib/types' ;
33import { env } from '$env/dynamic/private' ;
4+ import { fileURLToPath } from 'url' ;
5+ import { opendirSync , readFileSync } from "fs" ;
6+ import { compile } from 'mdsvex' ;
47
58const LIMIT = 20 ;
69
@@ -11,113 +14,152 @@ export const preview = env.PREVIEW === "false" ? false : env.VERCEL_ENV === "pre
1114// While developing locally this allows you to see pages without setting up firebase.
1215export const allowLocal = env . PREVIEW === "false" ? false : import . meta. env . DEV ;
1316
14- export const parseModules = async ( modules : Record < string , ( ) => Promise < unknown > > ) => {
15- const contentList : Content [ ] = [ ] ;
16- for ( const path in modules ) {
17- await modules [ path ] ( ) . then ( ( mod ) => {
18- const splitPath = path . split ( '/' ) ;
19- const courseType = splitPath . at ( - 3 ) ;
20- const normalType = splitPath . at ( - 2 ) ;
21- const slug = splitPath . at ( - 1 ) ;
22- const type = courseType === 'content' ? normalType : courseType ;
23-
24- if ( courseType === 'content' ) {
25- console . log ( `Precompiling: ${ type } /${ slug } ` ) ;
26- } else {
27- console . log ( `Precompiling: ${ type } /${ normalType } ` ) ;
28- }
29-
30- if ( ! type || ! slug ) {
31- console . error ( 'Missing name or type' ) ;
32- return ;
33- }
34-
35- const mdsvx = mod as {
36- default : {
37- render : ( ) => { html : string } ;
38- } ;
39- metadata : Content ;
40- } ;
41- const { html } = mdsvx . default . render ( ) ;
42- /**
43- * This needs to match the function that adds the
44- * same data to Firestore
45- */
46- const content = {
47- ...mdsvx ?. metadata ,
48- cover : mdsvx ?. metadata ?. cover ? decodeURI ( mdsvx ?. metadata ?. cover ) : '' ,
49- type : type as ContentType ,
50- html,
51- weight : mdsvx ?. metadata ?. weight ? mdsvx ?. metadata ?. weight : 0 ,
52- published : mdsvx ?. metadata ?. published ? mdsvx ?. metadata ?. published : ContentPublished . draft ,
53- start : mdsvx ?. metadata ?. start ? new Date ( mdsvx ?. metadata ?. start ) : new Date ( 'Jan 01, 1900' ) ,
54- } ;
55- contentList . push ( content ) ;
56- } ) ;
17+ export const getContentTypeDirectory = async < T > ( contentType : ContentType , withCode = true ) => {
18+ const contentList : T [ ] = [ ] ;
19+
20+ // Normal Files
21+ let root = fileURLToPath ( new URL ( `../../routes/(content-single)/(non-course)/${ contentType } ` , import . meta. url ) ) ;
22+ if ( contentType === ContentType . course ) {
23+ root = fileURLToPath ( new URL ( `../../routes/(content-single)/${ contentType } ` , import . meta. url ) ) ;
24+ }
25+ const dirs = opendirSync ( root ) ;
26+ for await ( const dir of dirs ) {
27+ const parsed = await parseContentType ( `${ root } /${ dir . name } /+page.md` , withCode ) as T ;
28+ contentList . push ( parsed ) ;
5729 }
5830 return contentList ;
5931}
6032
61- export const parseLessonModules = async ( { lessonModules, courses } : { lessonModules : Record < string , ( ) => Promise < unknown > > , courses : Course [ ] } ) => {
62- for ( const path in lessonModules ) {
63- await lessonModules [ path ] ( ) . then ( ( mod ) => {
64- const splitPath = path . split ( '/' ) ;
65- const type = splitPath . at ( - 4 ) ;
66- const slug = splitPath . at ( - 3 ) ;
67- const lessonSlug = splitPath ?. at ( - 1 ) ?. replace ( / \. [ ^ / . ] + $ / , '' ) ;
68-
69- console . log ( `Precompiling Lesson: ${ type } /${ slug } /lesson/${ lessonSlug } ` ) ;
70-
71- if ( ! type || ! slug || ! lessonSlug ) {
72- console . error ( 'Lesson Param missing' ) ;
73- return ;
74- }
75-
76- const mdsvx = mod as {
77- default : {
78- render : ( ) => { html : string } ;
79- } ;
80- metadata : Lesson ;
81- } ;
82- const { html } = mdsvx . default . render ( ) ;
83- /**
84- * This needs to match the function that adds the
85- * same data to Firestore
86- */
87- const content = {
88- ...mdsvx ?. metadata ,
89- cover : mdsvx ?. metadata ?. cover ? decodeURI ( mdsvx ?. metadata ?. cover ) : '' ,
90- type : ContentType . lesson ,
91- courseSlug : slug ,
92- html,
93- weight : mdsvx ?. metadata ?. weight ? mdsvx ?. metadata ?. weight : 0 ,
94- published : mdsvx ?. metadata ?. published ? mdsvx ?. metadata ?. published : ContentPublished . draft ,
95- start : mdsvx ?. metadata ?. start ? new Date ( mdsvx ?. metadata ?. start ) : new Date ( 'Jan 01, 1900' ) ,
96- locked : mdsvx ?. metadata ?. locked || false ,
97- } ;
33+ export const parseContentType = ( async ( path : string , withCode = true ) => {
34+ const md = readFileSync ( path , 'utf8' ) ;
35+ const transformed = await compile ( md ) ;
36+ const frontmatter = transformed ?. data ?. fm as Content & Podcast | undefined ;
9837
99- courses
100- . filter ( ( c ) => c . slug === slug )
101- . map ( ( c ) => {
102- c ?. lesson ? c . lesson . push ( content ) : ( c [ 'lesson' ] = [ content ] ) ;
103- } ) ;
104- } ) ;
38+ // TODO: Add more checks?
39+
40+ if ( ! frontmatter ?. type ) {
41+ console . error ( 'Missing Frontmatter details' ) ;
42+ return ;
10543 }
106- return courses ;
107- }
44+
45+ return {
46+ ...frontmatter ,
47+ cover : frontmatter ?. cover ? decodeURI ( frontmatter ?. cover ) : '' ,
48+ type : frontmatter ?. type as ContentType ,
49+ html : withCode ? transformed ?. code : undefined ,
50+ weight : frontmatter ?. weight ? frontmatter ?. weight : 0 ,
51+ published : frontmatter ?. published ? frontmatter ?. published : ContentPublished . draft ,
52+ start : frontmatter ?. start ? new Date ( frontmatter ?. start ) : new Date ( 'Jan 01, 2000' ) ,
53+ } ;
54+ } )
55+
56+ // export const parseModules = async (modules: Record<string, () => Promise<unknown>>) => {
57+ // const contentList: Content[] = [];
58+ // for (const path in modules) {
59+ // await modules[path]().then((mod) => {
60+ // const splitPath = path.split('/');
61+ // const courseType = splitPath.at(-3);
62+ // const normalType = splitPath.at(-2);
63+ // const slug = splitPath.at(-1);
64+ // const type = courseType === 'content' ? normalType : courseType;
65+
66+ // if (courseType === 'content') {
67+ // console.log(`Precompiling: ${type}/${slug}`);
68+ // } else {
69+ // console.log(`Precompiling: ${type}/${normalType}`);
70+ // }
71+
72+ // if (!type || !slug) {
73+ // console.error('Missing name or type');
74+ // return;
75+ // }
76+
77+ // const mdsvx = mod as {
78+ // default: {
79+ // render: () => { html: string };
80+ // };
81+ // metadata: Content;
82+ // };
83+ // const { html } = mdsvx.default.render();
84+ // /**
85+ // * This needs to match the function that adds the
86+ // * same data to Firestore
87+ // */
88+ // const content = {
89+ // ...mdsvx?.metadata,
90+ // cover: mdsvx?.metadata?.cover ? decodeURI(mdsvx?.metadata?.cover) : '',
91+ // type: type as ContentType,
92+ // html,
93+ // weight: mdsvx?.metadata?.weight ? mdsvx?.metadata?.weight : 0,
94+ // published: mdsvx?.metadata?.published ? mdsvx?.metadata?.published : ContentPublished.draft,
95+ // start: mdsvx?.metadata?.start ? new Date(mdsvx?.metadata?.start) : new Date('Jan 01, 1900'),
96+ // };
97+ // contentList.push(content);
98+ // });
99+ // }
100+ // return contentList;
101+ // }
102+
103+ // export const parseLessonModules = async ({ lessonModules, courses }: { lessonModules: Record<string, () => Promise<unknown>>, courses: Course[] }) => {
104+ // for (const path in lessonModules) {
105+ // await lessonModules[path]().then((mod) => {
106+ // const splitPath = path.split('/');
107+ // const type = splitPath.at(-4);
108+ // const slug = splitPath.at(-3);
109+ // const lessonSlug = splitPath?.at(-1)?.replace(/\.[^/.]+$/, '');
110+
111+ // console.log(`Precompiling Lesson: ${type}/${slug}/lesson/${lessonSlug}`);
112+
113+ // if (!type || !slug || !lessonSlug) {
114+ // console.error('Lesson Param missing');
115+ // return;
116+ // }
117+
118+ // const mdsvx = mod as {
119+ // default: {
120+ // render: () => { html: string };
121+ // };
122+ // metadata: Lesson;
123+ // };
124+ // const { html } = mdsvx.default.render();
125+ // /**
126+ // * This needs to match the function that adds the
127+ // * same data to Firestore
128+ // */
129+ // const content = {
130+ // ...mdsvx?.metadata,
131+ // cover: mdsvx?.metadata?.cover ? decodeURI(mdsvx?.metadata?.cover) : '',
132+ // type: ContentType.lesson,
133+ // courseSlug: slug,
134+ // html,
135+ // weight: mdsvx?.metadata?.weight ? mdsvx?.metadata?.weight : 0,
136+ // published: mdsvx?.metadata?.published ? mdsvx?.metadata?.published : ContentPublished.draft,
137+ // start: mdsvx?.metadata?.start ? new Date(mdsvx?.metadata?.start) : new Date('Jan 01, 1900'),
138+ // locked: mdsvx?.metadata?.locked || false,
139+ // };
140+
141+ // courses
142+ // .filter((c) => c.slug === slug)
143+ // .map((c) => {
144+ // c?.lesson ? c.lesson.push(content) : (c['lesson'] = [content]);
145+ // });
146+ // });
147+ // }
148+ // return courses;
149+ // }
108150
109151
110152/**
111153 * List all content from specified content type
112154 * allows for optionally sending after object
113155 * */
114- export const listContent = async ( {
156+ export const listContent = async < T extends Content > ( {
115157 contentItems,
116158 after,
117159 limit,
118160 contentFilter = ( c ) => c . published === ContentPublished . published
119161} : {
120- contentItems : Content [ ] ;
162+ contentItems : T [ ]
121163 after ?: number ;
122164 limit ?: number ;
123165 contentFilter ?: ( c : Content ) => boolean ;
@@ -127,6 +169,10 @@ export const listContent = async ({
127169
128170 console . log ( `List limit of ${ theLimit } ` ) ;
129171
172+ for ( const c of contentItems ) {
173+ console . log ( c ?. title )
174+ }
175+
130176 const fullContent = contentItems
131177 . filter ( preview ? ( ) => true : contentFilter )
132178 . sort ( ( a , b ) => new Date ( b . start ) . valueOf ( ) - new Date ( a . start ) . valueOf ( ) ) ;
0 commit comments