fix: catch all error in text macro replace
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { marked } from 'marked'
|
||||
|
||||
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common'
|
||||
|
||||
import { deepCloneWithFunction } from '~/utils'
|
||||
import { safeEval } from '~/utils/safe-eval.util'
|
||||
|
||||
@Injectable()
|
||||
export class TextMacroService {
|
||||
private readonly logger: Logger
|
||||
constructor() {
|
||||
this.logger = new Logger(TextMacroService.name)
|
||||
}
|
||||
static readonly Reg = {
|
||||
'#': /^#(.*?)$/g,
|
||||
$: /^\$(.*?)$/g,
|
||||
@@ -66,59 +70,64 @@ export class TextMacroService {
|
||||
text: string,
|
||||
model: T,
|
||||
): Promise<string> {
|
||||
const matchedReg = /\[\[\s(.*?)\s\]\]/g
|
||||
if (text.search(matchedReg) != -1) {
|
||||
text = text.replace(matchedReg, (match, condition) => {
|
||||
const ast = marked.lexer(text)
|
||||
try {
|
||||
const matchedReg = /\[\[\s(.*?)\s\]\]/g
|
||||
if (text.search(matchedReg) != -1) {
|
||||
text = text.replace(matchedReg, (match, condition) => {
|
||||
const ast = marked.lexer(text)
|
||||
|
||||
// FIXME: shallow find, if same text both in code block and paragraph, the macro in paragraph also will not replace
|
||||
const isInCodeBlock = ast.some((i) => {
|
||||
if (i.type === 'code' || i.type === 'codespan') {
|
||||
return i.raw.includes(condition)
|
||||
}
|
||||
})
|
||||
// FIXME: shallow find, if same text both in code block and paragraph, the macro in paragraph also will not replace
|
||||
const isInCodeBlock = ast.some((i) => {
|
||||
if (i.type === 'code' || i.type === 'codespan') {
|
||||
return i.raw.includes(condition)
|
||||
}
|
||||
})
|
||||
|
||||
if (isInCodeBlock) {
|
||||
return match
|
||||
}
|
||||
|
||||
condition = condition?.trim()
|
||||
if (condition.search(TextMacroService.Reg['?']) != -1) {
|
||||
return this.ifConditionGrammar(condition, model)
|
||||
}
|
||||
if (condition.search(TextMacroService.Reg['$']) != -1) {
|
||||
const variable = condition
|
||||
.replace(TextMacroService.Reg['$'], '$1')
|
||||
.replace(/\s/g, '')
|
||||
return model[variable]
|
||||
}
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
if (condition.search(TextMacroService.Reg['#']) != -1) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const functions = condition.replace(TextMacroService.Reg['#'], '$1')
|
||||
|
||||
const variables = Object.keys(model).reduce(
|
||||
(acc, key) => ({ [`$${key}`]: model[key], ...acc }),
|
||||
{},
|
||||
)
|
||||
|
||||
try {
|
||||
return safeEval(
|
||||
`return ${functions}`,
|
||||
{
|
||||
dayjs: deepCloneWithFunction(dayjs),
|
||||
fromNow: (time: Date | string) => dayjs(time).fromNow(),
|
||||
|
||||
...variables,
|
||||
},
|
||||
{ timeout: 1000 },
|
||||
)
|
||||
} catch {
|
||||
if (isInCodeBlock) {
|
||||
return match
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
condition = condition?.trim()
|
||||
if (condition.search(TextMacroService.Reg['?']) != -1) {
|
||||
return this.ifConditionGrammar(condition, model)
|
||||
}
|
||||
if (condition.search(TextMacroService.Reg['$']) != -1) {
|
||||
const variable = condition
|
||||
.replace(TextMacroService.Reg['$'], '$1')
|
||||
.replace(/\s/g, '')
|
||||
return model[variable]
|
||||
}
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
if (condition.search(TextMacroService.Reg['#']) != -1) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const functions = condition.replace(TextMacroService.Reg['#'], '$1')
|
||||
|
||||
const variables = Object.keys(model).reduce(
|
||||
(acc, key) => ({ [`$${key}`]: model[key], ...acc }),
|
||||
{},
|
||||
)
|
||||
|
||||
try {
|
||||
return safeEval(
|
||||
`return ${functions}`,
|
||||
{
|
||||
dayjs: deepCloneWithFunction(dayjs),
|
||||
fromNow: (time: Date | string) => dayjs(time).fromNow(),
|
||||
|
||||
...variables,
|
||||
},
|
||||
{ timeout: 1000 },
|
||||
)
|
||||
} catch {
|
||||
return match
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return text
|
||||
} catch (err) {
|
||||
this.logger.log(err.message)
|
||||
return text
|
||||
}
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user