Šķîþ ţö ḿàîñ çöñţéñţ

Ţĥé çĥàñĝé àþþļîéŕ: core/change

Éṽéŕý çĥàñĝé ţö à ƃļöçķ'š çöñţéñţ ĝöéš ţĥŕöüĝĥ öñé ƒüñçţîöñ, change.ApplyBlock. Ţĥîš ñöţé çöṽéŕš ţĥé þàçķàĝé ţĥàţ ĥöļđš îţ: ţĥé çĥàñĝé-šéţ çöñţŕàçţ, ţĥé ŕüļéš àñ öþéŕàţîöñ öƃéýš, ŵĥàţ à ƒöŕḿàţ đéçļàŕéš îţ çàñ ŵŕîţé, àñđ ĥöŵ ţööļš îñ à ƒļöŵ ŕéàçĥ îţ. Ţĥé þàçķàĝé îḿþöŕţš core/model, core/format àñđ core/safeio àñđ ñöţĥîñĝ ƒŕöḿ ţĥé ĥöšţ, ţĥé ÇĻÎ öŕ àñý šüŕƒàçé, šö éṽéŕý šüŕƒàçé çàñ ƃüîļđ öñ îţ.

Ţĥé çöñţŕàçţ ţýþéš​

À çĥàñĝé šéţ (change.Set) îš àñ éñṽéļöþé öƒ öŕđéŕéđ öþéŕàţîöñš (change.Op) üñđéŕ ţĥé šçĥéḿà kapi.change/v1. Ţĥé éñṽéļöþé çàŕŕîéš mode (apply öŕ preview), gate (enforce öŕ report), require_basis, à note àñđ evidence (éàçĥ éñţŕý à ƒîļé'š path, ţĥé block ķéý à ŕéàđ ŕéþöŕţš, à quote öŕ à url). Îţ ĥàš ñö àçţöŕ ƒîéļđ: ţĥé ţŕàñšþöŕţ ţĥàţ çàŕŕîéš à çĥàñĝé šéţ šàýš ŵĥö šéñţ îţ, àñđ ApplyBlock ţàķéš ţĥé šéñđéŕ îñ îţš BlockEnv.

Àñ öþéŕàţîöñ îš ƒļàţ öñ ţĥé ŵîŕé, {"op": kind, "at": …, "if_match": …, …}. Op ĥöļđš ţĥé ķîñđ, ţĥé àđđŕéšš (change.Ref: đöçüḿéñţ, ƃļöçķ, éđîţîöñ), ţĥé þŕéçöñđîţîöñ, ţĥé ƃàšîš öƒ à đéŕîṽéđ éđîţîöñ, àñđ à ƃöđý ŵĥöšé ţýþé ḿàţçĥéš ţĥé ķîñđ (*change.SetContent, *change.ReplaceText, àñđ šö öñ). Ţĥé éđîţîöñ îñ à ŕéƒéŕéñçé îš þàŕšéđ ŵîţĥ model.ParseEditionKey, ŵĥîçĥ ķééþš îţ çàñöñîçàļ àñđ ŕéƒüšéš à ļàñĝüàĝé ţĥàţ îš ñöţ à ļöçàļé öŕ à đîḿéñšîöñ öţĥéŕ ţĥàñ ţöñé àñđ çĥàññéļ.

change.Decode ŕéàđš à çĥàñĝé šéţ àš öñé öƃĵéçţ, àš ĴŠÖÑĻ ŵîţĥ ţĥé éñṽéļöþé öñ îţš ƒîŕšţ ļîñé, öŕ àš àñ àŕŕàý öƒ öþéŕàţîöñš. Đéçöđîñĝ îš šţŕîçţ: àñ üñķñöŵñ ƒîéļđ, àñ üñķñöŵñ öþéŕàţîöñ, à ḿîššîñĝ ŕéǫüîŕéđ ƒîéļđ, à null, à ṽàļüé öƒ ţĥé ŵŕöñĝ ţýþé àñđ à ŕüñ þàýļöàđ ţĥàţ çàŕŕîéš ñàţîṽé data àŕé ŕéƒüšéđ àš invalid, àñđ ţĥé éŕŕöŕ'š Pointer îš ţĥé ĴŠÖÑ þöîñţéŕ öƒ ţĥé ṽàļüé àţ ƒàüļţ (/ops/2/edits/0/find).

changeschema.Schema (core/change/changeschema) îš ţĥé ĴŠÖÑ Šçĥéḿà öƒ à çĥàñĝé šéţ, ĝéñéŕàţéđ ƒŕöḿ ţĥé šàḿé Ĝö ţýþéš ŵîţĥ github.com/google/jsonschema-go; change.Operations đéšçŕîƃéš éàçĥ öþéŕàţîöñ ƒöŕ îţ. Îţ šîţš îñ îţš öŵñ þàçķàĝé šö ţĥàţ ţĥé àþþļîéŕ, ŵĥîçĥ éṽéŕý ţööļ ļîñķš, çàŕŕîéš ñö šçĥéḿà ĝéñéŕàţöŕ. Éàçĥ öþéŕàţîöñ îš à oneOf ḿéḿƃéŕ ŵĥöšé op îš à const àñđ ŵĥîçĥ àļļöŵš ñö öţĥéŕ þŕöþéŕţîéš. core/change/testdata/schema.golden.json þîñš îţ; ŕéĝéñéŕàţé îţ ŵîţĥ go test ./core/change -run TestSchemaGolden -update. À ţéšţ ṽàļîđàţéš ţĥé çöñţŕàçţ'š éẋàḿþļéš àĝàîñšţ ţĥé šçĥéḿà àñđ ţĥé đéçöđéŕ àļîķé, šö ţĥé ţŵö çàññöţ đŕîƒţ àþàŕţ. changeschema.ResultSchema àñđ changeschema.ReadSchema àŕé ţĥé šçĥéḿàš öƒ à ŕéšüļţ àñđ öƒ à ŕéàđ þàĝé, ĝéñéŕàţéđ ƒŕöḿ ţĥé šţŕüçţš ţĥé šéŕṽîçé ḿàŕšĥàļš ŵîţĥ ţĥé šàḿé ļîƃŕàŕý: ţĥé ƒîŕšţ îš ţĥé öüţþüţ šçĥéḿà öƒ ţĥé apply_edits ţööļ, àñđ result.golden.json àñđ read.golden.json þîñ ƃöţĥ (go test ./core/change -run TestReplySchemaGoldens -update).

Ţĥé çöñţŕàçţ îš ƒŕöžéñ. schema.v1.frozen.json, result.v1.frozen.json àñđ read.v1.frozen.json àŕé ţĥé ĝöļđéñš àţ ţĥé ƒŕééžé, éàçĥ ŵîţĥ à $comment ñàḿîñĝ ţĥé ŕéļéàšé àñđ ţĥé đàţé îţ ƒŕöžé ƒöŕ (1.3.0, 2026-10-03), àñđ ñöţĥîñĝ ŕéĝéñéŕàţéš ţĥéḿ. changeschema.Extends(frozen, current, side) ŵàļķš à ƒŕöžéñ šçĥéḿà ƃéšîđé ţĥé ĝéñéŕàţéđ öñé, þŕöþéŕţîéš àñđ $defs ƃý ñàḿé, oneOf ḿéḿƃéŕš ƃý ţĥéîŕ op çöñšţ öŕ ţĥéîŕ ŕéǫüîŕéđ ƒîéļđš, àñđ ŕéþöŕţš éàçĥ đéŕéñçé ţĥàţ ƃŕéàķš ţĥé Writer (à ŕéǫüéšţ) öŕ ţĥé Reader (à ŕéþļý) šîđé; TestSchemaExtendsFrozenV1, TestResultSchemaExtendsFrozenV1 àñđ TestReadSchemaExtendsFrozenV1 ƒàîļ öñ àñý, àñđ TestExtends_RequestSide ĥöļđš ţĥé ŵàļķ ţö ţĥé çàšéš îţ ḿüšţ ŕéƒüšé àñđ àļļöŵ. kapi/cmd/kapi/testdata/mcp_tools.frozen.json ĥöļđš ţĥé ḾÇÞ ţööļ šüŕƒàçé ţĥé šàḿé ŵàý (TestMCPToolSurfaceExtendsFrozen), îţš ţööļ ñàḿéš à šéţ ţĥàţ ḿàý öñļý ĝŕöŵ.

Ŕéƒüšàļš üšé à çļöšéđ šéţ öƒ çöđéš (change.Code), éàçĥ ḿàþþéđ öñçé ţö àñ éẋîţ çöđé (ExitCode: 2 ƒöŕ invalid, 5 ƒöŕ unreachable, 3 ƒöŕ ţĥé ŕéšţ) àñđ àñ ĤŢŢÞ šţàţüš (HTTPStatus).

ŢýþéŠçŕîþţ ţýþéš​

À ŢýþéŠçŕîþţ çļîéñţ îḿþöŕţš ţĥé çöñţŕàçţ ƒŕöḿ @neokapi/contract-types (packages/contract-types, Àþàçĥé-2.0). Îţš change.gen.ts îš ĝéñéŕàţéđ ƃý scripts/gen-contract-types ƒŕöḿ ţĥé šàḿé šöüŕçéš ţĥé šéŕṽîçé üšéš. ChangeSet àñđ ţĥé ChangeOp üñîöñ, öñé îñţéŕƒàçé þéŕ öþéŕàţîöñ ñàḿéđ àƒţéŕ îţ (SetContentOp, ReplaceTextOp, …), àŕé ŕéñđéŕéđ ƒŕöḿ changeschema.Schema. À çĥöîçé öƒ éẋàçţļý öñé ƒîéļđ ƃéçöḿéš à üñîöñ ţĥàţ ŕéƒüšéš ţĥé öţĥéŕš, šö à set_content ŵîţĥ ƃöţĥ text àñđ runs, àñ éđîţ ţĥàţ ñàḿéš îţš ţéẋţ ƃý find àñđ ƃý start àţ öñçé, öŕ à ŕüñ ţĥàţ çàŕŕîéš ñàţîṽé data ƒàîļš ţö çöḿþîļé, àš ţĥé đéçöđéŕ ŕéƒüšéš îţ. Ḿéḿƃéŕš ţĥàţ à šçĥéḿà ţéļļš àþàŕţ ƃý ţĥé ƒîéļđš ţĥéý ĥöļđ ŕàţĥéŕ ţĥàñ ƃý à çöñšţàñţ (à ŕüñ îš text, ph, pcOpen àñđ šö öñ; à þàţĥ šţéþ îš à plural ƒöŕḿ öŕ à select çàšé) éàçĥ đéçļàŕé ţĥé öţĥéŕ ḿéḿƃéŕš' ƒîéļđš àš never, šö à ŕüñ öƒ ţŵö ķîñđš ƒàîļš ţö çöḿþîļé ţöö. Ţĥé ţýþéš çàŕŕý ţĥé šţŕüçţüŕé ţĥé šçĥéḿà šţàţéš; à þàţţéŕñ, à ƃöüñđ öŕ à ŕüļé ƃéţŵééñ ƒîéļđš (à ŕéṽîšîöñ'š ƒöŕḿ, occurrence öñļý ƃéšîđé find) îš đöçüḿéñţéđ öñ ţĥé ƒîéļđ àñđ çĥéçķéđ ƃý ţĥé đéçöđéŕ àļöñé. Ţĥé ŕéþļîéš àŕé ŕéƒļéçţéđ ƒŕöḿ ţĥé šţŕüçţš ţĥé šéŕṽîçé ḿàŕšĥàļš, ŵîţĥ ţĥé đöç çöḿḿéñţš öƒ ţĥéîŕ Ĝö đéçļàŕàţîöñš: ChangeResult, OpResult, ChangeError àñđ ResultRef ƒöŕ à ŕéšüļţ, ReadPage àñđ BlockRead ƒöŕ à ŕéàđ, FormatDescription ƒöŕ Describe, àñđ EditionHistory àñđ HistoryEntry ƒöŕ History. À ŕéàđ'š çöđéš çàŕŕý éàçĥ çöđé'š equiv àñđ disp, ŵĥîçĥ àñ éđîţöŕ ļàƃéļš à çĥîþ ŵîţĥ, àñđ ļéàṽé öüţ éîţĥéŕ öñé ţĥàţ ŕéþéàţš ţĥé çöđé'š ñàţîṽé ƒöŕḿ, àš àñ ÀŔƂ ŕéàđéŕ'š ÎÇÜ àŕĝüḿéñţ öŕ à þŕîñţƒ šþéçîƒîéŕ đöéš; editTextToCoded àñđ codedToEditText îñ @neokapi/ui-primitives ţüŕñ à ŕéàđ'š þļàçéĥöļđéŕ ţéẋţ îñţö ţĥé îñļîñé-çöđé éđîţöŕ'š çöđéđ ţéẋţ àñđ ƃàçķ, öñé ţöķéñ ţö öñé çĥîþ. À çĥàñĝé šéţ ŕéƒüšéđ àš à ŵĥöļé îš à ChangeResult ţöö, ŵĥöšé error šàýš ŵĥý. À ŕéàđ'š ref îš à ChangeRef àñđ îţš rev à šţŕîñĝ, šö à çļîéñţ çöþîéš ƃöţĥ îñţö àñ öþéŕàţîöñ üñçĥàñĝéđ. Ţĥé öþéŕàţîöñ ķîñđš, šţàţüšéš, éŕŕöŕ çöđéš àñđ ĝüàŕđ šüƃçöđéš àŕé üñîöñš ŵîţĥ ƒŕöžéñ ļîšţš öƒ ţĥéîŕ ḿéḿƃéŕš, àñđ CHANGE_ERROR_HTTP_STATUS àñđ CHANGE_ERROR_EXIT_CODE ĥöļđ éàçĥ çöđé'š ḿàþþîñĝ. Àñ öþéŕàţîöñ'š ŕéšüļţ ñàḿéš à ResultOpKind, ŵĥîçĥ àđđš ţĥé þŕöṽéñàñçé öþéŕàţîöñ à ţööļ àþþļîéš îñ þŕöçéšš ţö ţĥé ķîñđš à çĥàñĝé šéţ çàŕŕîéš.

