Pro 版本
Projection — 深入參考
本頁是 Pro Projection 模組的深入參考,記錄公開的 tokenize、emit 與 round-trip 介面、intent 閘門,以及內容串流的來回往返(round-trip)語意。ContentProjectionWriter 會將 PDF 內容串流解析為一個扁平、有序的符記清單,再把符記清單重新序列化為一個新的內容串流。此模型是單向的:發射(emission)會產生一個新的串流,絕不會就地編輯原件。
**注意。**此處的「projection」指的是內容串流符記投影(content-stream token projection),而非座標或地理空間投影。
可用性與授權
標題為「可用性與授權」的區段此能力隨 NextPDF Pro(nextpdf/pro)出貨,並以 Pro 層級的授權封套啟用。未持有該權利的部署不會載入此能力的類別。比較版本並取得授權。
不存在個別功能的授權旗標。這是一項 Pro 版本能力。發射另外還需要一個明確的 ProjectionIntent 引數,由型別系統強制要求,而非授權開關。
公開 API 介面
標題為「公開 API 介面」的區段composer require nextpdf/pro:^3此模組位於 NextPDF\Pro\Projection 命名空間。ContentProjectionWriter 上的所有操作皆為靜態。
| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
ContentProjectionWriter::tokenize | string $contentStream | 將串流解析為扁平、有序的符記清單;正規化空白、丟棄註解、跳過無法辨識的位元組 | list<ContentToken> | 無;格式錯誤或控制位元組會被跳過,而非拒絕 | 唯讀;不需要 intent。 |
ContentProjectionWriter::emit | list<ContentToken> $tokens, ProjectionIntent $intent | 將符記序列化為一個新的內容串流;輸出與 intent 值無關 | string | 本體中無;缺少引數或非 ProjectionIntent 引數會在型別邊界失敗 | Intent 是呼叫端的閘門,而非執行期開關。 |
ContentProjectionWriter::roundTrip | string $contentStream | 先 tokenize、再原樣重新發射;驗證閘門 | string | 無 | 輸出並非位元組逐一相同;運算子序列與運算元值會被保留。 |
ContentToken::__construct | ContentTokenType $type, string|int|float|bool|null $value = null | 建構一個不可變的符記;不進行任何驗證 | ContentToken | 無;型別不相容的 $value 會在型別邊界失敗 | readonly;type 與 value 為公開。 |
ContentToken::isTextOperator | — | 回報該符記是否為文字運算子(BT、ET、Tj、TJ、Td、TD、Tm、T*、Tf、Tc、Tw、Tz、TL、Tr、Ts、'、") | bool | 無;對於非運算子符記回傳 false | — |
ContentToken::isTextShowingOperator | — | 回報該符記是否為顯示文字運算子(Tj、TJ、'、") | bool | 無;對於非運算子符記回傳 false | 文字運算子的子集。 |
ContentTokenType | —(字串背景列舉) | 列舉符記判別子:LiteralString、HexString、Number、Name、Operator、ArrayBegin、ArrayEnd、DictBegin、DictEnd、Boolean、Null | — | — | 背景值為穩定識別碼。 |
ProjectionIntent | —(純列舉) | 列舉兩種允許的發射 intent:Sanitization、SteganographicEmbedding | — | — | 沒有通用 case,因此靜態分析會標示未宣告的使用。 |
public static function tokenize(string $contentStream): arraypublic static function emit(array $tokens, ProjectionIntent $intent): stringpublic static function roundTrip(string $contentStream): stringenum ProjectionIntent{ case Sanitization; case SteganographicEmbedding;}public function __construct( public ContentTokenType $type, public string|int|float|bool|null $value = null,) {}
public function isTextOperator(): boolpublic function isTextShowingOperator(): bool行為合約
標題為「行為合約」的區段ContentProjectionWriter::tokenize($contentStream) 會將串流解析為一個扁平、有序的 list<ContentToken>。它涵蓋字面字串、十六進位字串、名稱、數字、陣列與字典分隔符、布林值、null 以及運算子。空白與註解會被消耗並丟棄;無法辨識的位元組會推進游標而不產生符記。此處理是唯讀的,不需要 intent。
emit($tokens, $intent) 會將符記清單序列化回內容串流位元組,並需要一個 ProjectionIntent。intent 僅是呼叫端的宣告:無論傳入哪個 case,發射出的位元組都相同。數字會保留其整數/浮點數區別——整數原樣發射,浮點數最多發射六位小數並修剪尾端的零。字面字串會被重新轉義,十六進位字串以大寫十六進位發射,名稱會帶著其開頭的斜線(solidus)。每個運算子後面會接一個換行;陣列與字典分隔符會抑制相鄰的分隔字元。
roundTrip($contentStream) 會先 tokenize、再原樣重新發射。它是驗證閘門:在信任任何「修改並發射」序列之前,先確認一個乾淨的結果。輸出與輸入並非位元組逐一相同——空白會被正規化、註解會消失——但運算子序列與運算元值會被保留。
ProjectionIntent 恰好只有兩個 case:Sanitization(具破壞性、不可逆的遮蔽)與 SteganographicEmbedding(隱藏酬載嵌入)。沒有通用 case,因此靜態分析能標示任何缺少已宣告、已知目的的發射。ContentToken 是一個不可變的 readonly 值,攜帶一個 type 判別子與一個已解碼的 value;isTextOperator() 與 isTextShowingOperator() 會分類運算子符記,並對每個非運算子符記回傳 false。
邊界案例與失敗模式
標題為「邊界案例與失敗模式」的區段- 在任何「修改並發射」序列之前,先確認一次乾淨的來回往返。將失敗的來回往返視為停止條件。
Sanitizationintent 是不可逆的。已移除的符記不會出現在輸出中,且無法從輸出復原。- Intent 不會改變輸出。
emit()對任一 case 都產生相同的位元組;該引數是呼叫端的閘門。遮蔽與隱寫編輯是由呼叫端在發射前變更符記清單來套用。 - 發射器會正規化空白並丟棄註解,因此即使是未修改的來回往返,與原件進行位元組層級比對也會有差異。
- 浮點運算元最多格式化為六位小數,然後再修剪。需要更高精度的值會在發射時被四捨五入;整數則是精確的。
- 輸入時會解碼的字面字串轉義包含
\n、\r、\t、\b、\f、經轉義的分隔符,以及最多三位、夾限為一個位元組的八進位轉義。 - 位數為奇數的十六進位字串在輸入時會以尾端零補齊,符合 ISO 十六進位字串規則。
- 格式錯誤或控制位元組會被跳過,而非拒絕;
tokenize()對非預期輸入不會拋出例外。 - 本模組不進行任何密碼學運算,也未定義任何 FIPS 特定行為。
一致性
標題為「一致性」的區段符記化會將串流視為以標準 PDF 物件語法表達的運算子與運算元序列,依 ISO 32000-2:2020, 8.2。位元組到符記的分組遵循 ISO 32000-2:2020, 7.2 的詞法字元類別。奇數長度的十六進位字串會將最後一位補為零,依 ISO 32000-2:2020, 7.3.4.3。這些條款記錄在本頁的引用紀錄中。
這些陳述描述的是相對於所引用條款的能力。NextPDF 未持有任何一致性認證,且對某條款的支援並非認證主張。
開發備註
標題為「開發備註」的區段- 自模組 1.10.0 版起可用;三項操作皆為
ContentProjectionWriter上的靜態進入點。 - Tokenize 與 emit 的複雜度與內容串流長度呈線性。沒有公布的吞吐量數據;請以具代表性的串流自行量測。
- 扁平符記模型——每個詞法元素一個符記,而非依運算子分組——正是能進行精準編輯(例如調整 TJ 陣列中的單一數字)的關鍵。依運算子分組的表示形式位於 Pro 樹的其他地方,不在本頁範圍內。
ContentToken是不可變的。請透過建構新符記來組成修改後的清單,而非變更既有符記。- 在你的管線中保留來回往返閘門:通過的
roundTrip()是本模組在任何破壞性編輯之前所圍繞設計的前提條件。
發布邊界
標題為「發布邊界」的區段本頁僅記錄外部可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表格、runbook 檔名與工單前綴皆不在範圍內。