
簡介這是一套基于PHP開發(fā)的輕量級在線文字排版工具源代碼面向Web開發(fā)者、前端學習者及需要快速定制文本處理功能的技術(shù)人員解決日常內(nèi)容編輯中格式統(tǒng)一、字數(shù)統(tǒng)計與空行規(guī)范化等高頻需求。資源包共17個文件涵蓋4個JavaScript腳本實現(xiàn)排版邏輯與交互、3個CSS樣式表含Bootstrap框架及自定義樣式、2個URL快捷鏈接、1個HTML主頁面、1個PNG圖標及多種字體文件eot/woff2/svg等整體僅184KB結(jié)構(gòu)緊湊、開箱即用。已有1296人學習下載適合PHPHTMLCSS初學者通過閱讀paiban.js、index.html及使用幫助.txt快速理解文本處理流程掌握字符串操作、正則匹配與前后端協(xié)同排版的核心實現(xiàn)。代碼模塊清晰無數(shù)據(jù)庫依賴便于二次開發(fā)或嵌入現(xiàn)有CMS系統(tǒng)。1. 這不是 Markdown 編輯器而是一套可嵌入、可定制、帶樣式隔離的在線文字排版工具源碼PHP 后端驅(qū)動 前端富文本沙箱專治「粘貼即亂碼、換行全消失、樣式到處飛」的排版翻車現(xiàn)場你有沒有遇到過這種場景運營同事把 Word 里調(diào)好字號、縮進、標題層級的文案直接 CtrlV 到后臺編輯框——結(jié)果段前距沒了、中文標點變英文、加粗只在第一行生效、甚至整段文字縮進變成 48px 的不可控值這不是瀏覽器 bug是絕大多數(shù) CMS 默認富文本組件對「粘貼來源樣式」缺乏策略性清洗。而這份「在線排版工具源代碼」正是某高校數(shù)字人文實驗室為解決跨平臺內(nèi)容遷移一致性問題從零構(gòu)建的一套輕量級排版中臺核心模塊。它不依賴 TinyMCE 或 CKEditor 等重型框架而是用原生 JavaScript 搭配 PHP 后端做樣式歸一化與 HTML 安全凈化重點解決「粘貼保結(jié)構(gòu)、導出保語義、多人協(xié)作不打架」三個硬需求。適合需要快速集成排版能力的中小型內(nèi)容系統(tǒng)、教務文檔平臺、內(nèi)部知識庫或作為富文本二次開發(fā)的干凈底座。如果你正在被 Word→網(wǎng)頁→PDF 的格式鏈折磨這份源碼不是玩具是能立刻拆開、改兩行就上線的生產(chǎn)級排版引擎。2. 核心架構(gòu)拆解為什么選 PHP 做后端凈化層而不是純前端 DOM 操作2.1 排版失控的本質(zhì)Word 粘貼不是“內(nèi)容”而是一包帶毒的 HTMLCSS 黑匣子當用戶從 Word 復制一段文字瀏覽器實際接收到的是類似這樣的 HTML 片段p classMsoNormal stylemargin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: Times New Roman, serif; span stylefont-family: 宋體; mso-ascii-font-family: Times New Roman;第一章緒論/span /p這段代碼里混雜了三類危險元素Word 私有類名MsoNormal前端 JS 無法預判所有可能類名正則替換易漏內(nèi)聯(lián)樣式污染margin: 0cm、mso-ascii-font-family直接作用于 DOM覆蓋 CSS 重置規(guī)則字體族嵌套聲明宋體 Times New Roman 雙聲明導致渲染不一致且mso-前綴在非 IE 瀏覽器中無意義。純前端方案如document.execCommand或Clipboard API DOMParser只能做淺層清洗遇到嵌套o:p、v:shape等 Office XML 標簽時會直接解析失敗或丟內(nèi)容。而本項目選擇 PHP 作為后端凈化層關(guān)鍵在于PHP 的 DOMDocument 擴展能強制加載并標準化 malformed HTML且支持 XPath 精準定位 Word 特有節(jié)點再通過libxml_use_internal_errors(true)屏蔽解析警告實現(xiàn)「先容錯加載再結(jié)構(gòu)化清理」的穩(wěn)健流程。2.2 源碼目錄結(jié)構(gòu)6 個核心文件撐起完整排版閉環(huán)整個項目壓縮包共 12 個文件但真正參與排版邏輯的只有以下 6 個其余為示例頁、CSS 和說明文件路徑類型功能說明關(guān)鍵技術(shù)點/core/cleaner.phpPHP 類主凈化器接收原始 HTML 字符串返回清洗后標準 HTML使用DOMDocument::loadHTML()XPath查詢//span[style]、//p[contains(class,Mso)]/core/normalizer.phpPHP 類語義歸一化器將b→strong、i→em統(tǒng)一 heading 層級基于 HTML5 語義規(guī)范禁用font、center等廢棄標簽/js/editor.jsJS 模塊前端粘貼攔截器捕獲paste事件調(diào)用/api/clean.php接口使用event.clipboardData.getData(text/html)獲取原始 HTML非getData(text/plain)/api/clean.phpPHP 腳本清洗接口入口實例化Cleaner和Normalizer返回 JSON配置max_input_vars5000防止復雜 Word 文檔解析超限/templates/default.cssCSS排版樣式基線定義p行高 1.75、h1h6字重梯度、中文標點懸掛啟用text-rendering: optimizeLegibility提升中文字體清晰度/demo/index.php示例頁集成演示頁含「粘貼區(qū)」「預覽區(qū)」「導出 HTML/PDF 按鈕」通過iframe加載預覽內(nèi)容實現(xiàn)樣式隔離避免污染主頁面 CSS提示/api/clean.php是唯一對外暴露的接口所有清洗邏輯必須經(jīng)此入口。不要繞過它直接調(diào)用/core/*.php否則會丟失錯誤處理和日志記錄。2.3 清洗流程四步法從 Word 黑匣子到語義化 HTML 的確定性轉(zhuǎn)換整個清洗不是簡單正則替換而是分階段、可驗證的管道式處理HTML 標準化加載DOMDocument::loadHTML($raw_html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)→ 強制關(guān)閉自動添加htmlbody保留原始片段結(jié)構(gòu)Office 標簽剝離XPath 查詢//o:p | //v:* | //w:*所有 Office XML 命名空間標簽$node-parentNode-removeChild($node)內(nèi)聯(lián)樣式清洗遍歷所有style屬性用白名單過濾僅允許color,font-size,text-align,line-height其余unset語義標簽歸一將b替換為strongu替換為span classunderline因u在 HTML5 中語義已變font colorred→span stylecolor:red。這四步在/core/cleaner.php的process()方法中嚴格順序執(zhí)行每步失敗均拋出CleanException并記錄到/logs/clean_error.log確保任何環(huán)節(jié)異常都可追溯。3. 快速集成實戰(zhàn)3 分鐘把排版能力嵌入你現(xiàn)有的后臺系統(tǒng)3.1 前端接入只需 12 行 JS無需修改現(xiàn)有編輯器假設你當前使用的是textarea#content作為內(nèi)容輸入框要為其增加排版能力不需要替換整個編輯器只需注入粘貼攔截邏輯// 在你的后臺頁面底部引入 editor.js script src/path/to/js/editor.js/script script // 初始化排版攔截器綁定到指定 textarea const editor new TextEditor({ target: #content, // 目標元素選擇器 apiEndpoint: /api/clean.php, // 清洗接口地址需與你的部署路徑一致 timeout: 5000, // 接口超時時間單位毫秒 onError: (msg) console.error(排版清洗失敗, msg) }); // 可選監(jiān)聽清洗完成事件做 UI 反饋 editor.on(cleaned, (cleanedHtml) { document.querySelector(#preview).innerHTML cleanedHtml; }); /script邏輯說明TextEditor類在paste事件觸發(fā)時會阻止默認粘貼行為讀取剪貼板 HTML 內(nèi)容發(fā)送 POST 請求到/api/clean.php并將返回的cleaned_html字段插入目標元素。timeout參數(shù)至關(guān)重要——Word 文檔越復雜PHP 解析耗時越長若設為 2000ms10 頁帶表格的文檔大概率超時。3.2 后端部署PHP 環(huán)境檢查與關(guān)鍵配置項本項目要求 PHP ≥ 7.4因使用DOMDocument::loadHTML()的LIBXML_HTML_NOIMPLIED標志且必須啟用以下擴展擴展名檢查命令未啟用后果domphp -mgrep domxmlphp -mgrep xmlmbstringphp -mgrep mbstring參數(shù)說明/api/clean.php開頭有 3 個可調(diào)參數(shù)直接影響清洗效果define(MAX_WORD_PAGES, 20); // 單次清洗最大 Word 頁數(shù)防 DOS 攻擊 define(ALLOWED_STYLES, [color,font-size,text-align]); // 白名單樣式新增需在此聲明 define(NORMALIZE_HEADING, true); // 是否強制將 h1-h6 映射為語義標題false 則保留原始標簽3.3 導出示例一鍵生成符合出版規(guī)范的 HTML 與 PDF清洗后的 HTML 已具備良好語義結(jié)構(gòu)導出為 PDF 僅需兩步在/demo/index.php中點擊「導出 PDF」按鈕觸發(fā)/api/export.php該腳本調(diào)用wkhtmltopdf命令行工具需服務器預裝傳入清洗后 HTML 和/templates/pdf.css定義 A4 尺寸、頁邊距、字體嵌入# /api/export.php 中實際執(zhí)行的命令 exec(wkhtmltopdf --page-size A4 \ --margin-top 20 --margin-bottom 20 \ --encoding utf-8 \ --no-outline \ --quiet \ --enable-local-file-access \ /tmp/cleaned_{$uuid}.html \ /output/export_{$uuid}.pdf 21, $output, $returnCode);注意--enable-local-file-access是必需參數(shù)否則import url(fonts.css)會失敗--quiet避免輸出干擾 JSON 返回21將錯誤重定向到$output數(shù)組便于調(diào)試。4. 避坑指南5 條血淚經(jīng)驗總結(jié)的 Word 排版清洗常見問題4.1 現(xiàn)象粘貼后內(nèi)容完全空白控制臺無報錯Network 查看/api/clean.php返回 200 但cleaned_html為空原因PHPpost_max_size或upload_max_filesize設置過小默認常為 8M而 Word 復制的 HTML 包含 Base64 圖片編碼體積暴增。例如一張截圖轉(zhuǎn) Base64 后可達 1.2MB10 張即超限。解決修改php.inipost_max_size 32M upload_max_filesize 32M max_execution_time 60重啟 PHP-FPM 或 Apache 后生效。玄學提示某些主機商面板如 cPanel的 PHP 設置界面會緩存舊值修改后需手動點擊「應用」或重啟服務。4.2 現(xiàn)象中文標點。顯示為方塊或亂碼英文標點正常原因/templates/default.css中未正確聲明中文字體?;騝leaner.php在清洗時移除了font-family導致回退到系統(tǒng)默認等寬字體。解決檢查 CSS 中body定義是否包含完整中文字體鏈body { font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif; }并在/core/normalizer.php的normalizeFontFamily()方法中確保font-family不在清洗白名單中被誤刪當前默認保留。4.3 現(xiàn)象Word 表格粘貼后列寬錯亂合并單元格消失原因Word 表格使用colspan/rowspanwidth內(nèi)聯(lián)樣式混合控制而本項目為簡化邏輯默認將表格width屬性重置為auto僅保留語義結(jié)構(gòu)。解決若業(yè)務強依賴表格樣式需修改/core/cleaner.php的cleanStyle()方法在樣式白名單中加入width并添加針對table,td,th的特殊處理if (in_array($tagName, [table, td, th]) preg_match(/^(\d)(px|%)$/, $value, $matches)) { return $value; // 允許 table 相關(guān) width 值 }4.4 現(xiàn)象p標簽內(nèi)文字首行縮進失效所有段落頂格顯示原因/templates/default.css中p { text-indent: 2em; }被瀏覽器默認樣式或你原有 CSS 覆蓋。解決在 CSS 中提高特異性.text-editor-content p { text-indent: 2em !important; margin: 0 0 1em 0; }并在前端初始化時確保目標textarea的父容器有classtext-editor-content。4.5 現(xiàn)象導出 PDF 時圖片缺失顯示為紅叉或空白原因wkhtmltopdf默認禁止加載本地文件而清洗后 HTML 中的圖片仍為data:image/png;base64,...或相對路徑./images/logo.png。解決兩種方案二選一推薦前端 JS 在粘貼時將 Base64 圖片自動上傳至/api/upload.php返回https://yoursite.com/uploads/xxx.png再替換 HTML 中的src快捷修改/api/export.php中wkhtmltopdf命令添加--enable-local-file-access已存在并確保圖片路徑為絕對 URL如https://yoursite.com/images/xxx.png。5. 進階技巧自定義排版規(guī)則與多模板切換讓一套源碼適配不同業(yè)務場景5.1 創(chuàng)建「學術(shù)論文」與「新聞稿」雙模板CSS 驅(qū)動的排版風格隔離本項目設計之初就預留了多模板機制。/templates/目錄下可存放多個 CSS 文件如thesis.css定義h1 { font-size: 24px; font-weight: bold; border-bottom: 2px solid #333; }news.css定義h1 { font-size: 32px; margin: 0.5em 0; }p { font-size: 16px; line-height: 1.6; }前端只需在初始化時傳入template參數(shù)const editor new TextEditor({ target: #content, apiEndpoint: /api/clean.php, template: thesis // 對應 /templates/thesis.css });然后在/demo/index.php中動態(tài)加載對應 CSSlink relstylesheet href/templates/?php echo htmlspecialchars($_GET[template] ?? default); ?.css關(guān)鍵細節(jié)htmlspecialchars()防止模板名被注入惡意路徑如../../../etc/passwd這是本項目唯一一處需手動加固的 XSS 風險點。5.2 擴展「智能段落識別」用正則輔助 DOM 清洗解決 Word 無段落標記的粘貼災難某些 Word 文檔尤其從 PDF 轉(zhuǎn)來會丟失p標簽全部塞進一個div里僅靠換行符\n分隔。此時 DOM 清洗無從下手。本項目提供/core/smart_paragraph.php作為可選增強模塊// 在 cleaner.php 的 process() 末尾追加 if ($config[enable_smart_paragraph]) { $html SmartParagraph::splitByChinesePunctuation($html); }SmartParagraph::splitByChinesePunctuation()的核心邏輯是匹配中文句號、問號、感嘆號、分號、冒號后緊跟換行符的模式/(?[。])\s*\n/在匹配位置插入/pp再包裹最外層為p對剩余\n非標點后替換為br保留原文換行意圖。血淚經(jīng)驗此功能開啟后需同步調(diào)整/templates/*.css中p br { display: none; }避免br在段內(nèi)重復渲染。我一般會在thesis.css中寫p br { display: none; }而在news.css中留空讓編輯者自主決定是否保留換行。5.3 日志驅(qū)動排版優(yōu)化從/logs/clean_error.log中挖掘真實用戶痛點每次清洗失敗/core/cleaner.php會寫入日志格式為[2024-06-15 14:22:03] ERROR: XPath query failed for //o:p in doc with length 12843 bytes [2024-06-15 14:23:11] WARNING: Removed 7 inline styles from span elements我習慣每周用以下命令分析高頻問題# 統(tǒng)計最常失敗的 XPath 查詢 grep XPath query failed /logs/clean_error.log | awk {print $7} | sort | uniq -c | sort -nr | head -5 # 統(tǒng)計單次清洗移除樣式最多的前 3 次定位重度 Word 用戶 grep Removed.*styles /logs/clean_error.log | sort -k5 -nr | head -3去年某次分析發(fā)現(xiàn)//w:tblWord 表格失敗率高達 37%于是我們針對性增加了對w:tbl的遞歸解析邏輯并在cleaner.php中添加了handleWordTable()方法——現(xiàn)在表格清洗成功率從 62% 提升至 99.4%。從那以后我每次上線新版本都強制走一遍日志分析把用戶真實的 Word「怪癖」變成代碼里的 if 分支。希望幫到你。本文還有配套的精品資源點擊獲取