Ţĥé ĝéñéŕàţöŕ ƒàîļš öñ à šçĥéḿà ķéýŵöŕđ öŕ à çöḿƃîñàţîöñ öƒ ķéýŵöŕđš îţ đöéš ñöţ ŕéñđéŕ, öñ à Ĝö ţýþé ţĥàţ ḿàŕšĥàļš îţšéļƒ àñđ ĥàš ñö ŢýþéŠçŕîþţ ñàḿé, öñ à đéçļàŕéđ ñàḿé ḿîššîñĝ ƒŕöḿ ţĥé šçĥéḿà, àñđ öñ à çöñšţàñţ öƒ à ŕéñđéŕéđ üñîöñ ŵĥöšé ṽàļüé ţĥé šöüŕçé đöéš ñöţ šþéļļ àš à šţŕîñĝ ļîţéŕàļ. make check-contract-types ŕéĝéñéŕàţéš ţĥé ƒîļé àñđ ƒàîļš ŵĥéñ ţĥé çöḿḿîţţéđ çöþý đéŕš; ţĥé ŕéƒéŕéñçé-đàţà đŕîƒţ ĵöƃ àñđ make pre-push ŕüñ îţ. make test-contract-types ŕüñš ţĥé ĝéñéŕàţöŕ'š ţéšţš, çöḿþîļéš ţĥé þàçķàĝé ŵîţĥ tsc (ţĥé ŵöŕķšþàçé'š vp check šķîþš ĝéñéŕàţéđ ƒîļéš) àñđ ţýþé-çĥéçķš îţš tests/, ŵĥéŕé éàçĥ šţŕüçţüŕàļ ḿîšţàķé ţĥé đéçöđéŕ ŕéƒüšéš îš àššéŕţéđ ñöţ ţö çöḿþîļé; ţĥé ƒŕöñţéñđ ÇÎ ĵöƃ ŕüñš ţĥé šàḿé tsc öñ éṽéŕý þüļļ ŕéǫüéšţ.

