发帖
 找回密码
 立即注册
搜索
1 0 0
资源分享 432 1 4 小时前

有时候要把和llm的内容保存下来,md本身也可以存,但是一些内容上传或者分享给别人还是会用到pdf,本身就有个测试AI编程能力的工具站,就想着直接做个工具看看。

之前完全没有前端处理生成pdf的经验,然后就vibe coding了一下,gemini给了不少方案:

  1. html canvas(这个最后保存的不能选择,就是图片);
  2. markdownit+pdfmake(这个纯坑爹, gemini是直接把html直接写进去,然后发现是纯文本。。。用pdfmake需要自己做个AST,把markdown转成它的格式写入。。。放弃了)

最后头疼。。。想着到底怎么样保存pdf才能可以选择文本呢
然后发现。。沃日 直接用浏览器的打印不就好了

然后和qwen3 coder友好交流了好几个小时,终于捣鼓出来了。。。

https://merchmindai.net/zh/tools/markdown-to-pdf

8ab58188bf3ce21cf7beb36c17b7439bf503d2a3.webp
然后点击转换直接打开一个新网页,弹出打印选项,我发现不同浏览器兼容性不一样,用edge打开的网页里是能显示html的,但是一些浏览器是空白(不影响打印)
0c0c0a23c36cf8ea435296ccc3173a27d7ca8be2.webp
还有就是一定要选择为"另存为PDF",不然默认的microsoft pdf那个一样是没法选中的
20ff2f9991ce423768792bc8d110f8f2a052f82f.webp
核心代码送上:

// Extract HTML generation logic
  const generateHtmlContent = async (
    markdownText: string,
    css: string,
    selectedTheme: "white" | "black",
    title?: string
  ) => {
    try {
      // Dynamically import markdown-it and highlight.js for rendering
      const [mdModule, hljsModule] = await Promise.all([
        import("markdown-it"),
        import("highlight.js"),
      ]);

      const MarkdownIt = mdModule.default;
      const hljs = hljsModule.default;

      // Initialize markdown-it with highlight.js support
      const md = new MarkdownIt({
        highlight: function (str, lang) {
          if (lang && hljs.getLanguage(lang)) {
            try {
              return hljs.highlight(str, { language: lang }).value;
            } catch (__) {}
          }
          return ""; // use external default escaping
        },
      });

      const htmlContent = md.render(markdownText);
      const themeClass =
        selectedTheme === "white" ? "theme-white" : "theme-black";

      // Create the HTML content
      const html = document.createElement("html");
      const head = document.createElement("head");
      const body = document.createElement("body");

      if (title) {
        const titleElement = document.createElement("title");
        titleElement.textContent = title;
        head.appendChild(titleElement);
      }

      // Add theme-specific CSS
      const themeStyle = document.createElement("style");
      themeStyle.textContent = css;
      head.appendChild(themeStyle);

      // Add highlight.js CSS
      const hljsLink = document.createElement("link");
      hljsLink.rel = "stylesheet";
      hljsLink.href =
        selectedTheme === "white"
          ? "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github.min.css"
          : "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github-dark.min.css";
      head.appendChild(hljsLink);

      body.className = themeClass;
      const div = document.createElement("div");
      div.className = "markdown-body";
      div.innerHTML = htmlContent;
      body.appendChild(div);

      html.appendChild(head);
      html.appendChild(body);

      return html.outerHTML;
    } catch (error) {
      console.error("Error generating HTML content:", error);
      throw error;
    }
  };

  const handlePrint = async () => {
    if (!markdown.trim()) {
      toast({
        title: t("pdf.toastErrorTitle"),
        description: t("pdf.toastErrorDescription"),
        variant: "destructive",
      });
      return;
    }

    setIsPrinting(true);
    try {
      // Create a new window for printing
      const printWindow = window.open("", "_blank");
      if (!printWindow) {
        toast({
          title: t("pdf.toastErrorTitle"),
          description: t("pdf.toastPopupBlocked"),
          variant: "destructive",
        });
        setIsPrinting(false);
        return;
      }

      const htmlContent = await generateHtmlContent(
        markdown,
        customCss,
        theme,
        fileName
      );

      // Add print script
      const printScript = `
        <script>
          window.onload = function() {
            setTimeout(function() {
              window.print();
            }, 500);
          };
        </script>
      `;

      const finalHtml = htmlContent.replace("</body>", `${printScript}</body>`);

      // Write to the print window
      printWindow.document.open();
      printWindow.document.write(finalHtml);
      printWindow.document.close();

      setIsPrinting(false);
    } catch (error) {
      console.error("Error preparing print content:", error);
      toast({
        title: t("pdf.toastErrorTitle"),
        description: t("pdf.toastErrorDescription"),
        variant: "destructive",
      });
      setIsPrinting(false);
    }
  };
──── 0人觉得很赞 ────

使用道具 举报

啊,这个没转过。
感觉可以先把PDF转成Markdown(可以用Mistral OCR,影印版的PDF也能处理,布局还不错),
然后再用其他工具转换。
这个功能挺实用的
有时候需要把和大语言模型(LLM)交流的内容保存下来,Markdown(md)格式本身也能存储,不过有些内容在上传或者分享给别人时还是会用到PDF格式。刚好有个测试人工智能编程能力的工具站,就想着直接做个工具试试看。
已收藏
太强了,大佬。
大佬太厉害了,PDF转Word好转吗?我转出来的Word输出格式和原来的PDF格式差别太大了。
您需要登录后才可以回帖 立即登录
高级模式