@rex0220/print-craft-authoring-tools 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +9 -4
  2. package/SECURITY.md +6 -2
  3. package/dist/cli.mjs +450 -150
  4. package/dist/core.mjs +3422 -0
  5. package/dist/types/_print-craft/src/authoring/api.d.ts +3 -0
  6. package/dist/types/_print-craft/src/config/load.d.ts +4 -0
  7. package/dist/types/_print-craft/src/config/schema.d.ts +5 -0
  8. package/dist/types/commands/buttons.d.ts +19 -0
  9. package/dist/types/commands/diff.d.ts +6 -0
  10. package/dist/types/commands/fields.d.ts +54 -0
  11. package/dist/types/commands/normalize.d.ts +40 -0
  12. package/dist/types/commands/preview.d.ts +39 -0
  13. package/dist/types/commands/pull.d.ts +36 -0
  14. package/dist/types/commands/record.d.ts +63 -0
  15. package/dist/types/commands/records.d.ts +36 -0
  16. package/dist/types/commands/save.d.ts +50 -0
  17. package/dist/types/commands/take.d.ts +19 -0
  18. package/dist/types/commit-file.d.ts +38 -0
  19. package/dist/types/context.d.ts +10 -0
  20. package/dist/types/core.d.ts +32 -0
  21. package/dist/types/engine.d.ts +64 -0
  22. package/dist/types/env.d.ts +50 -0
  23. package/dist/types/kintone-rest.d.ts +65 -0
  24. package/dist/types/kintone-url.d.ts +11 -0
  25. package/dist/types/meta.d.ts +30 -0
  26. package/dist/types/normalize/checks.d.ts +58 -0
  27. package/dist/types/normalize/css-check.d.ts +53 -0
  28. package/dist/types/normalize/derive.d.ts +30 -0
  29. package/dist/types/normalize/findings.d.ts +21 -0
  30. package/dist/types/normalize/html-check.d.ts +23 -0
  31. package/dist/types/normalize/line-diff.d.ts +8 -0
  32. package/dist/types/normalize/model.d.ts +36 -0
  33. package/dist/types/normalize/policy.d.ts +29 -0
  34. package/dist/types/normalize/size.d.ts +16 -0
  35. package/dist/types/paths.d.ts +7 -0
  36. package/dist/types/permission.d.ts +21 -0
  37. package/dist/types/plugin-zip.d.ts +53 -0
  38. package/dist/types/preview/render.d.ts +82 -0
  39. package/dist/types/safe-path.d.ts +24 -0
  40. package/dist/types/workspace.d.ts +84 -0
  41. package/package.json +10 -2