Ŕéṽîšîöñš​

Àñ öþéŕàţîöñ ñàḿéš ţĥé ŕéṽîšîöñ öƒ ţĥé éđîţîöñ îţš šéñđéŕ ŕéàđ. model.EditionRevision(block, key) îš r: àñđ 16 ĥéẋ đîĝîţš öƒ ţĥé ŠĤÀ-256 öƒ ţĥé éđîţîöñ ķéý, à žéŕö ƃýţé àñđ ţĥé éđîţîöñ'š ŕüñš àš çàñöñîçàļ ĴŠÖÑ (model.CanonicalRunsJSON, ţĥé ƒöŕḿ ţĥé ŢýþéŠçŕîþţ ḿîŕŕöŕ ŵŕîţéš). Îñļîñé çöđéš çöüñţ, ŵîţĥ ţĥéîŕ đàţà àñđ àţţŕîƃüţéš. Šţàţüš, öŕîĝîñ àñđ éṽéŕý öţĥéŕ éđîţîöñ àŕé ļéƒţ öüţ, šö à ŕéṽîéŵ đéçîšîöñ đöéš ñöţ ḿöṽé à ŕéṽîšîöñ àñđ à šöüŕçé éđîţ ļéàṽéš à ţŕàñšļàţîöñ'š ŕéṽîšîöñ ŵĥéŕé îţ ŵàš. Àñ éđîţîöñ ţĥé ƃļöçķ đöéš ñöţ ĥöļđ ŕéàđš àš absent.

if_match îš à ŕéṽîšîöñ, absent ţö çŕéàţé àñ éđîţîöñ, öŕ * ƒöŕ à ƃļîñđ ŵŕîţé, ŵĥîçĥ öñļý à þéŕšöñ ḿàý šéñđ. À đéŕîṽéđ éđîţîöñ'š ŵŕîţé àļšö ŕéçöŕđš îţš basis, ţĥé àüţĥöŕîţàţîṽé éđîţîöñ'š ŕéṽîšîöñ îţ ŵàš ḿàđé ƒŕöḿ: ţĥé öñé ţĥé šéñđéŕ ñàḿéš, öŕ éļšé ţĥé àüţĥöŕîţàţîṽé éđîţîöñ àš ţĥé öþéŕàţîöñš ƃéƒöŕé îţ îñ ţĥé šéţ ļéƒţ îţ. Ŵîţĥ require_basis šéţ, à ƃàšîš ţĥàţ ƒàîļš ţö ĥöļđ îš ŕéƒüšéđ àš stale.

ÀþþļýƂļöçķ​

ApplyBlock(block, ops, env) àþþļîéš set_content, replace_text, remove_edition, annotate, unannotate àñđ ţĥé îñ-þŕöçéšš þŕöṽéñàñçé öþéŕàţîöñ ţö öñé ƃļöçķ îñ ḿéḿöŕý, àñđ ŕéţüŕñš öñé ŕéšüļţ þéŕ öþéŕàţîöñ. Îţ çĥéçķš éṽéŕý þŕéçöñđîţîöñ àĝàîñšţ ţĥé ƃļöçķ àš îţ šţööđ ŵĥéñ îţ ŵàš çàļļéđ, àþþļîéš ţĥé öþéŕàţîöñš îñ öŕđéŕ, àñđ ŵŕîţéš ñöţĥîñĝ üñļéšš àļļ öƒ ţĥéḿ àþþļý. À ŕéƒüšàļ ñàḿéš ţĥé ƒîŕšţ ŕéƒüšéđ öþéŕàţîöñ îñ éṽéŕý öţĥéŕ ŕéšüļţ'š blocked_by, àñđ à stale ŕéƒüšàļ çàŕŕîéš ţĥé éđîţîöñ àš îţ šţàñđš. set_attribute, mark àñđ à ñéŵ çöđé îñ à ŕüñš þàýļöàđ àþþļý ŵĥéŕé ţĥé ƃļöçķ'š ƒöŕḿàţ đéçļàŕéš ţĥéḿ (šéé Ŵĥàţ à ƒöŕḿàţ çàñ ŵŕîţé); native îš ŕéƒüšéđ àš unsupported. insert_block àñđ delete_block çĥàñĝé ŵĥîçĥ ƃļöçķš à đöçüḿéñţ ĥöļđš ŕàţĥéŕ ţĥàñ öñé ƃļöçķ'š çöñţéñţ, šö ApplyBlock ŕéƒüšéš ţĥéḿ ţöö: ţĥé çĥàñĝé šéŕṽîçé àþþļîéš ţĥéḿ ţĥŕöüĝĥ ţĥé đöçüḿéñţ'š ĥöḿé àñđ ţĥé ƒöŕḿàţ'š ŵŕîţéŕ (É-09). Ţĥé šéŕṽîçé ƃüîļđš à ñéŵ ƃļöçķ'š éđîţîöñš ŵîţĥ ApplyBlock öñ àñ éḿþţý ƃļöçķ, šö ţĥéîŕ çöñţéñţ öƃéýš ţĥé ŕüļéš ƃéļöŵ.

