-
Notifications
You must be signed in to change notification settings - Fork 251
Expand file tree
/
Copy pathcontentFolderPlugin.ts
More file actions
151 lines (141 loc) · 4.9 KB
/
contentFolderPlugin.ts
File metadata and controls
151 lines (141 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import { lstatSync, readdir, readFileSync } from 'fs';
import { basename, extname, join } from 'path';
import {
AlternateExtensionsForFilePlugin,
FilePlugin,
plugins,
registerPlugin,
} from '../pluginManagement/pluginRepository';
import { readFileAndCheckPrePublishSlug } from '../renderPlugins/content-render-utils/readFileAndCheckPrePublishSlug';
import { scullyConfig } from '../utils/config';
import { RouteTypeContentFolder } from '../utils/interfacesandenums';
import { log, logWarn, yellow } from '../utils/log';
import { HandledRoute } from './addOptionalRoutesPlugin';
import { Extension } from 'typescript';
let basePath: string;
export async function contentFolderPlugin(
angularRoute: string,
conf: RouteTypeContentFolder
): Promise<HandledRoute[]> {
const parts = angularRoute.split('/');
/** for now, just handle the First parameter. Not sure if/how we can handle multiple ones. */
const param = parts
.filter((p) => p.startsWith(':'))
.map((id) => id.slice(1))[0];
const paramConfig = conf[param];
if (!paramConfig) {
console.error(
`missing config for parameters (${param}) in route: ${angularRoute}. Skipping`
);
return [];
}
const baseRoute = angularRoute.split(':' + param)[0];
basePath = join(scullyConfig.homeFolder, paramConfig.folder);
log(`Finding files in folder "${yellow(basePath)}"`);
return await checkSourceIsDirectoryAndRun(basePath, baseRoute, conf);
}
async function checkSourceIsDirectoryAndRun(path, baseRoute, conf) {
const files = await new Promise<string[]>((resolve) =>
readdir(path, (err, data) => resolve(data))
);
const handledRoutes: HandledRoute[] = [];
for (const sourceFile of files) {
const ext = extname(sourceFile);
// const ext = sourceFile.split('.').pop();
const templateFile = join(path, sourceFile);
if (lstatSync(templateFile).isDirectory()) {
handledRoutes.push(
...(await checkSourceIsDirectoryAndRun(templateFile, baseRoute, conf))
);
} else {
if (checkIfEmpty(templateFile)) {
logWarn(
`The file ${yellow(templateFile)} is empty, scully will ignore.`
);
} else if (!hasContentPlugin(ext)) {
logWarn(
`The file ${yellow(templateFile)} has extension ${yellow(
ext
)} that has no plugin defined, scully will skip this file.`
);
} else {
handledRoutes.push(
...(await addHandleRoutes(
sourceFile,
baseRoute,
templateFile,
conf,
ext
))
);
}
}
}
return handledRoutes;
}
function hasContentPlugin(extension: string) {
const availAblePlugins = plugins.fileHandler;
extension = extension.toLowerCase().trim();
extension = extension.startsWith('.') ? extension.slice(1) : extension;
return (
Object.entries(availAblePlugins).find(
([name, plugin]: [string, FilePlugin]) =>
extension === name.toLowerCase() ||
(Array.isArray(plugin[AlternateExtensionsForFilePlugin]) &&
plugin[AlternateExtensionsForFilePlugin].includes(extension))
) !== undefined
);
}
function checkIfEmpty(templateFile: string) {
try {
const file = readFileSync(templateFile).toString();
return file.length === 0 ? true : false;
} catch (e) {
return false;
}
}
async function addHandleRoutes(sourceFile, baseRoute, templateFile, conf, ext) {
const handledRoutes = [];
const base = basename(sourceFile, ext);
// if a subfolder we need add a route for this folder
let routify = (frag) => `${baseRoute}${slugify(frag)}`;
// replace \ for / for windows
const newTemplateFile = templateFile.split('\\').join('/');
if (!newTemplateFile.endsWith(`${basePath}/${sourceFile}`)) {
/** get the 'path' part of as a route partial */
const routePartial = newTemplateFile
.substr(basePath.length + 1)
.replace(sourceFile, '');
routify = (frag) => `${baseRoute}${routePartial}${slugify(frag)}`;
}
const { meta, prePublished } = await readFileAndCheckPrePublishSlug(
templateFile
);
const name = conf.name;
const handledRoute: HandledRoute = {
route: routify(meta.slug || base),
type: conf.type,
templateFile,
data: { name, ...meta, sourceFile },
};
handledRoutes.push(handledRoute);
if (!prePublished && Array.isArray(meta.slugs)) {
/** also add routes for all available slugs */
meta.slugs
.filter((slug) => typeof slug === 'string')
.map(routify)
.forEach((route) => handledRoutes.push({ ...handledRoute, route }));
}
return handledRoutes;
}
export function slugify(frag: string): string {
return encodeURIComponent(
frag.trim().split('/').join('_').split(' ').join('_').split('?').join('_')
);
}
// TODO actual validation of the config
const configValidator = async (conf) => {
// return [yellow('all seems ok')];
return [];
};
registerPlugin('router', 'contentFolder', contentFolderPlugin, configValidator);