code.pablomurad.com

patchwork

Publishes the revisions of your pages as a feed, with notes and readable diffs, written in Go

internal/render/model.go raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Package render builds everything Patchwork publishes from the store: the
// JSON API, Atom and JSON Feed, and plain text for terminals. Build returns
// one in-memory tree; the server serves it and export writes it to disk, so
// both always publish the same bytes.
package render

import (
	"time"

	"git.pablomurad.com/pablo/patchwork/internal/diff"
)

// The JSON contract, version 1. schema/v1 describes the same shapes; change
// both together, and never remove or rename a field within v1.

// PageRef identifies a page inside other objects.
type PageRef struct {
	UID   string `json:"uid"`
	Slug  string `json:"slug"`
	Title string `json:"title"`
	URL   string `json:"url"`
}

// PageSummary is one entry of /api/v1/pages.
type PageSummary struct {
	UID          string `json:"uid"`
	Slug         string `json:"slug"`
	Path         string `json:"path"`
	Title        string `json:"title"`
	URL          string `json:"url"`
	HistoryURL   string `json:"history_url"`
	Maturity     string `json:"maturity,omitempty"`
	OriginalDate string `json:"original_date"`
	FirstSeenAt  string `json:"first_seen_at"`
	// LastRevisedAt is the latest published revision; empty when the page
	// has only its first version.
	LastRevisedAt string `json:"last_revised_at,omitempty"`
	RevisionCount int    `json:"revision_count"`
	LatestNumber  int    `json:"latest_number"`
}

// VersionSummary is one entry of a page's history.
type VersionSummary struct {
	Number       int    `json:"number"`
	Baseline     bool   `json:"baseline,omitempty"`
	PublishedAt  string `json:"published_at"`
	UpdatedAt    string `json:"updated_at"`
	Note         string `json:"note,omitempty"`
	Kind         string `json:"kind,omitempty"`
	Maturity     string `json:"maturity,omitempty"`
	URL          string `json:"url"`
	WordsAdded   int    `json:"words_added"`
	WordsRemoved int    `json:"words_removed"`
}

// PageDetail is /api/v1/pages/{slug}: the summary plus the history, newest
// first.
type PageDetail struct {
	PageSummary
	Versions []VersionSummary `json:"versions"`
}

// Excerpt is the part of a diff shown in feeds and lists.
type Excerpt struct {
	Truncated bool      `json:"truncated"`
	Blocks    []diff.Op `json:"blocks"`
}

// Revision is one published revision: an entry in /api/v1/revisions and in
// the feeds.
type Revision struct {
	ID           string            `json:"id"`
	Number       int               `json:"number"`
	BaseNumber   int               `json:"base_number"`
	Page         PageRef           `json:"page"`
	Kind         string            `json:"kind,omitempty"`
	Maturity     string            `json:"maturity,omitempty"`
	Note         string            `json:"note"`
	PublishedAt  string            `json:"published_at"`
	UpdatedAt    string            `json:"updated_at"`
	OriginalDate string            `json:"original_date"`
	VersionURL   string            `json:"version_url"`
	HistoryURL   string            `json:"history_url"`
	Stats        diff.Stats        `json:"stats"`
	MetaChanges  []diff.MetaChange `json:"meta_changes"`
	Excerpt      Excerpt           `json:"excerpt"`

	published, updated time.Time
}

// Version is /api/v1/pages/{slug}/versions/{n}: one public version with its
// text and its full diff against the previous public version.
type Version struct {
	Page         PageRef        `json:"page"`
	Number       int            `json:"number"`
	LatestNumber int            `json:"latest_number"`
	Baseline     bool           `json:"baseline,omitempty"`
	PublishedAt  string         `json:"published_at"`
	UpdatedAt    string         `json:"updated_at"`
	Note         string         `json:"note,omitempty"`
	Kind         string         `json:"kind,omitempty"`
	Maturity     string         `json:"maturity,omitempty"`
	URL          string         `json:"url"`
	Title        string         `json:"title"`
	BodyMarkdown string         `json:"body_markdown"`
	Frontmatter  map[string]any `json:"frontmatter"`
	BaseNumber   int            `json:"base_number,omitempty"`
	// Diff is null for the first version.
	Diff *diff.Full `json:"diff"`
}

// RevisionList is /api/v1/revisions.
type RevisionList struct {
	Revisions []Revision `json:"revisions"`
}

// PageList is /api/v1/pages.
type PageList struct {
	Pages []PageSummary `json:"pages"`
}

// Error is the body of every API error.
type Error struct {
	Error struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"error"`
}