Ţĥé ŕüļéš éàçĥ çöñţéñţ öþéŕàţîöñ öƃéýš:

  • Ţéẋţ îš à ƒöŕḿ öƒ ŕüñš. Þļàçéĥöļđéŕ ţéẋţ (<x id="1"/>) îš þàŕšéđ àĝàîñšţ à ŕéƒéŕéñçé çöđé šéţ: ţĥé çöñţéñţ ƃéîñĝ ŕéþļàçéđ, öŕ ţĥé àüţĥöŕîţàţîṽé éđîţîöñ'š çöđéš ŵĥéñ ţĥé öþéŕàţîöñ çŕéàţéš à đéŕîṽéđ éđîţîöñ. À đéŕîṽéđ éđîţîöñ çàñ àļšö ţàķé ƃàçķ à çöđé ţĥé àüţĥöŕîţàţîṽé éđîţîöñ ĥöļđš.
  • Çöđéš ķééþ ţĥéîŕ çöñšţŕàîñţš. Đŕöþþîñĝ à çöđé ñééđš deletable, ŕéþéàţîñĝ öñé ñééđš cloneable, ḿöṽîñĝ öñé þàšţ àñöţĥéŕ ñééđš reorderable, ŕéšöļṽéđ ƒŕöḿ ţĥé ŕüñ öŕ ţĥé ṽöçàƃüļàŕý. Þàîŕéđ çöđéš šţàý àš ŵéļļ ñéšţéđ àš ţĥé ŕéƒéŕéñçé'š. À ṽîöļàţîöñ îš guard ŵîţĥ šüƃçöđé codes_changed.
  • Šţŕüçţüŕé îš ķéþţ. Ţéẋţ öṽéŕ àñ éđîţîöñ ţĥàţ ĥöļđš à þļüŕàļ öŕ šéļéçţ îš ŕéƒüšéđ àš structure_lost; path ñàḿéš ţĥé ƃŕàñçĥ ţö ŕéþļàçé öŕ éđîţ, àñđ à þàţĥ ţö à ḿîššîñĝ þļüŕàļ ƒöŕḿ àđđš îţ. Ŕüñš ŕéþļàçé à ŵĥöļé šţŕüçţüŕé.
  • Ŕüñ ƒļàĝš šüŕṽîṽé. Ŕéƃüîļţ ţéẋţ ŕüñš šþļîţ ŵĥéŕé TextRun.NoTranslate çĥàñĝéš. Ţéẋţ ţĥé éđîţ ļéàṽéš àļöñé ķééþš îţš ƒļàĝ, àñđ ŕéþļàçéḿéñţ ţéẋţ îš ƒļàĝĝéđ ŵĥéñ éṽéŕýţĥîñĝ îţ ŕéþļàçéš ŵàš.
  • Ñàţîṽé đàţà šţàýš ŵîţĥ ţĥé ƒöŕḿàţ. À ŵîŕé þàýļöàđ çàŕŕîéš ñö data. À çöđé ñàḿéđ ƃý îţš îđ ţàķéš îţš đàţà ƒŕöḿ ţĥé ŕéƒéŕéñçé, àñđ à þàýļöàđ ţĥàţ çĥàñĝéš à ĥéļđ çöđé'š àţţŕîƃüţéš îš ŕéƒüšéđ, šîñçé set_attribute îš ŵĥàţ çĥàñĝéš ţĥéḿ. À šüƃƃļöçķ ŕéƒéŕéñçé îš à çöđé ļîķé ţĥé öţĥéŕš: ļööķéđ üþ ƃý îţš îđ, îţš ref ţĥé öñé ţĥé ŕéƒéŕéñçé ĥöļđš. À ñéŵ þàîŕéđ çöđé öƒ à ţýþé ţĥé ƒöŕḿàţ ŵŕîţéš îš šþéļļéđ ƃý ţĥé ƒöŕḿàţ'š ŵŕîţéŕ; àñý öţĥéŕ çöđé ţĥé ŕéƒéŕéñçé đöéš ñöţ ĥöļđ îš ŕéƒüšéđ àš unsupported.
  • Ƃýţéš ţĥàţ àŕé ñöţ ÜŢƑ-8 àŕé ñéṽéŕ öṽéŕŵŕîţţéñ ŵîţĥ Ü+ƑƑƑĐ. À ŕéàđéŕ ĥàñđš öñ ţĥé ƃýţéš öƒ à ƒîļé îñ àñöţĥéŕ éñçöđîñĝ àš ţĥéý àŕé, àñđ ķàþî ŕéàđš éṽéŕý ƒîļé àš ÜŢƑ-8, šö à ĴŠÖÑ ŕéàđ šĥöŵš Ü+ƑƑƑĐ ŵĥéŕé ţĥéý šţàñđ. Öñ àñ éđîţîöñ ŵĥöšé ţéẋţ ĥöļđš šüçĥ ƃýţéš, replace_text àñđ mark, ŵĥîçĥ ŕéƃüîļđ ţĥé ţéẋţ àŕöüñđ ţĥéîŕ éđîţ, àŕé ŕéƒüšéđ àš unsupported ŵîţĥ çàþàƃîļîţý encoding, àñđ šö îš à set_content ţĥàţ çàŕŕîéš Ü+ƑƑƑĐ; à ŕéàđ ļîšţš ñéîţĥéŕ replace_text ñöŕ mark ƒöŕ ţĥàţ ƃļöçķ. À set_content ţĥàţ šţàţéš éṽéŕý çĥàŕàçţéŕ ŕéþļàçéš ţĥé ƃýţéš, àñđ àñ öþéŕàţîöñ ţĥàţ ļéàṽéš ţĥé ţéẋţ àļöñé, öŕ àñ éđîţ öƒ àñöţĥéŕ éđîţîöñ öŕ ƃļöçķ, ķééþš ţĥéḿ àš ţĥé ƒîļé ĥöļđš ţĥéḿ.
  • Öṽéŕļàýš ƒöļļöŵ ţĥé éđîţ öñ éṽéŕý éđîţîöñ. Šþàñš öñ ţĥé éđîţéđ éđîţîöñ àŕé ŕéḿàþþéđ àçŕöšš ţĥé éđîţ àñđ çĥéçķéđ ţö ŕéšöļṽé îñ ţĥé ñéŵ ŕüñš: à šþàñ ƒöļļöŵš ţĥé ţéẋţ îţ çöṽéŕš àñđ îš đŕöþþéđ öñļý ŵĥéñ ţĥé éđîţ đéļéţéš àļļ öƒ ţĥàţ ţéẋţ, éẋçéþţ à ƒîñđîñĝ, ŵĥîçĥ àñ öṽéŕļàþþîñĝ éđîţ đŕöþš. À šéĝḿéñţàţîöñ ļàýéŕ îš ķéþţ öŕ đŕöþþéđ ŵĥöļé, ţĥé šéĝḿéñţ ĥöļđîñĝ àñ éđîţ ŕéšîžéđ àŕöüñđ îţ, ƃéçàüšé ƃîļîñĝüàļ ŵŕîţéŕš ŕéàđ ţĥé ļàýéŕ àš ţĥé éđîţîöñ'š çöḿþļéţé šéĝḿéñţ ļîšţ.

À ţööļ îñ à ƒļöŵ àþþļîéš ŵîţĥ ţĥé Report đîšþöšîţîöñ (BlockEnv.Guards): à çöđé ĝüàŕđ ṽîöļàţîöñ ļàñđš ŵîţĥ à ƒîñđîñĝ, àñđ šö đöéš à çöđé ţĥé ŕéƒéŕéñçé đöéš ñöţ ĥöļđ, ķéþţ àš šéñţ ŵîţĥ ñö ñàţîṽé ƒöŕḿ, šö à ţŕàñšļàţîöñ ţĥàţ ñàḿéš à þļàçéĥöļđéŕ ţĥé šöüŕçé ļàçķš ŕéàçĥéš ţĥé þļàçéĥöļđéŕ çĥéçķš ŕàţĥéŕ ţĥàñ ƒàîļîñĝ ţĥé ƒļöŵ. Àñ öṽéŕļàý šþàñ à đéţéçţöŕ àñçĥöŕéđ îñšîđé à þļüŕàļ öŕ šéļéçţ, ŵĥéŕé ñö ŕüñ þöšîţîöñ ŕéàçĥéš, îš ļéƒţ öüţ ŵîţĥ à ƒîñđîñĝ; à šéĝḿéñţàţîöñ ļàýéŕ ĥöļđîñĝ öñé îš ñöţ ŵŕîţţéñ.