@@ -0,0 +1,65 @@
1
+ /**
2
+ * kintone REST API の読み取り専用クライアント(docs/authoring-plan.md 12.2、Codex MAJOR 5 の反映。1-10 レビュー BLOCKER 1 で送信先の検証を足した)。
3
+ * - GET しか送らない(メソッドはここで固定。他のメソッドを送る口が無い)
4
+ * - 送れるパスは ALLOWED_APIS に固定し、それ以外は送信前に止める(ゲストスペースの /k/guest/<id>/v1/… も同じ一覧)
5
+ * - 送信先は kintone のドメイン(kintone-url.ts)だけ。URL は new URL(path, base) で組み、送信直前に origin が検証済みの origin と同じか確かめる
6
+ * - 認証は API トークン(X-Cybozu-API-Token)か、ログインユーザー(X-Cybozu-Authorization)
7
+ * - エラーの文言は HTTP の状態と kintone のコードと固定のヒントだけ(サーバーの message は出さない。認証情報とレコードの中身を混ぜない)
8
+ */
9
+ import type { KintoneAuth } from "./env.ts";
10
+ /**
11
+ * 許可する API(/k/v1/ と /k/guest/<id>/v1/ の後ろ)。app/plugin/config と preview/app/plugin/config は pull が使う(API ラボの
12
+ * 「アプリに追加されているプラグインの設定情報を取得する」。GET だけ。変更の PUT は呼ばない。Takashi 2026-10-05「tools のみで GET だけ」)
13
+ */
14
+ export declare const ALLOWED_APIS: readonly ["app", "app/form/fields", "app/form/layout", "record", "records", "preview/app/form/fields", "preview/app/form/layout", "app/plugin/config", "preview/app/plugin/config"];
15
+ /**
16
+ * 受け取る本文の上限(バイト。段階 0-2 の段 4。print-craft-authoring-mcp の docs/api-table.md 2 章)。CLI にも効くので、大きなアプリ
17
+ * (項目 500 前後、テーブルが多い)でも引っかからない値にする。超えたら本文を読み切らずに RestError(code LimitError)
18
+ */
19
+ export declare const RECEIVE_LIMITS: Record<(typeof ALLOWED_APIS)[number], number>;
20
+ export type AllowedApi = (typeof ALLOWED_APIS)[number];
21
+ export declare class RestError extends Error {
22
+ readonly status: number;
23
+ readonly code: string | undefined;
24
+ readonly apiPath: string | undefined;
25
+ constructor(message: string, status: number, code?: string, apiPath?: string);
26
+ }
27
+ export declare class NotAllowedError extends Error {
28
+ }
29
+ /**
30
+ * fetch の応答のうち使う部分。本文はストリーム(body)だけから読む(全文を読んでから大きさを確かめる経路は持たない。Codex レビュー MINOR 8)。
31
+ * body が null なら本文なし。headers は無くてもよい(Content-Length は読む前に止めるためだけ)
32
+ */
33
+ export interface FetchResponseLike {
34
+ ok: boolean;
35
+ status: number;
36
+ headers?: {
37
+ get(name: string): string | null;
38
+ };
39
+ body: {
40
+ getReader(): {
41
+ read(): Promise<{
42
+ done: boolean;
43
+ value?: Uint8Array;
44
+ }>;
45
+ cancel(): Promise<void>;
46
+ };
47
+ } | null;
48
+ }
49
+ export type FetchLike = (url: string, init: {
50
+ method: "GET";
51
+ headers: Record<string, string>;
52
+ }) => Promise<FetchResponseLike>;
53
+ /**
54
+ * 上限を守って本文を読む。Content-Length が上限を超えれば読まずに止める。無い・偽りでも、読みながら上限 + 1 バイトで止める。
55
+ * 止めるときの cancel の失敗は無視する(上限の誤りを優先して返す)。JSON にするのは上限の確認の後だけ(呼ぶ側)
56
+ */
57
+ export declare function readCapped(res: FetchResponseLike, limit: number, apiPath: string): Promise<string>;
58
+ export interface RestClient {
59
+ readonly baseUrl: string;
60
+ /** 許可した API を GET で呼ぶ。api は "app" / "app/form/fields" など。guestSpaceId を渡すとゲストスペースの URL */
61
+ get<T>(api: AllowedApi, params: Record<string, string | number | boolean | undefined>, guestSpaceId?: number): Promise<T>;
62
+ }
63
+ export declare function apiPathOf(api: string, guestSpaceId?: number): string;
64
+ export declare function authHeaders(auth: KintoneAuth): Record<string, string>;
65
+ export declare function createRestClient(auth: KintoneAuth, fetchImpl?: FetchLike): RestClient;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * kintone の接続先 URL の検証(Codex 1-10 レビュー BLOCKER 1)。認証ヘッダー(API トークン / ログインユーザー)を送る先を kintone のドメインだけに限る。
3
+ * - https で、ユーザー情報(user:pass@)・ポート・パス・クエリ・フラグメントが無い
4
+ * - ホストは *.cybozu.com / *.kintone.com / *.cybozu.cn(セキュアアクセスの *.s.cybozu.com も含む)
5
+ * 返すのは正規化した origin(小文字、末尾の / 無し)。REST の送信直前にも同じ origin か確かめる(kintone-rest.ts)。
6
+ */
7
+ export declare const KINTONE_HOST_SUFFIXES: readonly [".cybozu.com", ".kintone.com", ".cybozu.cn"];
8
+ export declare class KintoneUrlError extends Error {
9
+ }
10
+ export declare function normalizeKintoneBaseUrl(raw: string): string;
11
+ export declare function isKintoneBaseUrl(raw: string): boolean;
@@ -0,0 +1,30 @@
1
+ /** 印刷屋プラグインの kintone のプラグイン ID(PUBKEY の SHA-256 から。plugin-zip.ts の pluginIdOf。5 変種とも同じ鍵) */
2
+ export declare const PRINT_CRAFT_PLUGIN_ID = "lcapkanpjdabgphknkabojmcfhonhkhp";
3
+ /** tools が扱う印刷屋の版の下限(manifest.json の version。authoring API を同梱したのが Ver.6) */
4
+ export declare const MIN_PLUGIN_VERSION = 6;
5
+ /** tools が対応する印刷屋の authoring API の版(print-craft の src/authoring/api.ts の AUTHORING_API_VERSION。2 = Ver.7 で webFontPageCss を追加) */
6
+ export declare const SUPPORTED_API_VERSIONS: readonly number[];
7
+ /** 印刷屋の版として扱えるか(整数で MIN_PLUGIN_VERSION 以上) */
8
+ export declare function isSupportedPluginVersion(version: string): boolean;
9
+ /** tools が使う authoring API のキーと型(契約。zip の API がこの形でなければ止める。1-10 レビュー MAJOR 8) */
10
+ export declare const REQUIRED_API: Record<string, "function" | "object" | "string" | "number">;
11
+ export interface ToolsMeta {
12
+ toolsVersion: string;
13
+ /** 扱う印刷屋の zip のプラグイン ID */
14
+ pluginId: string;
15
+ /** 扱う印刷屋の版の下限 */
16
+ minPluginVersion: number;
17
+ supportedApiVersions: number[];
18
+ /** tools のリポジトリ(print-craft-authoring)の commit(作業ツリーに変更があれば +dirty) */
19
+ commit: string;
20
+ builtAt: string;
21
+ mode: "build" | "dev";
22
+ }
23
+ /** RegExp を文字列にして JSON にする(CONFIG_SCHEMA の pattern を落とさない) */
24
+ export declare function stableJson(v: unknown): string;
25
+ export declare function sha256Hex(data: string | Buffer): string;
26
+ /** CONFIG_SCHEMA のハッシュ(先頭 12 桁)。印刷屋の API から受けた schema で計算する */
27
+ export declare function schemaRevisionOf(schema: unknown): string;
28
+ export declare function gitCommit(dir: string): string;
29
+ export declare function devMeta(): ToolsMeta;
30
+ export declare function toolsMeta(): ToolsMeta;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * 正規化した設定の検査(docs/authoring-plan.md 12.3)。派生値は derive.ts が作った後に呼ぶ。列挙の定数は印刷屋の API から。
3
+ * 1-10 レビューと再レビューで足したこと:
4
+ * - `isSafeExpression` は式全体を見る("ESC_HTML(x) & HTML(…)" を安全にしない。& でつないだ項がすべて安全なら安全。REPLACE の置換文字列は <br> か記号無しの定数だけ)
5
+ * - HTML 設定の 1 行目 $out / 2 行目 $fname の欠落、有効なボタンの HTML 設定の欠落、有効なボタン名の重複はエラー
6
+ * 2026-10-04 Takashi「ver.6 にチェックを組み込めばよい」: kintone 以外への読み込みとスクリプトは印刷屋 Ver.6 が描画の前に除く(共通の設定「外部参照」externalRefs = "block"。
7
+ * print-craft の src/shared/sanitize.ts)。計算式が作る HTML を tools の静的検査で止め切れない(Codex レビュー 5 回)ので、止めるのは本体、tools は次の分担にした:
8
+ * - externalRefs が "allow"(Ver.5 と同じく何も除かない。自己責任)は、利用者が policy/authoring-policy.json の allowExternalRefs にその設定ファイルを
9
+ * 書いていなければエラー。キーが無い設定(Ver.5 のエクスポート)は印刷屋が "allow" として動かすので derive.ts が "allow" を明示する(同じ承認が要る)
10
+ * - "block" の設定の HTML / CSS のテンプレートにある外部 URL はエラー(印刷屋が除くので帳票に出ない。添付ファイルか data:image にする)。
11
+ * "allow" の設定では policy の allowExternal で承認(承認済みは情報、無ければ警告)
12
+ * - Web フォント(fontInfo.cssUrl)は印刷屋が除かないので、外部参照の設定に関わらず policy の allowExternal で承認(Google Fonts は既定で承認)
13
+ * - 帳票の行の計算式が作る HTML は警告だけ: HTML を作る関数の名前、TAG の要素名や ATTR / STYLE / BATTR の値が定数でない、
14
+ * 文字列の定数に HTML / CSS があれば HTML / CSS と同じ検査を警告として出す(外部 URL は "block" なら「除かれる」警告、"allow" なら承認の対象)
15
+ */
16
+ import type { Findings } from "./findings.ts";
17
+ import { type Model } from "./model.ts";
18
+ import { type Policy } from "./policy.ts";
19
+ export interface CheckOptions {
20
+ policy: Policy;
21
+ /** cwd からの相対パス(policy の files / allowExternalRefs と照合) */
22
+ settingsFile?: string;
23
+ }
24
+ /** 共通の設定「外部参照」(印刷屋 Ver.6 の shared/external-refs.ts と同じ値) */
25
+ export type ExternalRefs = "block" | "allow";
26
+ export declare const EXTERNAL_REFS: readonly ExternalRefs[];
27
+ /**
28
+ * 文字列の定数の中の \n / \r / \t(2026-10-05)。実エンジンは " のエスケープ(\")しか解釈しないので、"\n" は改行でなく \ と n の 2 文字で、
29
+ * REPLACE(ESC_HTML(備考), "\n", "<br>") は何も置き換えない(試用の納品書で発覚。文書と samples がこの形を勧めていた)。改行は NEWLINE()
30
+ */
31
+ export declare function backslashEscapes(formula: string): string[];
32
+ /** 最上位の区切り文字(, や &)で分ける(文字列と括弧の中は分けない)。括弧や引用符が合わなければ null */
33
+ export declare function splitTopLevel(s: string, sep?: string): string[] | null;
34
+ /** 式全体が 1 つの関数呼び出し NAME(args) か("A(1) & B(2)" は違う) */
35
+ export declare function parseCall(e: string): {
36
+ name: string;
37
+ args: string[];
38
+ } | null;
39
+ /**
40
+ * 文字列の定数の中に // があるか。印刷屋の stripComments(load.ts)は文字列を見ずに // 以降を行末まで捨てるので、
41
+ * "https://…" のような文字列は設定画面でもデスクトップでも壊れる(印刷屋の仕様。URL は HTML の属性か ##目印## に置く)。
42
+ * 文字列の規則は実エンジンの p.dq と同じ: 二重引用符だけ、直前に \ がある " はエスケープ(\\" も閉じない)、' は文字
43
+ */
44
+ export declare function commentInsideString(formulaSet: string): boolean;
45
+ /** 式の中の文字列の定数("…" と '…'。エスケープは外す) */
46
+ export declare function stringLiterals(formula: string): string[];
47
+ /** 式の中の NAME(...) の呼び出しをすべて見つけ、引数を最上位のカンマで分けて返す(入れ子も見る) */
48
+ export declare function callsOf(formula: string, name: string): string[][];
49
+ /**
50
+ * HTML の ${式} が安全な差し込みか(12.3 の html.rawExpression)。式**全体**が次のどれか(& でつないだ項はすべてがこれなら安全):
51
+ * ESC_HTML(…)、REPLACE(ESC_HTML(…), NEWLINE() か "文字列", "<br>" か記号無しの文字列)、数値・日付の項目そのもの、数値・日付の項目(と算術・整える関数の入れ子)を
52
+ * 整える関数(FVAL(合計) など。残りの引数は記号無しの文字列や数の定数)、TODAY() / NOW()、数の定数、HTML の記号を含まない文字列の定数
53
+ * それ以外(文字列系の項目、FVAL(文字列項目)、HTML(…)、記号を含む定数)は警告
54
+ */
55
+ export declare function isSafeExpression(expr: string, pp: Record<string, {
56
+ type: string;
57
+ }>): boolean;
58
+ export declare function checkBody(body: Record<string, unknown>, model: Model, f: Findings, opt: CheckOptions): Promise<void>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * CSS の検査(docs/authoring-plan.md 12.3、Codex BLOCKER 1。1-10 レビュー BLOCKER 3 と再レビュー BLOCKER 2 / MINOR 1 で Chrome の解釈に合わせた)。
3
+ * 簡易トークナイザー(tokenizeCss)で、
4
+ * 1. コメントを外す(文字列の中の /* は壊さない。エスケープで /* を作っても注釈にはならない)
5
+ * 2. 文字列を番号の印(\u0001N\u0001)に置き換えて別に持つ(文字列の中の url( や @import を禁止構文と誤認しない。再レビュー MINOR 1)
6
+ * 3. CSS のエスケープを復号する(\75rl → url、@\69mport → @import。16 進の後ろの空白は改行・CR・FF・CRLF も 1 つ消費する = 仕様どおり。再レビュー BLOCKER 2)
7
+ * その上で、外部に接続する手段をすべて拾って URL を分類する: url()、image-set() / -webkit-image-set() / image() / src() の文字列、@import の文字列。
8
+ * 禁止: @import、expression(、behavior:、-moz-binding:(文字列の外だけ見る)。
9
+ * URL の分類は Chrome の URL パーサーに合わせる: タブ・改行を捨て、両端の制御文字と空白を外し、\ は / と同じ(\\evil はスキーム相対)。
10
+ * 印刷屋の置き換えタグ #{&f(…)} は添付ファイルの画像(data URL に置き換わる)なので許す。
11
+ */
12
+ export interface CssUrl {
13
+ url: string;
14
+ /** url() / @import / image-set / image / src */
15
+ via: string;
16
+ }
17
+ export interface CssCheckResult {
18
+ errors: string[];
19
+ /** https の外部 URL(承認の対象) */
20
+ externals: CssUrl[];
21
+ }
22
+ export type UrlKind = "placeholder" | "data-image" | "data-svg" | "https" | "relative" | "fragment" | "bad";
23
+ /** 置き換えタグの形(#{&p} #{&n} #{&f(fileKey)} #{&q(文字列)}) */
24
+ export declare const PLACEHOLDER_RE: RegExp;
25
+ /**
26
+ * URL を Chrome の URL パーサーと同じ前処理で整える: 両端の引用符、両端の C0 制御文字と空白を外し、途中のタブ・改行・復帰を捨てる。
27
+ * 分類(classifyUrl)と承認の照合(policy)の両方でこれを使う。
28
+ */
29
+ export declare function cleanUrl(raw: string): string;
30
+ /** URL の分類(HTML の属性と共通) */
31
+ export declare function classifyUrl(raw: string): UrlKind;
32
+ /**
33
+ * srcset の候補から URL だけを取り出す(HTML の仕様の手順を簡略化: 空白と , を読み飛ばし、URL は空白まで、
34
+ * URL の末尾の , は区切り。記述子は次の , まで(括弧の中の , は除く)。data: URL の中の , で壊れない)
35
+ */
36
+ export declare function parseSrcsetUrls(value: string): string[];
37
+ /** コメントを除く(文字列の中の /* は壊さない) */
38
+ export declare function stripCssComments(css: string): string;
39
+ export interface CssTokens {
40
+ /** コメント無し・文字列は \u0001N\u0001 の印・エスケープは復号済み */
41
+ code: string;
42
+ /** 印の番号 → 文字列の中身(復号済み) */
43
+ strings: string[];
44
+ }
45
+ /** CSS の簡易トークナイザー(コメント、文字列、エスケープ) */
46
+ export declare function tokenizeCss(css: string): CssTokens;
47
+ /** CSS のエスケープを復号する(文字列の外の走査用。tokenizeCss と同じ規則) */
48
+ export declare function decodeCssEscapes(text: string): string;
49
+ /** 検査用の本文(デバッグ用。コメント無し・復号済み。文字列は "" に) */
50
+ export declare function prepareCss(css: string): string;
51
+ /** url(...) と URL を持てる関数・@import の中身を取り出す(引用符あり / なし。#{&f(...)} を含むときは )} まで) */
52
+ export declare function extractUrls(css: string): CssUrl[];
53
+ export declare function checkCss(css: string): CssCheckResult;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 派生値の生成(docs/authoring-plan.md 12.2。段階 0 の work/authoring-spike/spike-normalize.mjs の移植 + 更新項目の行の再構成)。印刷屋のコードは API から使う。
3
+ * 入力にあった派生値は信用せず上書きする:
4
+ * - HTML 設定の各行: id、formula(formulaSet からコメントを除いたもの)、usedFields(実エンジンで crec を評価)
5
+ * - 更新項目: 行の並びと state / formulaSet / remark は AI のまま、type / ptcode / row_type / lookup / fieldlabel / required は
6
+ * fields + layout の一覧(createFieldsInfo)で上書き(設定画面の buildCalcRows と同じ)。一覧に無い項目はエラー。先頭は $out(無ければ既定の "1" を足す)。
7
+ * 一覧にあって入力に無い項目は足さない(設定画面の「未使用を除く」の後の形)。入力が [] なら [] のまま(dialog を開いていないボタン)。
8
+ * calcInfo.usedFields は有効な行の和、flinkage は false
9
+ * - views(viewsCsv から)、id の振り直し(toSavedRows)、ルートの usedFields と pluginUOG(computeUsage)
10
+ */
11
+ import type { Engine } from "../engine.ts";
12
+ import type { Findings } from "./findings.ts";
13
+ import { type Model } from "./model.ts";
14
+ import type { MenuRow, TagRow } from "../_print-craft/src/config/schema.ts";
15
+ /** 封筒のキー(kit の export-import.ts と同じ) */
16
+ export declare const ENVELOPE_KEYS: readonly ["date", "pluginName", "pluginID", "PluginVersion", "appId", "appName"];
17
+ /** 外枠(kit の shell)が付け足すキー。CONFIG_SCHEMA に無く、インポートで落ちる */
18
+ export declare const SHELL_KEYS: readonly ["pluginProductEnv", "pluginLastUpdate", "pluginUpdater", "startDate", "name", "version", "ldate"];
19
+ export interface EvalResult {
20
+ formula: string;
21
+ usedFields: Record<string, unknown>;
22
+ error?: string;
23
+ }
24
+ /** 設定画面の formulaRule と同じ: 検証用レコードで評価して usedFields を取る */
25
+ export declare function evaluateFormula(engine: Engine, model: Model, formulaSet: string): EvalResult;
26
+ export declare function rowLabel(row: MenuRow, index: number): string;
27
+ export declare function tagRowLabel(tag: TagRow, index: number): string;
28
+ /** 設定本体(封筒と外枠のキーを除いたもの)を取り出す */
29
+ export declare function bodyOf(envelope: Record<string, unknown>): Record<string, unknown>;
30
+ export declare function deriveBody(input: Record<string, unknown>, model: Model, engine: Engine, f: Findings): Record<string, unknown>;
@@ -0,0 +1,21 @@
1
+ /** normalize の検査結果(docs/authoring-plan.md 12.3。エラー / 警告 / 情報) */
2
+ export type Level = "error" | "warning" | "info";
3
+ export interface Finding {
4
+ level: Level;
5
+ /** 規則の名前(機械可読。例 html.script、field.filecode) */
6
+ rule: string;
7
+ /** 場所(例 「見積書 / HTML 設定 3 行目 (本文)」) */
8
+ where: string;
9
+ message: string;
10
+ }
11
+ export declare class Findings {
12
+ readonly items: Finding[];
13
+ add(level: Level, rule: string, where: string, message: string): void;
14
+ error(rule: string, where: string, message: string): void;
15
+ warning(rule: string, where: string, message: string): void;
16
+ info(rule: string, where: string, message: string): void;
17
+ count(level: Level): number;
18
+ get hasErrors(): boolean;
19
+ /** 画面に出す表(レベル → 場所 → 文言) */
20
+ format(): string;
21
+ }
@@ -0,0 +1,23 @@
1
+ export { parseSrcsetUrls } from "./css-check.ts";
2
+ export interface HtmlExternal {
3
+ url: string;
4
+ /** 例 >div>img[src]、iframe[src]、<style> url() */
5
+ via: string;
6
+ }
7
+ export interface HtmlCheckResult {
8
+ errors: string[];
9
+ warnings: string[];
10
+ externals: HtmlExternal[];
11
+ }
12
+ export declare const ALLOWED_TAGS: Set<string>;
13
+ /** URL として分類する属性 */
14
+ export declare const URL_ATTRS: Set<string>;
15
+ /** 要素が使えないときの文言(使えれば null)。計算式の TAG / VTAG の要素名の検査にも使う */
16
+ export declare function tagError(tag: string, where?: string): string | null;
17
+ /** 属性が使えるか(tag が分からないときは、どの要素でも使える属性か、どれかの要素で使える属性か) */
18
+ export declare function attrAllowed(tag: string | undefined, name: string): boolean;
19
+ export declare function checkHtml(html: string, opt?: {
20
+ baseUrl?: string;
21
+ }): Promise<HtmlCheckResult>;
22
+ /** HTML の ${式} を列挙する(生の差し込みの警告用) */
23
+ export declare function expressionsOf(html: string): string[];
@@ -0,0 +1,8 @@
1
+ /** 行の差分(LCS。設定の HTML / CSS / 式の比較用。大きすぎるときは全体の置き換えとして返す) */
2
+ export interface DiffLine {
3
+ kind: " " | "-" | "+";
4
+ text: string;
5
+ }
6
+ export declare function lineDiff(a: string, b: string): DiffLine[];
7
+ /** 変わった行と前後 context 行だけにする */
8
+ export declare function formatDiff(lines: DiffLine[], context?: number): string;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * fields/<app>.json(fields コマンドの出力)から、設定画面と同じ項目の模型を作る(docs/authoring-plan.md 12.2)。印刷屋のコードは API(engine.api)から使う。
3
+ * pp … properties + $id / $revision / $html → createCheckRecord(テーブルの子を ptcode 付きで平らに足す)。設定画面の load.ts 204〜214 行と同じ作り方
4
+ * crec … 計算式の検証用レコード(空の値)
5
+ * ppRun … 実行用(preview)。デスクトップと同じ expandFields
6
+ * calcCandidates … 更新項目にできる項目(createFieldsInfo。テーブルの子を除く)
7
+ */
8
+ import type { PrintCraftAuthoringApi } from "../_print-craft/src/authoring/api.ts";
9
+ import type { FieldInfo, FieldProp } from "../_print-craft/src/config/load.ts";
10
+ import type { FieldsFile } from "../commands/fields.ts";
11
+ export declare const PSEUDO_FIELDS: Set<string>;
12
+ /** UINFO / OINFO / GINFO を使った印(項目ではない。lib 26 行) */
13
+ export declare const UOG_MARK = "$UGO$";
14
+ export declare const EXEC_CONDITION_LABEL = "\u5B9F\u884C\u6761\u4EF6";
15
+ export interface Model {
16
+ api: PrintCraftAuthoringApi;
17
+ file: FieldsFile;
18
+ /** .env の KINTONE_BASE_URL(検証済み)。無ければ ""(iframe は使えない) */
19
+ baseUrl: string;
20
+ /** fields の baseUrl(kintone のドメインなら正規化、違えば "")。表示と警告だけに使う */
21
+ fieldsBaseUrl: string;
22
+ appId: number;
23
+ pp: Record<string, FieldProp>;
24
+ crec: Record<string, unknown>;
25
+ ppRun: Record<string, FieldProp>;
26
+ calcCandidates: FieldInfo[];
27
+ calcByCode: Map<string, FieldInfo>;
28
+ }
29
+ /**
30
+ * @param trustedBaseUrl .env の KINTONE_BASE_URL(検証済み)。iframe の同一オリジンの判定はこれだけを使う(無ければ iframe は使えない)
31
+ */
32
+ export declare function buildModel(file: FieldsFile, api: PrintCraftAuthoringApi, trustedBaseUrl?: string): Model;
33
+ /** 項目コードが使えるか(usedFields の実在チェック。12.3) */
34
+ export declare function fieldExists(model: Model, code: string): boolean;
35
+ /** 更新項目にできない理由(できれば null) */
36
+ export declare function calcIneligibleReason(model: Model, code: string): string | null;
@@ -0,0 +1,29 @@
1
+ export interface AllowRule {
2
+ origin?: string;
3
+ url?: string;
4
+ files?: string[];
5
+ note?: string;
6
+ }
7
+ export interface Policy {
8
+ allowExternal: AllowRule[];
9
+ /** externalRefs: "allow" を許す設定ファイル(正規化した相対パス) */
10
+ allowExternalRefs?: string[];
11
+ /** 読んだファイル(無ければ undefined) */
12
+ file?: string;
13
+ }
14
+ export declare class PolicyError extends Error {
15
+ }
16
+ export declare const POLICY_FILE: string;
17
+ export declare const DEFAULT_ALLOWED_ORIGINS: string[];
18
+ /** 相対パスの正規化(\ → /、./ を外す、連続する / を 1 つに。Windows は小文字に)。.. や絶対パスは使えない */
19
+ export declare function normalizeRel(p: string): string;
20
+ /** policy の JSON を検証して読む(未知のキー、型、件数、URL の形) */
21
+ export declare function parsePolicy(text: string, file: string): Policy;
22
+ /** 設定ファイルが externalRefs: "allow" を使ってよいか(settingsFile は cwd からの相対パス。分からなければ許さない) */
23
+ export declare function isExternalRefsAllowed(policy: Policy, settingsFile?: string): boolean;
24
+ /** リポジトリ(cwd)の policy/authoring-policy.json を読む。無ければ承認なし */
25
+ export declare function loadPolicy(opt: {
26
+ cwd: string;
27
+ }): Policy;
28
+ /** URL が承認済みか(settingsFile は cwd からの相対パス) */
29
+ export declare function isAllowed(policy: Policy, url: string, settingsFile?: string): boolean;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 保存値の大きさ(docs/authoring-plan.md 12.3、Codex MAJOR 6)。印刷屋の API 経由で kit の writeConfig(print-craft の保存形式 compressed)を呼び、
3
+ * kintone の制限(1 値 65,535 文字、合計 256 KB)を設定画面と同じコードで検査する。表示の合計も kit の checkLimits と同じくキー + 値のバイト数。
4
+ */
5
+ import type { PrintCraftAuthoringApi } from "../_print-craft/src/authoring/api.ts";
6
+ export interface StoredSize {
7
+ ok: boolean;
8
+ totalBytes: number;
9
+ maxTotalBytes: number;
10
+ splitCount: number;
11
+ maxValueLength: number;
12
+ maxValueLimit: number;
13
+ error?: string;
14
+ }
15
+ export declare function measureStored(data: unknown, api: PrintCraftAuthoringApi): Promise<StoredSize>;
16
+ export declare function formatSize(s: StoredSize): string;
@@ -0,0 +1,7 @@
1
+ /** tools/ */
2
+ export declare const AUTHORING_ROOT: string;
3
+ /** リポジトリ print-craft-authoring のルート(テンプレートの置き場所) */
4
+ export declare const REPO_ROOT: string;
5
+ export declare const VENDOR_DIR: string;
6
+ export declare const MOMENT_URL = "https://js.cybozu.com/momentjs/2.24.0/moment-with-locales.min.js";
7
+ export declare const MOMENT_FILE: string;
@@ -0,0 +1,21 @@
1
+ import { type EnvRole } from "./workspace.ts";
2
+ export declare class PermissionError extends Error {
3
+ }
4
+ export type ChangeOp = "settings" | "snapshot" | "fields" | "record" | "preview";
5
+ /** アプリのフォルダーの中の場所(docs/permission-table.md の P4〜P9) */
6
+ export type TargetClass = "snapshot" | "edit" | "report" | "fields" | "record" | "out" | "other";
7
+ export interface TargetRole {
8
+ role: EnvRole;
9
+ /** 環境の名前(分かるとき) */
10
+ envName?: string;
11
+ /** 未分類の理由 */
12
+ why?: string;
13
+ /** アプリのフォルダーの中の場所(フォルダーが分かるとき) */
14
+ cls?: TargetClass;
15
+ }
16
+ /** アプリのフォルダーからの相対パスで場所を分ける */
17
+ export declare function classOfAppPath(relInFolder: string): TargetClass;
18
+ /** kintone/ の下のファイルの環境・役割・場所(kintone/ の外なら null)。environments.json はその場で読む */
19
+ export declare function roleOfTarget(root: string, file: string): TargetRole | null;
20
+ /** kintone/ の下をこの操作で変えてよいか。だめなら PermissionError(決まった文) */
21
+ export declare function assertChangeAllowed(root: string, file: string, op: ChangeOp): void;
@@ -0,0 +1,53 @@
1
+ export declare class PluginZipError extends Error {
2
+ }
3
+ export interface ZipLimits {
4
+ maxOuterBytes: number;
5
+ maxEntries: number;
6
+ maxEntryBytes: number;
7
+ maxTotalBytes: number;
8
+ }
9
+ /** 印刷屋の zip は 1 MB 程度。余裕を見た上限 */
10
+ export declare const ZIP_LIMITS: ZipLimits;
11
+ /** CRC-32(zip と同じ。Node 20 には zlib.crc32 が無いので自前) */
12
+ export declare function crc32(buf: Uint8Array): number;
13
+ /** zip の全エントリーを { 名前 → 中身 } に展開する(上限と整合性を確かめる) */
14
+ export declare function unzip(buf: Buffer, limits?: ZipLimits): Map<string, Buffer>;
15
+ export interface PluginManifest {
16
+ manifest_version?: number;
17
+ version?: number | string;
18
+ name?: Record<string, string>;
19
+ [key: string]: unknown;
20
+ }
21
+ export interface PluginSources {
22
+ /** 入力(zip のパス、または開発中の print-craft のフォルダー) */
23
+ from: string;
24
+ manifest: PluginManifest;
25
+ pluginVersion: string;
26
+ engine: string;
27
+ bignumber: string;
28
+ momentTimezone: string;
29
+ /** 印刷屋の authoring API(Ver.6 以降の zip にある。無ければ undefined) */
30
+ api?: string;
31
+ /** プラグイン ID(zip の PUBKEY から。開発中のフォルダーと PUBKEY の無い zip は undefined) */
32
+ pluginId?: string;
33
+ sha256: {
34
+ engine: string;
35
+ api?: string;
36
+ bignumber: string;
37
+ momentTimezone: string;
38
+ contents?: string;
39
+ };
40
+ }
41
+ export declare const ENGINE_ENTRY = "desktop_js/KintoneFormulaPCraft.min.js";
42
+ export declare const BIGNUMBER_ENTRY = "desktop_js/bignumber.min.js";
43
+ export declare const MOMENT_TZ_ENTRY = "desktop_js/moment-timezone-with-data.min.js";
44
+ export declare const API_ENTRY = "config_js/print-craft-authoring-api.js";
45
+ export declare const MANIFEST_ENTRY = "manifest.json";
46
+ export declare function sha256Hex(data: string | Buffer): string;
47
+ /**
48
+ * プラグイン ID(kintone の @kintone/plugin-packer の uuid と同じ: 外側の zip の PUBKEY(公開鍵の DER)の SHA-256 の先頭 32 桁を 0-9a-f → a-p)。
49
+ * 印刷屋は 5 変種とも同じ鍵で作るので同じ ID(pull がプラグインの設定を取るときの id。2026-10-05)
50
+ */
51
+ export declare function pluginIdOf(publicKey: Buffer): string;
52
+ /** 印刷屋の zip(2 層)から tools が要るものを取り出す */
53
+ export declare function readPluginZip(file: string): PluginSources;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 帳票 HTML のプレビュー(docs/authoring-plan.md 12.2 の preview、Codex BLOCKER 1 / MAJOR 4 の反映。1-10 レビュー BLOCKER 4)。印刷屋のコードは API(engine.api)から。
3
+ * - CSS は印刷屋と同じ buildReportCss(ページの基本 → 共通 CSS → 行の CSS)。文書に入れる前に `<` を CSS のエスケープ(\3c)にして、CSS から </style> で抜けられないようにする
4
+ * - HTML は authoring 専用の行単位レンダラー: ${式} ごと・行の計算式ごとに catch し、失敗した式はエスケープして赤字で埋めて続ける
5
+ * - #{&f(…)} / #{&q(…)} はダミー画像、#{&p} / #{&n} はページ番号(印刷屋の replaceTags を happy-dom の DOM で動かす)
6
+ * - 描いた DOM から、動きや通信や遷移の元になる要素と属性を外す(script / meta / link / form / iframe / SMIL …、on*、href、srcdoc …)。
7
+ * レコードの値が TABLE_HTML などで HTML として入る経路があるため、テンプレートの検査(html-check)とは別にここでも外す
8
+ * - 出力は 2 層の HTML: 外側の文書の中に sandbox 属性だけの iframe を置き、帳票の文書を srcdoc で入れる。帳票の文書にも CSP(img は data: だけ)
9
+ * - Web フォント(Takashi 2026-10-05「preview で、指定した WEB フォントを利用できるようにすることは可能か?」→ Go): 配信元が承認済み(Google Fonts は既定、
10
+ * 他は policy の allowExternal)のときだけ、帳票の文書に <link rel="stylesheet"> を入れ、CSP の style-src / font-src にその配信元を足す
11
+ * (Google Fonts は fonts.googleapis.com と fonts.gstatic.com)。preview の外部通信はこれだけで、送るのは設定に書いた固定の URL。未承認なら読まない(OS の書体)
12
+ */
13
+ import type { PrintCraftAuthoringApi } from "../_print-craft/src/authoring/api.ts";
14
+ import type { MenuRow } from "../_print-craft/src/config/schema.ts";
15
+ import type { Engine, FormulaInstance } from "../engine.ts";
16
+ import type { Model } from "../normalize/model.ts";
17
+ import type { KintoneRecord } from "../commands/record.ts";
18
+ export declare const PREVIEW_CSP = "default-src 'none'; img-src data:; style-src 'unsafe-inline'; font-src data:; connect-src 'none'; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'";
19
+ export declare const OUTER_CSP = "script-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'none'";
20
+ /** 帳票の文書に入れる Web フォント(印刷屋の webFontOf と同じ family / cssUrl) */
21
+ export interface PreviewFont {
22
+ family: string;
23
+ cssUrl: string;
24
+ }
25
+ /** Web フォントの CSS とフォント本体の配信元(CSP に書く)。Google Fonts は CSS が fonts.googleapis.com、本体が fonts.gstatic.com。https 以外は null */
26
+ export declare function fontOrigins(cssUrl: string): {
27
+ style: string[];
28
+ font: string[];
29
+ } | null;
30
+ /** 帳票の文書の CSP。承認済みの Web フォントがあれば、その配信元だけを style-src / font-src に足す */
31
+ export declare function previewCsp(font: PreviewFont | null): string;
32
+ /** プレビューの DOM から外す要素(動き・通信・遷移の元。描画には要らない) */
33
+ export declare const PREVIEW_REMOVE_SELECTOR = "script,meta,link,base,form,input,button,select,textarea,iframe,frame,object,embed,applet,noscript,template,video,audio,source,track,canvas,map,area,animate,animatemotion,animatetransform,animatecolor,set,foreignobject,math";
34
+ export declare function escapeHtml(s: string): string;
35
+ /** <style> の中に入れる CSS: `<` を CSS のエスケープにして、</style> や <!-- で文書を壊せないようにする(文字列の中の < も同じ見た目になる) */
36
+ export declare function escapeCssText(css: string): string;
37
+ export interface RenderedButton {
38
+ menu: string;
39
+ fileName: string;
40
+ pageSize: string;
41
+ orientation: string;
42
+ dpi: string;
43
+ pages: number;
44
+ errors: string[];
45
+ /** 帳票の文書に入れた Web フォントの CSS の URL(承認済みのときだけ。無ければ null) */
46
+ webFont: string | null;
47
+ inner: string;
48
+ html: string;
49
+ }
50
+ /** authoring 専用の行単位レンダラー(印刷屋の buildReportHtml と同じ順序・同じ \ → &yen; の置き換え。失敗しても続ける) */
51
+ export declare function renderRows(api: PrintCraftAuthoringApi, row: MenuRow, record: KintoneRecord, kf: FormulaInstance, errors: string[]): string;
52
+ interface DomElement {
53
+ tagName: string;
54
+ attributes: ArrayLike<{
55
+ name: string;
56
+ value: string;
57
+ }>;
58
+ textContent: string | null;
59
+ innerHTML: string;
60
+ querySelectorAll(selector: string): ArrayLike<DomElement>;
61
+ removeAttribute(name: string): void;
62
+ remove(): void;
63
+ }
64
+ /** 描いた DOM から動き・通信・遷移の元を外す。外した数を返す */
65
+ export declare function sanitizePreviewDom(host: DomElement): {
66
+ removedElements: number;
67
+ removedAttributes: number;
68
+ };
69
+ export interface RenderInput {
70
+ body: Record<string, unknown>;
71
+ row: MenuRow;
72
+ model: Model;
73
+ engine: Engine;
74
+ record: KintoneRecord;
75
+ /** 設定の Web フォント(有効なとき)と、配信元が承認済みか(policy。Google Fonts は既定で承認) */
76
+ webFont?: {
77
+ font: PreviewFont;
78
+ approved: boolean;
79
+ } | null;
80
+ }
81
+ export declare function renderButton(input: RenderInput): RenderedButton;
82
+ export {};
@@ -0,0 +1,24 @@
1
+ export declare class PathError extends Error {
2
+ }
3
+ /** 書き込みを許す場所(cwd からの相対)。kintone/ は environments.json があるときのアプリのフォルダー(workspace.ts) */
4
+ export declare const WRITE_ROOTS: {
5
+ readonly fields: readonly ["fields", "kintone"];
6
+ readonly records: readonly ["records", "kintone"];
7
+ readonly settings: readonly ["settings", "temp", "kintone"];
8
+ readonly out: readonly ["out", "kintone"];
9
+ readonly kintone: readonly ["kintone"];
10
+ };
11
+ /**
12
+ * 存在する最も深い親の realpath に残りを足した絶対パス。
13
+ * 親を探すのは lstat で「本当に無い」(ENOENT / ENOTDIR)ときだけ上がり、リンク切れ・ループ・アクセス不能は止める(fail closed。再レビュー MAJOR 5)
14
+ */
15
+ export declare function realResolve(target: string, cwd: string): string;
16
+ export declare function isInside(child: string, parent: string): boolean;
17
+ /** 読む入力(設定 JSON、fields、record): cwd の中。.env と node_modules と .git は読まない */
18
+ export declare function resolveRead(target: string, cwd: string): string;
19
+ /** 書き込み先: cwd の中の roots のどれかの下(root そのものではない)。返すのは絶対パス */
20
+ export declare function resolveWrite(target: string, roots: readonly string[], cwd: string): string;
21
+ /** 書き込み先のフォルダー(preview の --out-dir): cwd の中の roots のどれか、またはその下 */
22
+ export declare function resolveWriteDir(target: string, roots: readonly string[], cwd: string): string;
23
+ /** ファイル名に使えない文字と Windows の予約名を避ける(preview の out/<ボタン名>.html) */
24
+ export declare function safeFileName(name: string, fallback: string): string;