Browse Source

style(markdown): add commented styles for code blocks and update markdown configuration

- Added commented-out styles for code blocks to enhance presentation and usability.
- Updated markdown configuration to disable HTML rendering for improved security.
- Introduced a function to handle path not found errors in the error logger for better error management.

These changes prepare the codebase for future enhancements in markdown rendering and error handling.
main
npmrun 3 weeks ago
parent
commit
8320768f1d
  1. 45
      app/assets/scss/common.scss
  2. 3
      app/components/PostBodyMarkdownEditor.vue
  3. 42
      app/utils/render-markdown.ts
  4. BIN
      packages/drizzle-pkg/db.sqlite
  5. 32
      server/plugins/03.error-logger.ts

45
app/assets/scss/common.scss

@ -1,2 +1,45 @@
@use "./markdown/reset.scss";
@use "./markdown/green.scss";
@use "./markdown/green.scss";
// .code-block-wrapper {
// position: relative;
// margin: 16px 0;
// border-radius: 8px;
// background: #1e1e1e;
// overflow: hidden;
// }
// .code-header {
// display: flex;
// justify-content: space-between;
// align-items: center;
// padding: 8px 12px;
// background: #2d2d2d;
// color: #ccc;
// font-size: 14px;
// }
// .code-lang {
// font-weight: 600;
// text-transform: uppercase;
// }
// .copy-btn {
// padding: 4px 8px;
// border: none;
// border-radius: 4px;
// background: #444;
// color: #fff;
// cursor: pointer;
// font-size: 12px;
// transition: all 0.2s;
// }
// .copy-btn:hover {
// background: #555;
// }
// pre {
// margin: 0;
// padding: 12px;
// overflow-x: auto;
// }
// code {
// color: #d4d4d4;
// font-family: 'Consolas', 'Monaco', monospace;
// }

3
app/components/PostBodyMarkdownEditor.vue

@ -28,6 +28,9 @@ function ensureMdEditorStripFrontMatter() {
mdEditorGlobalConfig({
markdownItConfig(md) {
attachMarkdownItStripFrontMatter(md, 'person_panel_strip_fm')
md.set({
html: false
})
},
})
}

42
app/utils/render-markdown.ts

@ -7,8 +7,50 @@ const md = new MarkdownIt({
linkify: true,
typographer: false,
breaks: true,
// // 开启代码块语言识别
// highlight: function (str: string, lang: string) {
// // 处理语言标签(如果没有指定语言,默认 text)
// const language = lang || 'text'
// // 生成带语言标识 + 复制按钮的代码块外壳
// return `
// <div class="code-block-wrapper">
// <div class="code-header">
// <span class="code-lang">${language}</span>
// <button class="copy-btn" onclick="copyCode(this)">复制</button>
// </div>
// <pre><code class="language-${language}">${md.utils.escapeHtml(str)}</code></pre>
// </div>
// `
// },
})
// /** 全局复制代码函数(挂载到 window,确保页面可调用) */
// declare global {
// interface Window {
// copyCode: (btn: HTMLButtonElement) => void
// }
// }
// // 只在客户端环境注册复制函数
// if (typeof window !== 'undefined') {
// window.copyCode = function (btn: HTMLButtonElement) {
// const codeBlock = btn.closest('.code-block-wrapper')!.querySelector('code')!
// const text = codeBlock.textContent || ''
// navigator.clipboard.writeText(text).then(() => {
// const originalText = btn.textContent
// btn.textContent = '已复制'
// btn.style.backgroundColor = '#10b981'
// // 2秒后恢复按钮文字
// setTimeout(() => {
// btn.textContent = originalText
// btn.style.backgroundColor = ''
// }, 2000)
// })
// }
// }
/** 将 Markdown 转为可安全用于 `v-html` 的 HTML(禁用源码中的原始 HTML)。 */
export function renderSafeMarkdown(src: string): string {
if (!src.trim()) {

BIN
packages/drizzle-pkg/db.sqlite

Binary file not shown.

32
server/plugins/03.error-logger.ts

@ -2,6 +2,23 @@ import log4js from "logger";
const logger = log4js.getLogger("ERROR");
/** 路径/路由类「找不到」:只打控制台,不落盘(避免扫描、错 URL 等刷爆 running.log) */
function isPathNotFoundLikeError(error: unknown): boolean {
if (!error || typeof error !== "object") return false;
const e = error as NodeJS.ErrnoException & { statusCode?: number; statusMessage?: string };
const code = typeof e.code === "string" ? e.code : "";
if (code === "ENOENT" || code === "ENOTDIR") return true;
if (e.statusCode !== 404) return false;
const sm = (e.statusMessage ?? "").trim();
if (!sm) return true;
if (/^not found$/i.test(sm)) return true;
if (/page not found/i.test(sm)) return true;
if (/^cannot (get|post|put|delete|patch|head)\b/i.test(sm)) return true;
if (/no route found|cannot find.*route|static asset.*not found/i.test(sm)) return true;
return false;
}
const processHandlersKey = "__personPanelErrorLoggerProcessHandlers";
function installProcessErrorLogging() {
@ -32,12 +49,19 @@ export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook("error", (error, context) => {
const event = context.event;
const tags = Array.isArray(context.tags) ? (context.tags as string[]).join(",") : "";
logger.error(
const prefix = [
event?.method ?? "",
event?.path ?? "(no request)",
tags ? `[${tags}]` : "",
"\n",
error
);
]
.filter(Boolean)
.join(" ");
if (isPathNotFoundLikeError(error)) {
console.error(prefix || "(error)", "\n", error);
return;
}
logger.error(prefix, "\n", error);
});
});

Loading…
Cancel
Save