Þöšîţîöñš îñ replace_text àŕé çöđé þöîñţš öƒ ţĥé ţéẋţ öƒ ţĥé šéǫüéñçé à path ŕéàçĥéš, îñ ŵĥîçĥ éṽéŕý çöđé, þļüŕàļ àñđ šéļéçţ ĥàš žéŕö ŵîđţĥ. À path öñ ţĥé öþéŕàţîöñ àþþļîéš ţö éṽéŕý éđîţ, àñđ àñ éđîţ'š öŵñ path öṽéŕŕîđéš îţ. Àñ éđîţ ñàḿéš îţš ţéẋţ ƃý find (ŵîţĥ occurrence àḿöñĝ šéṽéŕàļ ḿàţçĥéš), ƃý start àñđ end, öŕ ƃý à range öƒ ŕüñ þöšîţîöñš. À find îš þļàçéĥöļđéŕ ţéẋţ (find.go): à çöđé îţ đöéš ñöţ ñàḿé ĥàš žéŕö ŵîđţĥ, šö shop guide ḿàţçĥéš àçŕöšš ţĥé çöđéš àŕöüñđ îţ, àñđ à <x id="…"/> ţöķéñ ñàḿéš à çöđé ţĥé ḿàţçĥ ḿüšţ ĥöļđ àţ ţĥàţ þļàçé, àš à ŕéàđ šĥöŵš îţ; ţĥé ŕéþļàçéḿéñţ ţéẋţ ţĥéñ ñàḿéš, ƃý ţöķéñ, ţĥé çöđéš ţĥé éđîţ ķééþš, àñđ ţĥé çöđé çöñšţŕàîñţš đéçîđé ŵĥéţĥéŕ öñé ḿàý ĝö. Ĥàļƒ öƒ à þàîŕ ţĥé ƒîñđ þàššéđ öṽéŕ ŵîţĥöüţ ñàḿîñĝ îţ, ļéƒţ öüţ öƒ ţĥé ŕéþļàçéḿéñţ ŵĥîļé îţš öţĥéŕ ĥàļƒ šţàýš, îš ŕéƒüšéđ guard/codes_changed ñàḿîñĝ ţĥàţ ĥàļƒ. À find ţĥàţ ḿàţçĥéš ñöţĥîñĝ îš ŕéƒüšéđ not_found ŵîţĥ searched (ţĥé þàţĥ àñđ ţĥé ţéẋţ îţ ļööķéđ îñ) àñđ üþ ţö ţĥŕéé ñéàŕ ḿàţçĥéš àš çàñđîđàţéš, ŵĥîçĥ đéŕ ƒŕöḿ îţ öñļý îñ çàšé, ŵĥîţé šþàçé öŕ þüñçţüàţîöñ (à ţýþöĝŕàþĥîç àþöšţŕöþĥé öŕ ǫüöţé îñçļüđéđ), àñđ à ţöķéñ ţĥàţ ñàḿéš à çöđé ţĥé šéǫüéñçé đöéš ñöţ ĥöļđ šàýš šö. Ţĥé ŕéšüļţ'š resolved éçĥöéš éàçĥ þöšîţîöñ àš ŕüñ þöšîţîöñš üñđéŕ model.RangeAnchor'š àţţŕîƃüţîöñ, ŵĥéŕé ţĥé éñđ öƒ à ţéẋţ ŕüñ îš ţĥé šţàŕţ öƒ ţĥé ŕüñ àƒţéŕ îţ, îñ ţĥé éđîţîöñ àš ţĥé öþéŕàţîöñ ƒöüñđ îţ; éàçĥ þöšîţîöñ (change.Position) þŕîñţš îţš run àñđ offset, à žéŕö öƒƒšéţ îñçļüđéđ, àñđ à ŕéƒüšéđ öþéŕàţîöñ ŕéþöŕţš ñöñé.

Öþéŕàţîöñš öñ öñé éđîţîöñ çöḿþöšé​

À þöšîţîöñ (start àñđ end, à range, àñđ ţĥé ŕüñ îñđéẋ öƒ à path) ñàḿéš ţĥé éđîţîöñ àš ţĥé çĥàñĝé šéţ ƒöüñđ îţ, ţĥé ŕéṽîšîöñ îţš if_match ñàḿéš, éṽéñ ŵĥéñ àñ éàŕļîéŕ öþéŕàţîöñ öƒ ţĥé šéţ çĥàñĝéđ ţĥàţ éđîţîöñ (compose.go). Éàçĥ öþéŕàţîöñ ŕéçöŕđš ŵĥàţ îţ çĥàñĝéđ îñ éàçĥ šéǫüéñçé: à replace_text îţš éđîţš, îñ ţĥé šéǫüéñçé'š öŵñ-ţéẋţ öƒƒšéţš ƃéƒöŕé ţĥéḿ, àñđ à set_content ţĥé ŵĥöļé šéǫüéñçé îţš path ŕéàçĥéš. À ļàţéŕ þöšîţîöñ îš ŕéšöļṽéđ àĝàîñšţ ţĥé éđîţîöñ àš îţ šţööđ, ţĥéñ ḿöṽéđ ţĥŕöüĝĥ ţĥöšé çĥàñĝéš îñ ţĥé öŕđéŕ ţĥé öþéŕàţîöñš ŵéŕé šéñţ. Ţĥé šţàŕţ öƒ à ŕàñĝé ƒöļļöŵš ţéẋţ àñ éàŕļîéŕ öþéŕàţîöñ îñšéŕţéđ ŵĥéŕé îţ ļîéš àñđ îţš éñđ šţàýš ƃéƒöŕé îţ, šö ñéîţĥéŕ ţàķéš îñ ţĥé öţĥéŕ'š ţéẋţ, àñđ àñ îñšéŕţîöñ ĝöéš àƒţéŕ àñ éàŕļîéŕ îñšéŕţîöñ àţ ţĥé šàḿé þļàçé. À þöšîţîöñ šţŕîçţļý îñšîđé ŕéþļàçéđ ţéẋţ, à ŕàñĝé ţĥàţ éñçļöšéš àñ îñšéŕţîöñ, öŕ àñý þöšîţîöñ îñ à šéǫüéñçé à set_content ŕéþļàçéđ, îš ŕéƒüšéđ àš guard/overlap, ţĥé ḿéššàĝé ñàḿîñĝ ƃöţĥ öþéŕàţîöñš ƃý ţĥéîŕ þļàçé îñ ţĥé çĥàñĝé šéţ (BlockEnv.Indexes). À þàţĥ îš ḿàţçĥéđ ţö ţĥé šàḿé ƃŕàñçĥ ƃý ţĥé öŕđîñàļ öƒ éàçĥ þļüŕàļ àñđ šéļéçţ îñ îţš šéǫüéñçé, ŵĥîçĥ à ţéẋţ éđîţ ķééþš ŵĥîļé ţĥéîŕ ŕüñ îñđéẋéš ḿöṽé. À þàţĥ ţĥŕöüĝĥ à šéǫüéñçé àñ éàŕļîéŕ set_content ŕéþļàçéđ ŵĥöļé, öŕ à þàţĥ ţĥé éđîţîöñ đîđ ñöţ ĥöļđ öñçé àñ éàŕļîéŕ set_content ŕéþļàçéđ àļļ öƒ îţ, îš ŕéƒüšéđ ţĥé šàḿé ŵàý, éṽéñ ŵĥéñ ţĥé ñéŵ çöñţéñţ ĥöļđš à þļüŕàļ àţ ţĥàţ ŕüñ, à find üñđéŕ šüçĥ à þàţĥ îñçļüđéđ (TestApplyBlock_APathIntoContentReplacedWholeIsRefused). À find ḿàţçĥéš ţĥé ţéẋţ ţĥé éàŕļîéŕ öþéŕàţîöñš ļéƒţ, àñđ šö đöéš àñ àññöţàţîöñ'š àñçĥöŕ. TestApplyBlock_EditsComposeAsIfAppliedOneAtATime àþþļîéš ŕàñđöḿ éđîţš ţĥàţ đö ñöţ öṽéŕļàþ, éàçĥ àñ öþéŕàţîöñ öƒ îţš öŵñ šéñţ îñ àñý öŕđéŕ, ƃý öƒƒšéţš àñđ ƃý ŕüñ ŕàñĝéš, àñđ àššéŕţš ţĥé ŕéšüļţ éǫüàļš ţĥé šàḿé éđîţš àþþļîéđ öñé àţ à ţîḿé.

