Skip to content

Commit

Permalink
Merge commit '6470701f7b503bbe71704f95fbae80ac1a37f49d'
Browse files Browse the repository at this point in the history
  • Loading branch information
2234839 committed Jan 1, 2024
2 parents 8075473 + 6470701 commit af72c80
Show file tree
Hide file tree
Showing 19 changed files with 518 additions and 180 deletions.
10 changes: 8 additions & 2 deletions apps/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@
<title>OceanPress</title>
<meta name="description" content="这是一款从思源笔记本 生成一个静态站点的工具" />
<meta property="og:description" content="这是一款从思源笔记本 生成一个静态站点的工具" />
<script type="text/javascript">
// https://clarity.microsoft.com 站点分析
(function (c, l, a, r, i, t, y) {
c[ a ] = c[ a ] || function () { (c[ a ].q = c[ a ].q || []).push(arguments) }
t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i
y = l.getElementsByTagName(r)[ 0 ]; y.parentNode.insertBefore(t, y)
})(window, document, "clarity", "script", "kdd1bzgo7w");
</script>
</head>

<body>
<div id="app"></div>
<script type="module" src="./src/webpage.ts"></script>
Expand All @@ -21,5 +28,4 @@
padding: 0 10px;
}
</style>

</html>
5 changes: 3 additions & 2 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "0.0.8",
"version": "0.0.9",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -14,10 +14,11 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.478.0",
"@hono/node-server": "^1.3.3",
"cheerio": "^1.0.0-rc.12",
"cheerio": "1.0.0-rc.12",
"commander": "^11.1.0",
"hono": "^3.11.8",
"jszip": "^3.10.1",
"meilisearch": "^0.36.0",
"octokit": "^3.1.2",
"tsx": "^4.6.2",
"vditor": "^3.9.5",
Expand Down
92 changes: 43 additions & 49 deletions apps/frontend/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { mkdir, readFile, writeFile } from 'fs/promises'
import { resolve } from 'path'
import { join } from 'path/posix'
import { currentConfig, loadConfigFile } from './core/config.ts'
import { build } from './core/build.ts'
import { setCache } from './core/cache.ts'
import { server } from './server.ts'
import { s3_uploads } from './publish/s3.ts'
import { OceanPress } from './core/ocean_press.ts'
const program = new Command()
console.log(process.argv)

