diff --git a/Build/build-public.ts b/Build/build-public.ts index ee890237..0e0c57fe 100644 --- a/Build/build-public.ts +++ b/Build/build-public.ts @@ -1,7 +1,8 @@ -import listDir from '@sukka/listdir'; import path from 'path'; import fsp from 'fs/promises'; import { task } from './lib/trace-runner'; +import { listDir } from './lib/list-dir'; +import type { TreeType, TreeTypeArray } from './lib/list-dir'; const rootPath = path.resolve(import.meta.dir, '../'); const publicPath = path.resolve(import.meta.dir, '../public'); @@ -15,7 +16,7 @@ const folderAndFilesToBeDeployed = [ 'LICENSE' ]; -export const buildPublicHtml = task(import.meta.path, async () => { +export const buildPublic = task(import.meta.path, async () => { await fsp.mkdir(publicPath, { recursive: true }); await Promise.all(folderAndFilesToBeDeployed.map(dir => fsp.cp( path.resolve(rootPath, dir), @@ -23,24 +24,37 @@ export const buildPublicHtml = task(import.meta.path, async () => { { force: true, recursive: true } ))); - const list = await listDir(publicPath, { - ignoreHidden: true, - ignorePattern: /node_modules|Build|.DS_Store|\.(json|html|md|js)|LICENSE/ - }); + const tree = await listDir(publicPath); - const html = template(list); + const html = generateHtml(tree); return Bun.write(path.join(publicPath, 'index.html'), html); }); if (import.meta.main) { - buildPublicHtml(); + buildPublic(); } -function template(urlList: string[]) { - return ` - +const priorityOrder: Record<'default' | string & {}, number> = { + domainset: 1, + non_ip: 2, + ip: 3, + List: 10, + Surge: 11, + Clash: 12, + Modules: 13, + Script: 14, + Mock: 15, + Assets: 16, + LICENSE: 20, + default: Number.MAX_VALUE +}; +const prioritySorter = (a: TreeType, b: TreeType) => (priorityOrder[a.name] || priorityOrder.default) - (priorityOrder[b.name] || priorityOrder.default) || +(a.name > b.name) || -(a.name < b.name); + +function generateHtml(tree: TreeTypeArray) { + let html = ` + Surge Ruleset Server | Sukka (@SukkaW) @@ -51,27 +65,51 @@ function template(urlList: string[]) { + + + - + - - - -
-

Sukka Surge Ruleset Server

-

Made by Sukka | Source @ GitHub | Licensed under AGPL-3.0

-

Last Build: ${new Date().toISOString()}

-
-
- -
+ `; + + html += ` +
+

Sukka Ruleset Server

+

+ Made by Sukka | Source @ GitHub | Licensed under AGPL-3.0 +

+

Last Build: 2023-12-03T16:54:15.820Z

+
`; + + html += ''; + + html += `
- - `; + `; + + return html; } diff --git a/Build/download-previous-build.ts b/Build/download-previous-build.ts index 22fca9ac..436f079c 100644 --- a/Build/download-previous-build.ts +++ b/Build/download-previous-build.ts @@ -44,7 +44,7 @@ export const downloadPreviousBuild = task(import.meta.path, async () => { if (flag & ALL_FILES_EXISTS) { console.log('All files exists, skip download.'); - // return; + return; } const extractedPath = path.join(os.tmpdir(), `sukka-surge-last-build-extracted-${Date.now()}`); diff --git a/Build/index.ts b/Build/index.ts index aa6c91b5..d8597e4b 100644 --- a/Build/index.ts +++ b/Build/index.ts @@ -14,7 +14,7 @@ import { buildStreamService } from './build-stream-service'; import { buildRedirectModule } from './build-redirect-module'; import { validate } from './validate-domainset'; -import { buildPublicHtml } from './build-public'; +import { buildPublic } from './build-public'; // import type { TaskResult } from './lib/trace-runner'; (async () => { @@ -84,7 +84,7 @@ import { buildPublicHtml } from './build-public'; ]); await Promise.all([ - buildPublicHtml(), + buildPublic(), validate() ]); diff --git a/Build/lib/create-file.ts b/Build/lib/create-file.ts index 31468d61..82400724 100644 --- a/Build/lib/create-file.ts +++ b/Build/lib/create-file.ts @@ -68,7 +68,6 @@ export async function compareAndWriteFile(linesA: string[], filePath: string) { writer.write('\n'); } - await writer.flush(); return writer.end(); }, picocolors.gray); } diff --git a/Build/lib/list-dir.ts b/Build/lib/list-dir.ts new file mode 100644 index 00000000..69612c39 --- /dev/null +++ b/Build/lib/list-dir.ts @@ -0,0 +1,57 @@ +import type { Path } from 'path-scurry'; +import { PathScurry } from 'path-scurry'; + +interface TreeFileType { + type: 'file', + name: string, + path: string +} + +interface TreeDirectoryType { + type: 'directory', + name: string, + path: string, + children: TreeTypeArray +} + +export type TreeType = TreeDirectoryType | TreeFileType; +export type TreeTypeArray = TreeType[]; + +type VoidOrVoidArray = void | VoidOrVoidArray[]; + +export const listDir = async (path: string): Promise => { + const pw = new PathScurry(path); + + const tree: TreeTypeArray = []; + + const walk = async (entry: Path, node: TreeTypeArray): Promise => { + const promises: Array> = []; + for (const child of await pw.readdir(entry)) { + if (child.isDirectory()) { + const newNode: TreeDirectoryType = { + type: 'directory', + name: child.name, + path: child.relative(), + children: [] + }; + node.push(newNode); + promises.push(walk(child, newNode.children)); + continue; + } + if (child.isFile()) { + const newNode: TreeFileType = { + type: 'file', + name: child.name, + path: child.relative() + }; + node.push(newNode); + continue; + } + } + return Promise.all(promises); + }; + + await walk(pw.cwd, tree); + + return tree; +};