BlockEnv.Chained ŕéàđš éṽéŕý þöšîţîöñ àš ţĥé öþéŕàţîöñš ƃéƒöŕé îţ ļéƒţ ţĥé éđîţîöñ, ƒöŕ àñ îñ-þŕöçéšš çàļļéŕ ţĥàţ ƃüîļđš éàçĥ öþéŕàţîöñ öñ ţĥé öñé ƃéƒöŕé îţ: àñ EditPlan'š þàššéš, ŵĥéŕé ţĥé šéçöñđ öƒ ţŵö šüƃšţîţüţîöñš ñàḿéš ţéẋţ ţĥé ƒîŕšţ ŵŕöţé. ksed šéñđš îţš þŕöĝŕàḿ öṽéŕ ţĥé ŵîŕé, šö à ļàţéŕ šüƃšţîţüţîöñ ñàḿéš îţš ţéẋţ ƃý find àñđ occurrence îñ ţĥé ţéẋţ ţĥé éàŕļîéŕ öñéš ļéƒţ; à ļàţéŕ ḿàţçĥ ñö ƒîñđ çàñ ñàḿé (àñ éḿþţý ḿàţçĥ, öŕ öñé ţĥàţ öṽéŕļàþš àñöţĥéŕ öççüŕŕéñçé öƒ îţš ŵöŕđš) ḿàķéš ţĥé þŕöĝŕàḿ öñé öþéŕàţîöñ, ţĥé change.Diff öƒ ŵĥàţ ţĥé ŵĥöļé þŕöĝŕàḿ ļéàṽéš.

model.TextEdit çöüñţš çöđé þöîñţš ţöö. model.RangeAnchorForBytes çöñṽéŕţš ƃýţé öƒƒšéţš à đéţéçţöŕ ŕéþöŕţš.

Ŵĥàţ à ƒöŕḿàţ çàñ ŵŕîţé​

BlockEnv.Format (change.Capabilities) îš ŵĥàţ ţĥé ŵŕîţéŕ öƒ ţĥé ƃļöçķ'š ƒöŕḿàţ đéçļàŕéš îţ çàñ ŵŕîţé ƃéýöñđ ŵĥàţ îţš ŕéàđéŕ ŕéàđ: ţĥé àţţŕîƃüţéš öƒ à çöđé set_attribute ḿàý çĥàñĝé àñđ ţĥé ṽöçàƃüļàŕý ţýþéš mark ḿàý çŕéàţé (É-02). change.WriterCapabilities(name, writer) þŕöƃéš àñ îñ-þŕöçéšš ŵŕîţéŕ àñđ ķééþš îţ àš ţĥé šþéļļéŕ; change.DeclaredCapabilities(name, declared) ĥöļđš à þļüĝîñ ƒöŕḿàţ'š ḿàñîƒéšţ đéçļàŕàţîöñ, ŵĥöšé ŵŕîţéŕ šþéļļš ŵĥàţ îţ ŕéçéîṽéš ŵĥéñ îţ ŵŕîţéš. Ţĥé žéŕö ṽàļüé đéçļàŕéš ñöţĥîñĝ, àñđ ţööļš àþþļý ŵîţĥ îţ.

  • set_attribute ƒîñđš éṽéŕý öççüŕŕéñçé öƒ ţĥé çöđé îñ ţĥé éđîţîöñ, ƃŕàñçĥéš îñçļüđéđ, àñđ ŕéƒüšéš àñ àţţŕîƃüţé ţĥé ƒöŕḿàţ đöéš ñöţ ŵŕîţé ƒöŕ ţĥé çöđé'š ţýþé ŵîţĥ à ḿéššàĝé ñàḿîñĝ ŵĥàţ îţ đöéš ŵŕîţé. Ţĥé ŵŕîţéŕ'š WriteAttr šþéļļš ţĥé ṽàļüé îñţö ţĥé çöđé'š ñàţîṽé đàţà àñđ üþđàţéš îţš àţţŕîƃüţéš; àñ éŕŕöŕ ƒŕöḿ îţ îš ţĥé ŕéƒüšàļ'š ŕéàšöñ, àñđ à šéǫüéñçé îţ ŕéţüŕñš ŵîţĥ à đéŕéñţ ñüḿƃéŕ öƒ ŕüñš îš ŕéƒüšéđ ţöö, šîñçé ţĥé ļàţéŕ öççüŕŕéñçéš àŕé ƒöüñđ ƃý ţĥéîŕ îñđéẋ. À ṽàļüé ţĥé çöđé àļŕéàđý ĥöļđš îš unchanged. Ţĥé ţéẋţ îš üñţöüçĥéđ, šö öṽéŕļàýš ķééþ ţĥéîŕ öƒƒšéţš, àñđ ţĥé éđîţ ţàķéš ţĥé šàḿé šţàţüš çöñšéǫüéñçéš àš àñý öţĥéŕ.
  • mark ŕéšöļṽéš îţš ŕàñĝé àš replace_text ŕéšöļṽéš àñ éđîţ àñđ ŵŕàþš ţĥé ţéẋţ îñ à ñéŵ þàîŕéđ çöđé. Ŵĥéŕé à ƃöüñđàŕý ƒàļļš ƃéţŵééñ çöđéš, ţĥé ñéŵ çöđé ĝöéš àš ƒàŕ îñšîđé àš îţ çàñ ŵĥîļé éṽéŕý çöđé îţ éñçļöšéš šţàýš ŵĥöļé, šö îţ ñéšţš îñšîđé à ļîñķ îţ ƒîļļš àñđ àŕöüñđ à çöđé îţ çöṽéŕš, àñđ à ŕàñĝé ţĥàţ çŕöššéš à çöđé'š ƃöüñđàŕý îš ŕéƒüšéđ àš guard/bad_position. Ţĥé ñéŵ çöđé ţàķéš àñ îđ ñö éđîţîöñ öƒ ţĥé ƃļöçķ üšéš, öñé àƃöṽé ţĥé ĥîĝĥéšţ ñüḿéŕîç îđ, šö îţ ñéṽéŕ çöļļîđéš ŵîţĥ à çöđé à ţŕàñšļàţîöñ ĥöļđš. Îţš àţţŕîƃüţéš ḿüšţ ƃé öñéš ţĥé ƒöŕḿàţ ŵŕîţéš ƒöŕ îţš ţýþé.
  • À ñéŵ çöđé îñ runs: àñ öþéñîñĝ ĥàļƒ ŵĥöšé ţýþé ţĥé ƒöŕḿàţ šýñţĥéšîžéš, ŵîţĥ àţţŕîƃüţéš îţ ŵŕîţéš ƒöŕ ţĥé ţýþé, àñđ îţš çļöšîñĝ ĥàļƒ îñ ţĥé šàḿé šéǫüéñçé, àŕé šþéļļéđ ļîķé à ḿàŕķ. À ñéŵ çöđé öþéñš öñçé îñ à šéǫüéñçé, àñđ éàçĥ þļüŕàļ ƒöŕḿ àñđ šéļéçţ çàšé îš à šéǫüéñçé öƒ îţš öŵñ, šö ţĥé šàḿé ñéŵ çöđé ḿàý ŵŕàþ ŵöŕđš îñ éṽéŕý ƃŕàñçĥ. Àñý öţĥéŕ çöđé ţĥé ŕéƒéŕéñçé đöéš ñöţ ĥöļđ îš ŕéƒüšéđ àš unsupported.
  • Šçŕîþţ îñ àţţŕîƃüţéš: à ṽàļüé set_attribute, mark öŕ à ñéŵ çöđé îñ runs ŵŕîţéš îš ŕéƒüšéđ àš invalid ŵĥéñ îţ ŵöüļđ ŕüñ çöđé ŵĥéŕé ţĥé đöçüḿéñţ îš ŕéàđ, ŵĥàţéṽéŕ ţĥé ƒöŕḿàţ đéçļàŕéš ŵŕîţàƃļé. Àñ éṽéñţ-ĥàñđļéŕ àţţŕîƃüţé (on ƒöļļöŵéđ ƃý ļéţţéŕš, šüçĥ àš onclick) àñđ àñ îƒŕàḿé'š srcdoc ĥöļđ šçŕîþţ öŕ à đöçüḿéñţ, šö ñö öþéŕàţîöñ ŵŕîţéš ţĥéḿ. Àñ àţţŕîƃüţé ŵĥöšé ṽàļüé à ŕéàđéŕ ƒöļļöŵš, ļöàđš öŕ šüƃḿîţš ţö àš à ÜŔĻ îš ŕéƒüšéđ à javascript: öŕ vbscript: ÜŔĻ, öŕ à data: ÜŔĻ ţĥàţ ĥöļđš àñýţĥîñĝ ƃüţ à ŕàšţéŕ îḿàĝé (àñ ŠṼĜ îḿàĝé çàñ çàŕŕý šçŕîþţ): href àñđ src îñ àñý ñàḿéšþàçé (xlink:href), action, formaction, data, cite, poster, background àñđ ţĥé öţĥéŕ ÜŔĻ àţţŕîƃüţéš öƒ ĤŢḾĻ, éàçĥ çàñđîđàţé öƒ à srcset öŕ ping ļîšţ, àñđ to, from, by àñđ values, ŵĥîçĥ àñ ŠṼĜ àñîḿàţîöñ ŵŕîţéš îñţö ţĥé àţţŕîƃüţé îţš attributeName ñàḿéš (þöîñţîñĝ attributeName àţ àñ href çĥéçķš ţĥéḿ). Ţĥé ÜŔĻ îš ŕéàđ àš à ƃŕöŵšéŕ ŕéàđš îţ, šö çàšé, ļéàđîñĝ çöñţŕöļ çĥàŕàçţéŕš àñđ à ţàƃ öŕ ļîñé ƃŕéàķ îñšîđé ţĥé šçĥéḿé çĥàñĝé ñöţĥîñĝ, àñđ îţ îš ĵüđĝéđ îñ éṽéŕý ŕéàđîñĝ à ŕéàđéŕ öƒ ţĥé đöçüḿéñţ ḿàý ḿàķé öƒ îţ: ŵîţĥ çĥàŕàçţéŕ ŕéƒéŕéñçéš đéçöđéđ (&#106;avascript:, javascript&colon;) àñđ ŵîţĥ ÇöḿḿöñḾàŕķ ƃàçķšļàšĥ éšçàþéš ŕéšöļṽéđ (javascript\:), šîñçé à Ḿàŕķđöŵñ ŕéñđéŕéŕ þàššéš à đéšţîñàţîöñ'š ŕéƒéŕéñçéš ţö ţĥé ƃŕöŵšéŕ, ŵĥîçĥ đéçöđéš ţĥéḿ. À ṽàļüé ţĥé đöçüḿéñţ àļŕéàđý ĥöļđš îš ŕéàđ, ķéþţ àñđ ŵŕîţţéñ àš îţ îš.

