Skip to content
internal/revisions
On this page

Tracking blog post revisions in a sidecar file, appending one only when the rendered body actually changes, so a frontmatter-only edit stays invisible.

#internal/revisions

#internal/revisions

Package revisions tracks post revisions in a sidecar revisions.json.

Content changes to blog posts are tracked using SHA-256 hashes of the rendered body text. A new revision is appended only when the body content actually changes, so a frontmatter-only edit is invisible.

The sidecar file sits at .selfdoc/revisions.json -- separate from the manifest, so no manifest format change can reach it.

#Revision

Go go
type Revision struct

Revision is one recorded revision of a post.

#PostRevisions

Go go
type PostRevisions struct

PostRevisions is one post's recorded revisions, oldest first.

#Document

Go go
type Document struct

Document is the parsed sidecar: every post that has a recorded revision, in the order the file declares them.

The order is part of the document rather than an implementation detail: the sidecar is rewritten whole on every recording, and a rewrite that reordered the posts would produce a diff on every publish.

#ComputePostContentHash

Go go
func ComputePostContentHash(body string) string

ComputePostContentHash computes a deterministic SHA-256 hash of a post's body text.

The body is the rendered content with frontmatter already stripped. Whitespace is normalized (per-line trim plus blank-line collapsing) so that insignificant formatting changes do not trigger false revisions.

Site-context-dependent values (base URLs, theme names) must NOT appear in the input -- callers pass only the body text.

#LoadRevisions

Go go
func LoadRevisions(dirPath string) (*Document, error)

LoadRevisions loads revisions.json from dirPath's .selfdoc directory.

An absent file is an empty document, not an error: a project that has published nothing yet has no revisions to read. A file that exists and is not readable as the document is an error.

#SaveRevisions

Go go
func SaveRevisions(handle *effects.Handle, document *Document, dirPath string) (string, error)

SaveRevisions writes revisions.json into dirPath's .selfdoc directory, atomically, and returns the path it wrote.

#RecordRevision

Go go
func RecordRevision(

RecordRevision records a revision for a post when its body content changed.

It computes the content hash, compares it against the latest revision for this slug, and appends a new entry only when the hash differs. The returned bool reports whether a revision was appended; when it is false nothing was written.

dirPath is the project root, slug the post's identifier, body the rendered body text with frontmatter stripped, and summary an optional note that is left out of the document when empty.

#GetPostRevisions

Go go
func GetPostRevisions(dirPath, slug string) ([]Revision, error)

GetPostRevisions returns the recorded revisions for a post, oldest first, and an empty slice for a post with none.

#GetLastUpdated

Go go
func GetLastUpdated(dirPath, slug string) (string, bool, error)

GetLastUpdated returns the timestamp of the most recent revision for a post. The bool reports whether the post has any revision at all.

#Document.Find

Go go
func (d *Document) Find(slug string) *PostRevisions

Find returns the entry for slug, or nil when the document carries none.

Search