mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
feat(plantuml): add cache supports
This commit is contained in:
@@ -23,6 +23,8 @@ export const USER_DATA = path.join(USER_DIR, './data')
|
||||
export const BIN_DIR = convertAppPath(path.join(__dirname, '../../bin'))
|
||||
export const RESOURCES_DIR = convertAppPath(path.join(__dirname, 'resources'))
|
||||
|
||||
export const CACHE_DIR = path.join(os.tmpdir(), APP_NAME)
|
||||
|
||||
export const BUILD_IN_STYLES = ['github.css']
|
||||
|
||||
export const PANDOC_REFERENCE_FILE = 'pandoc-reference.docx'
|
||||
|
||||
+84
-21
@@ -1,11 +1,12 @@
|
||||
import request from 'request'
|
||||
import fs from 'fs'
|
||||
import * as crypto from 'crypto'
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import pako from 'pako'
|
||||
import { PlantUmlPipe } from 'plantuml-pipe'
|
||||
import commandExists from 'command-exists'
|
||||
import config from '../config'
|
||||
import { ASSETS_DIR, BIN_DIR } from '../constant'
|
||||
import { ASSETS_DIR, BIN_DIR, CACHE_DIR } from '../constant'
|
||||
import { getAction } from '../action'
|
||||
|
||||
function plantumlBase64 (base64: string) {
|
||||
@@ -14,9 +15,57 @@ function plantumlBase64 (base64: string) {
|
||||
return base64.split('').map(x => map[x] || '').join('')
|
||||
}
|
||||
|
||||
export default async function (data: string): Promise<{ content: any, type: string }> {
|
||||
const code = pako.inflateRaw(Buffer.from(data, 'base64'))
|
||||
function getCacheKey (api: string, type: string, data: string) {
|
||||
return crypto.createHash('sha256').update(api + type + data).digest('hex')
|
||||
}
|
||||
|
||||
async function gcCache (cacheDir: string) {
|
||||
const files = await fs.readdir(cacheDir)
|
||||
if (files.length < 4000) {
|
||||
return
|
||||
}
|
||||
|
||||
const stats = await Promise.all(files.map(file => fs.stat(path.join(cacheDir, file))))
|
||||
stats.sort((a, b) => a.atimeMs - b.atimeMs)
|
||||
|
||||
for (let i = 0; i < stats.length / 2; i++) {
|
||||
await fs.remove(path.join(cacheDir, files[i]))
|
||||
}
|
||||
}
|
||||
|
||||
async function getCacheData (key: string, gen: () => Promise<any>) {
|
||||
const cacheDir = path.join(CACHE_DIR, 'plantuml')
|
||||
await fs.ensureDir(cacheDir)
|
||||
|
||||
gcCache(cacheDir)
|
||||
|
||||
const cacheFile = path.join(cacheDir, key)
|
||||
if (await fs.pathExists(cacheFile)) {
|
||||
const stat = await fs.stat(cacheFile)
|
||||
if (stat.size) {
|
||||
return fs.createReadStream(cacheFile)
|
||||
}
|
||||
}
|
||||
|
||||
const data = await gen()
|
||||
if (!data) {
|
||||
throw new Error('No data')
|
||||
}
|
||||
|
||||
if (typeof data.pipe === 'function') {
|
||||
await new Promise((resolve, reject) => {
|
||||
data.on('end', resolve)
|
||||
data.on('error', reject)
|
||||
data.pipe(fs.createWriteStream(cacheFile))
|
||||
})
|
||||
return fs.createReadStream(cacheFile)
|
||||
} else {
|
||||
await fs.writeFile(cacheFile, data)
|
||||
return fs.createReadStream(cacheFile)
|
||||
}
|
||||
}
|
||||
|
||||
export default async function (data: string): Promise<{ content: any, type: string }> {
|
||||
const api: string = config.get('plantuml-api', 'local')
|
||||
|
||||
if (api.startsWith('local')) {
|
||||
@@ -28,30 +77,44 @@ export default async function (data: string): Promise<{ content: any, type: stri
|
||||
|
||||
const format = api.split('-')[1] || 'png'
|
||||
const type = format === 'png' ? 'image/png' : 'image/svg+xml'
|
||||
const jarPath = path.join(BIN_DIR, 'plantuml.jar')
|
||||
|
||||
const puml = new PlantUmlPipe({
|
||||
split: format === 'svg',
|
||||
outputFormat: format as 'png' | 'svg',
|
||||
plantUmlArgs: ['-charset', 'UTF-8'],
|
||||
jarPath,
|
||||
const cacheKey = getCacheKey(api, type, data)
|
||||
const content = await getCacheData(cacheKey, async () => {
|
||||
const jarPath = path.join(BIN_DIR, 'plantuml.jar')
|
||||
|
||||
const puml = new PlantUmlPipe({
|
||||
split: format === 'svg',
|
||||
outputFormat: format as 'png' | 'svg',
|
||||
plantUmlArgs: ['-charset', 'UTF-8'],
|
||||
jarPath,
|
||||
})
|
||||
|
||||
puml.in.write(pako.inflateRaw(Buffer.from(data, 'base64')))
|
||||
puml.in.end()
|
||||
|
||||
return puml.out
|
||||
})
|
||||
|
||||
puml.in.write(code)
|
||||
puml.in.end()
|
||||
|
||||
return { content: puml.out, type }
|
||||
return { content, type }
|
||||
} else {
|
||||
const url = api.replace('{data}', plantumlBase64(data))
|
||||
const agent = await getAction('get-proxy-agent')(url)
|
||||
return new Promise((resolve, reject) => {
|
||||
request({ agent, url, encoding: null }, function (err: any, res: any) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve({ content: res.body, type: res.headers['content-type'] })
|
||||
}
|
||||
let type = ''
|
||||
|
||||
const cacheKey = getCacheKey(api, type, data)
|
||||
const content = await getCacheData(cacheKey, async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
request({ agent, url, encoding: null }, function (err: any, res: any) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
type = res.headers['content-type']
|
||||
resolve(res.body)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return { content, type }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user