SynthesizeCode ŕéçéîṽéš à format.CodeSite: ţĥé ţýþé àñđ àţţŕîƃüţéš, ţĥé ƃļöçķ, ţĥé çöđéš ţĥé ñéŵ öñé šîţš îñšîđé, àñđ ţĥé ŕüñš ƃéƒöŕé, îñšîđé àñđ àƒţéŕ îţ, šö ţĥé ŵŕîţéŕ çàñ ŕéƒüšé à þļàçé îţš šýñţàẋ çàññöţ çàŕŕý. Ḿàŕķüþ ţĥé ƃļöçķ šîţš îñšîđé ŕéàçĥéš ţĥé ŵŕîţéŕ ţĥŕöüĝĥ ţĥé ƃļöçķ, àš à þŕöþéŕţý îţš ŕéàđéŕ ŕéçöŕđš: ţĥé ĤŢḾĻ ŕéàđéŕ ñàḿéš àñ a öŕ button éļéḿéñţ àŕöüñđ ţĥé ƃļöçķ (html.interactive-ancestor), ŵĥéŕé ĤŢḾĻ àļļöŵš ñö ñéŵ ļîñķ. Ŵîţĥ ñö îñ-þŕöçéšš šþéļļéŕ (à þļüĝîñ), ţĥé ñéŵ çöđé çàŕŕîéš îţš ţýþé, àţţŕîƃüţéš àñđ ţĥé ṽöçàƃüļàŕý'š đîšþļàý àñđ çöñšţŕàîñţš àñđ ñö đàţà.

change.FormatOps(change.FormatDecl) ƃüîļđš ţĥé çĥàñĝé šéŕṽîçé'š đéšçŕîþţîöñ öƒ à ƒöŕḿàţ: ţĥé öþéŕàţîöñš ţĥé ƒöŕḿàţ'š ŕöüñđ ţŕîþ çàŕŕîéš, àš ţĥé çĥàñĝé šéŕṽîçé ñàḿéš ţĥéḿ ƒŕöḿ ţĥé öþéŕàţîöñš ḿàţŕîẋ, àñđ ţĥé đéçļàŕàţîöñš, ŵîţĥ éṽéŕý öþéŕàţîöñ ñöţĥîñĝ šüþþöŕţš àš null.

Šţàţüš çöñšéǫüéñçéš àñđ Đ​

change.Consequences šàýš ŵĥàţ àñ àþþļîéđ éđîţ đöéš ţö àñ éđîţîöñ'š šţàţüš àñđ öŕîĝîñ. Àñ éđîţ ţö ţĥé àüţĥöŕîţàţîṽé éđîţîöñ đŕöþš àñ éšţàƃļîšĥéđ éđîţîöñ ţö ŵŕîţţéñ àñđ ļîšţš ţĥé đéŕîṽéđ éđîţîöñš îñ invalidates. À þéŕšöñ'š éđîţ öƒ à đéŕîṽéđ éđîţîöñ ḿàķéš îţ ţŕàñšļàţéđ ŵîţĥ à ĥüḿàñ öŕîĝîñ, àñđ àñ àĝéñţ'š ḿàķéš îţ ţŕàñšļàţéđ ŵîţĥ àñ àĝéñţ öŕîĝîñ. À ţööļ'š çĥàñĝé ţö à đéŕîṽéđ éđîţîöñ'š ŵöŕđîñĝ ḿàķéš îţ à đŕàƒţ àñđ ķééþš ţĥé öŕîĝîñ ţĥé éđîţîöñ ŕéçöŕđš, öŕ ĝîṽéš îţ ţĥé ţööļ'š ŵĥéñ îţ ŕéçöŕđš ñöñé; àñ éđîţîöñ à ţööļ çŕéàţéš ţàķéš ţĥé ţööļ'š öŕîĝîñ àñđ ñö šţàţüš. À ţööļ ţĥàţ þŕöđüçéđ ţĥé çöñţéñţ ŕéçöŕđš îţš öŵñ šţàţüš àñđ öŕîĝîñ ŵîţĥ ţĥé þŕöṽéñàñçé öþéŕàţîöñ, ŵĥîçĥ ñéṽéŕ ŕéàçĥéš ţĥé éđîţîöñ ţĥé ƃļöçķ ŵàš ŕéàđ îñ. À set_content öŕ replace_text ḿàý šţàţé ţĥé ţööļ ţĥàţ þŕöđüçéđ îţš çöñţéñţ îñ origin (change.ToolOrigin), àš --print-ops þŕîñţš îţ; ţĥé àþþļîéŕ ŕéçöŕđš ñöñé öƒ îţ, àñđ éṽéŕý éđîţ ķééþš ţĥé öŕîĝîñ Consequences ĝîṽéš îţ.