Expand All @@ -21,60 +20,55 @@ program
.description('输出静态站点源码')
.option('-c, --config <string>', '指定配置文件的位置')
.option('-o, --output <string>', '指定输出目录位置')
.option('--publish_s3 <boolean>', '指定输出目录位置', false)
.action(
async (opt: { config: string; output: string; publish_s3: boolean }) => {
if (!opt.config || !opt.output) {
console.log(`请设置配置文件位置和输出目录位置`)
}
const config = await readFile(opt.config, 'utf-8')
loadConfigFile(JSON.parse(config))
const filePath = resolve(opt.output)
const res = build(currentConfig.value, {
onFileTree: async (tree) => {
for (const [path, data] of Object.entries(tree)) {
const fullPath = join(filePath, './', path)
const pathArray = fullPath.split('/').slice(0, -1)
const dirPath = pathArray.join('/')
mkdir(dirPath, { recursive: true })
try {
if (typeof data === 'string') {
await writeFile(fullPath, data, 'utf-8')
} else {
await writeFile(fullPath, new DataView(data))
}
} catch (error) {
console.log(`${fullPath} 无法写入`)
}
}
if (opt.publish_s3) {
const uploads = s3_uploads(tree, currentConfig.value)
for await (const [path, r] of uploads) {
console.log(`上传:${path} eTag:${r} `)
.action(async (opt: { config: string; output: string }) => {
if (!opt.config || !opt.output) {
console.log(`请设置配置文件位置和输出目录位置`)
throw new Error('请设置配置文件位置和输出目录位置')
}
const config = await readFile(opt.config, 'utf-8')
loadConfigFile(JSON.parse(config))
const filePath = resolve(opt.output)
const ocean_press = new OceanPress(currentConfig.value)
const res = await ocean_press.build()
// node 端写磁盘插件
ocean_press.pluginCenter.registerPlugin({
async build_onFileTree([tree]) {
for (const [path, data] of Object.entries(tree)) {
const fullPath = join(filePath, './', path)
const pathArray = fullPath.split('/').slice(0, -1)
const dirPath = pathArray.join('/')
mkdir(dirPath, { recursive: true })
try {
if (typeof data === 'string') {
await writeFile(fullPath, data, 'utf-8')
} else {
await writeFile(fullPath, new DataView(data))
}
console.log('上传完毕')
} catch (error) {
console.log(`${fullPath} 无法写入`)
}
},
})
const obj = (await res.next()).value
if (typeof obj === 'object' && !(obj instanceof Error)) {
obj.log = (...arg) => {
console.log(...arg)
}
},
})

const obj = (await res.next()).value
if (typeof obj === 'object' && !(obj instanceof Error)) {
obj.log = (...arg) => {
console.log(...arg)
}
for await (const iterator of res) {
if (typeof iterator === 'string') {
if (iterator.startsWith('渲染:')) {
process.stdout.write(`\r\x1b[K${iterator}`)
} else {
process.stdout.write(`\n${iterator}`)
}
}
for await (const iterator of res) {
if (typeof iterator === 'string') {
if (iterator.startsWith('渲染:')) {
process.stdout.write(`\r\x1b[K${iterator}`)
} else {
console.log(iterator + '\n')
process.stdout.write(`\n${iterator}`)
}
} else {
console.log(iterator + '\n')
}
},
)
}
})

program
.command('server')
Expand Down
57 changes: 7 additions & 50 deletions apps/frontend/src/core/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ export interface DocTree {
export interface FileTree {
[path: string]: string | ArrayBuffer
}

export type Build = typeof build
/** 根据配置文件进行编译
* TODO 将浏览器写文件的部分抽离出去,也改成使用 onFileTree
*/
export async function* build(
config: Config,
otherConfig?: {
/** 实验性api https://github.com/WICG/file-system-access/blob/main/EXPLAINER.md */
dir_ref?: any
// 监听文件准备完毕 TODO:应该修改实现,而非目前直接全量加载到内存
onFileTree?: (tree: FileTree) => void
renderHtmlFn?: typeof renderHTML
},
) {
const _renderHTML = otherConfig?.renderHtmlFn ?? renderHTML
const book = config.notebook
const docTree: DocTree = {}
const skipBuilds = useSkipBuilds()
Expand Down Expand Up @@ -123,10 +123,11 @@ export async function* build(
path.split('/').length -
2 /** 最开头有一个 / 还有一个 data 目录所以减二 */
const renderInstance = getRender()

fileTree[path + '.html'] = await htmlTemplate(
{
title: sy.Properties?.title || '',
htmlContent: await renderHTML(sy, renderInstance),
htmlContent: await _renderHTML(sy, renderInstance),
level: rootLevel,
},
{
Expand Down Expand Up @@ -263,10 +264,9 @@ ${(
] as string
if (
config.enableIncrementalCompilation &&
/** 资源没有变化,直接跳过 */
config.__skipBuilds__[widget.ID]?.updated === update
) {
return /** skip */
return /** 资源没有变化,直接跳过 */
} else {
const id = widget.ID
// 快照保存的位置 `/data/storage/oceanpress/widget_img/${id}.jpg`
Expand All @@ -282,16 +282,13 @@ ${(
}

// === 输出编译成果 ===
if (otherConfig?.dir_ref) {
yield `=== 开始写文件到磁盘 ===`
await writeFileSystem(fileTree, otherConfig.dir_ref)
}
if (otherConfig?.onFileTree) {
otherConfig.onFileTree(fileTree)
}
if (config.compressedZip) {
yield `=== 开始生成压缩包 ===`
await downloadZIP(fileTree, {
// TODO 这里应该移出来成为全局的写选项
withoutZip: config.withoutPublicZip,
publicZip: config.cdn.publicZip,
})
Expand Down Expand Up @@ -330,46 +327,6 @@ export async function downloadZIP(
console.error(error)
})
}

/** chrome系高版本可用 */
async function writeFileSystem(
fileTree: { [htmlPath: string]: string | ArrayBuffer },
dir_ref: any,
) {
/** 并发写文件 */
await Promise.all(
Object.entries(fileTree).map(async ([path, html]) => {
await writeFile(dir_ref, path, html).catch((e) => {
console.log(e, dir_ref)
})
}),
)
async function writeFile(
dir_ref: any,
name: string,
data: string | ArrayBuffer,
) {
const pathArr = name.split('/')
/** 如果路径中的目录不存在则创建 */
if (pathArr.length > 1) {
for (let i = 0; i < pathArr.length - 1; i++) {
const dirName = pathArr[i]
if (dirName === '') {
continue
}
dir_ref = await dir_ref.getDirectoryHandle(dirName, { create: true })
}
}
/** 写文件 */
const new_file = await dir_ref.getFileHandle(pathArr[pathArr.length - 1], {
create: true,
})
const new_file_writer = await new_file.createWritable()
await new_file_writer.write(data)
await new_file_writer.close()
}
}

function sitemap_xml(
docArr: DB_block[],
config: {
Expand Down
7 changes: 7 additions & 0 deletions apps/frontend/src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,20 @@ const defaultConfig = {
* https://help.aliyun.com/zh/oss/developer-reference/use-amazon-s3-sdks-to-access-oss#section-2ri-suq-pb3
*/
s3: {
enable: false,
bucket: '',
region: '',
pathPrefix: '',
endpoint: '',
accessKeyId: '',
secretAccessKey: '',
},
meilisearch: {
enable: false,
host: '',
apiKey: '',
indexName: '',
},
/** html模板嵌入代码块,会将此处配置中的代码嵌入到生成的html所对应的位置 */
embedCode: {
head: '',
Expand Down
40 changes: 40 additions & 0 deletions apps/frontend/src/core/ocean_press.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { MeilisearchPlugin } from '~/plugins/meilisearch_plugin/meilisearch_upload.ts'
import { Config } from './config.ts'
import { PluginCenter } from './plugin.ts'
import { s3Upload_plugin } from '~/plugins/publish/s3.ts'
import { FileTree, build } from './build.ts'
import { renderHTML } from './render.ts'

export type OceanPressPlugin = PluginCenter<OceanPress['funMap']>['pluginType']

export class OceanPress {
async build() {
const build_res = this.pluginCenter.fun.build(this.config, {
renderHtmlFn: this.pluginCenter.fun.build_renderHTML,
onFileTree: this.pluginCenter.fun.build_onFileTree,
})
return build_res
}
funMap = {
/** 开始整体编译 */
build,
/** 用于渲染文档的函数 */
build_renderHTML: renderHTML,
/** 编译完成后文件树的处理回调函数 */
build_onFileTree: (_tree: FileTree) => {},
}
pluginCenter: PluginCenter<OceanPress['funMap']> = new PluginCenter(
this.funMap,
)
constructor(public config: Config) {
// TODO 内置插件,以后应该改成由用户配置
if (config.meilisearch.enable) {
this.pluginCenter.registerPlugin(
new MeilisearchPlugin(config.meilisearch),
)
}
if (config.s3.enable) {
this.pluginCenter.registerPlugin(new s3Upload_plugin())
}
}
}
Loading

0 comments on commit af72c80

Please sign in to comment.