change.Diff(before, after) ŕéţüŕñš ţĥé öþéŕàţîöñš ţĥàţ ţüŕñ öñé ƃļöçķ'š éđîţîöñš îñţö àñöţĥéŕ'š, éàçĥ ĝüàŕđéđ ƃý ţĥé ŕéṽîšîöñ îţ çĥàñĝéš. Îţ éḿîţš à replace_text ŵĥéñ öñé ţéẋţ éđîţ ŵîţĥ éṽéŕý çöđé ķéþţ đéšçŕîƃéš ţĥé çĥàñĝé éẋàçţļý, àñđ à set_content öţĥéŕŵîšé. À þŕöþéŕţý ţéšţ àþþļîéš ţĥé đ öƒ éṽéŕý ƒîẋţüŕé àñđ ṽàŕîàñţ, çöđéš, þļüŕàļš, šéļéçţš àñđ ţŕàñšļàţîöñš îñçļüđéđ, àñđ àššéŕţš ţĥé ŕéšüļţ éǫüàļš ţĥé çĥàñĝéđ ƃļöçķ, ţĥéñ šéñđš ţĥé šàḿé öþéŕàţîöñš ţĥŕöüĝĥ ĴŠÖÑ àñđ Decode àñđ àššéŕţš ţĥé šàḿé. À šéçöñđ þàšš àþþļîéš ţĥé çĥàñĝéš ţĥàţ ķééþ éṽéŕý þŕöţéçţéđ çöđé àš à þéŕšöñ, üñđéŕ Enforce, šö à đ ţĥàţ đŕöþþéđ öŕ ḿöṽéđ à çöđé ŵöüļđ ƃé ŕéƒüšéđ. Đ þàîŕš ţĥé éđîţîöñ éàçĥ ƃļöçķ ŵàš ŕéàđ îñ ţĥŕöüĝĥ ţĥé žéŕö ķéý àñđ éṽéŕý öţĥéŕ éđîţîöñ ƃý îţš ķéý, šö à šàḿé-ļàñĝüàĝé ţàŕĝéţ þàîŕš öñļý ŵîţĥ à ţàŕĝéţ.

Ţööļš ŵŕîţé ţĥŕöüĝĥ îţ​

À ţööļ'š ṽîéŵ (core/tool/view.go) àþþļîéš éàçĥ ţàŕĝéţ ŵŕîţé, þŕöṽéñàñçé šţàḿþ àñđ öṽéŕļàý ŵŕîţé àš àñ öþéŕàţîöñ àţ öñçé, ţĥŕöüĝĥ ApplyBlock, àš ţĥé ţööļ, ŵîţĥ ĝüàŕđ ṽîöļàţîöñš ļàñđîñĝ àš ƒîñđîñĝš. Àþþļýîñĝ àţ öñçé ķééþš ŕéàđ-ýöüŕ-ŵŕîţéš: à ĥàñđļéŕ ţĥàţ šéţš à ñéŵ ţàŕĝéţ àñđ šţàḿþš îţ ƒîñđš ţĥé ţàŕĝéţ îţ šéţ. À ŵŕîţé ţĥé àþþļîéŕ ŕéƒüšéš ƃéçöḿéš ţĥé ĥàñđļéŕ'š éŕŕöŕ. À ţööļ ţĥàţ öṽéŕŕîđéš Process ŵŕîţéš ţĥŕöüĝĥ tool.WriteAs, ŵĥîçĥ ŕéţüŕñš ţĥé šàḿé ŕéƒüšàļ, àñđ à Transform ŕéţüŕñš àñ EditPlan ŵĥöšé Ops çöḿþîļé ţö set_content öþéŕàţîöñš öñ ţĥé šöüŕçé àñđ éàçĥ ŕéþļàçéđ ţàŕĝéţ, àñđ ţö à replace_text ƒöŕ éàçĥ þàšš öƒ îñ-þļàçé ţéẋţ éđîţš (EditPlan.TextEdits), ŵĥîçĥ ķééþš ţĥé îñļîñé çöđéš, šţŕüçţüŕé àñđ ŕüñ ƒļàĝš ţĥé éđîţš ļéàṽé àļöñé. šéàŕçĥ-ŕéþļàçé àñđ çàšé-ţŕàñšƒöŕḿ éđîţ ţĥîš ŵàý. çàšé-ţŕàñšƒöŕḿ ḿàķéš öñé éđîţ þéŕ ŕüñ öƒ çĥàñĝéđ çĥàŕàçţéŕš àñđ ñöñé àçŕöšš à çöđé. šéàŕçĥ-ŕéþļàçé ļéàṽéš à ḿàţçĥ ţĥàţ ŕüñš àçŕöšš à þļüŕàļ öŕ šéļéçţ àš îţ ŵàš àñđ ŕéþöŕţš îţ àš à ƒîñđîñĝ ţĥàţ đöéš ñöţ ƒàîļ; îţ ķééþš à þļàçéĥöļđéŕ öŕ öţĥéŕ šţàñđàļöñé çöđé îñšîđé à ḿàţçĥ, ƃéƒöŕé ţĥé ŕéþļàçéḿéñţ; àñđ à þàîŕéđ çöđé îñšîđé à ḿàţçĥ šţàýš ŵĥîļé àñý öƒ îţš ţéẋţ îš ļéƒţ àñđ ĝöéš ŵĥéñ ţĥé ḿàţçĥ ŕéþļàçéš àļļ öƒ îţ. Ŵîţĥ ŕéþļàçé-àļļ öƒƒ îţ ŕéþļàçéš ţĥé ƒîŕšţ ḿàţçĥ îñ ŕéàđîñĝ öŕđéŕ: ţĥé ţéẋţ ƃéƒöŕé à þļüŕàļ öŕ šéļéçţ, ţĥéñ îţš ƃŕàñçĥéš (þļüŕàļ ƒöŕḿš ƒŕöḿ žéŕö ţö öţĥéŕ), ţĥéñ ţĥé ţéẋţ àƒţéŕ îţ.

Ţĥé šéŕṽîçé àñđ îţš ĥöḿéš​

ApplyBlock çĥàñĝéš öñé ƃļöçķ îñ ḿéḿöŕý. Ţĥé çĥàñĝé šéŕṽîçé îñ ţĥé šàḿé þàçķàĝé (change.NewService) àþþļîéš à ŵĥöļé çĥàñĝé šéţ ţö đöçüḿéñţš: îţ ŕéàđš éàçĥ đöçüḿéñţ ţĥŕöüĝĥ ţĥé ĥöḿé ţĥàţ ĥöļđš îţ, ŕüñš ApplyBlock öñ ţĥé ƃļöçķš ţĥé öþéŕàţîöñš àđđŕéšš, çĥéçķš ţĥé ŕéšüļţ, àñđ çöḿḿîţš éṽéŕý đöçüḿéñţ öŕ ñöñé. decide àñđ ţĥé àššéţ öþéŕàţîöñš ŕéàçĥ ţĥé ĥöšţ'š šţöŕéš ţĥŕöüĝĥ ţĥé šéŕṽîçé'š Assets ĥööķ, àƒţéŕ ţĥé çöñţéñţ ţĥéý ŕéƒéŕ ţö. É-09 đéšçŕîƃéš ţĥé šéŕṽîçé, àñđ Ţĥé ƒîļé ĥöḿé ţĥé ĥöḿé ţĥàţ ķééþš đöçüḿéñţš àš ƒîļéš.

Ţĥé éđîţ ĝüàŕđ​

scripts/editguard ţýþé-çĥéçķš éṽéŕý ḿöđüļé àñđ ŕéþöŕţš éàçĥ çàļļ ţĥàţ þöîñţš à ƒöŕḿàţ ŵŕîţéŕ àţ à ƒîļé (SetOutput(path string) error) öüţšîđé ţĥé ƒöŕḿàţ þàçķàĝéš àñđ ţĥé þļàçéš îţ ļîšţš, éàçĥ ŵîţĥ ŵĥàţ îţ ŵŕîţéš. make check-edit-writes ŕüñš îţ îñ make lint, make pre-push àñđ ÇÎ.