feat(11.1-02): check links, commands, forbidden names and fence policy
- relative links and anchors resolve against the renderer's heading IDs - summer and ./bin/<app> command names come from the real command constructors through docsite.Options.Commands; a nil set is a problem - consuming-application names fail in page sources and built outputs - go fences in docs/ pages need src=, callouts are NOTE, TIP or WARNING, docs/ headings are plain ASCII - gate gains --claude and self-test plants for each new rule
This commit is contained in:
@@ -34,6 +34,9 @@ func problemLines(problems []Problem) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
// fixtureCommands is the command set the fixture trees are checked with.
|
||||
var fixtureCommands = &Commands{Tool: []string{"docs:build", "make:plugin"}, App: []string{"serve", "migrate"}}
|
||||
|
||||
const fixtureSite = `title: Acme
|
||||
description: Acme docs.
|
||||
sections:
|
||||
@@ -110,7 +113,7 @@ func TestReadmeIngestion(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := filepath.Join(t.TempDir(), "site")
|
||||
res, problems, err := Build(Options{Root: root, Out: out})
|
||||
res, problems, err := Build(Options{Root: root, Commands: fixtureCommands, Out: out})
|
||||
if err != nil || len(problems) > 0 {
|
||||
t.Fatalf("Build: %v %q", err, problemLines(problems))
|
||||
}
|
||||
@@ -302,7 +305,7 @@ func TestSnippetConfinement(t *testing.T) {
|
||||
if err := os.Symlink(outside, filepath.Join(root, "escape.txt")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
problems, err := Check(Options{Root: root})
|
||||
problems, err := Check(Options{Root: root, Commands: fixtureCommands})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -316,7 +319,7 @@ func TestSnippetConfinement(t *testing.T) {
|
||||
t.Errorf("src=%s: no problem %q...%q in\n%s", tc.src, prefix, tc.want, strings.Join(got, "\n"))
|
||||
}
|
||||
}
|
||||
if _, _, err := Build(Options{Root: root, Out: filepath.Join(t.TempDir(), "site")}); err != nil {
|
||||
if _, _, err := Build(Options{Root: root, Commands: fixtureCommands, Out: filepath.Join(t.TempDir(), "site")}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -327,7 +330,7 @@ func TestSyncRewritesDrift(t *testing.T) {
|
||||
root := snippetTree(t, map[string]string{"docs/setup/start.md": doc})
|
||||
path := filepath.Join(root, "docs/setup/start.md")
|
||||
|
||||
problems, err := Check(Options{Root: root})
|
||||
problems, err := Check(Options{Root: root, Commands: fixtureCommands})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -336,7 +339,7 @@ func TestSyncRewritesDrift(t *testing.T) {
|
||||
t.Fatalf("problems = %q, want [%q]", got, want)
|
||||
}
|
||||
out := filepath.Join(t.TempDir(), "site")
|
||||
if _, problems, err := Build(Options{Root: root, Out: out}); err != nil || len(problems) != 1 {
|
||||
if _, problems, err := Build(Options{Root: root, Commands: fixtureCommands, Out: out}); err != nil || len(problems) != 1 {
|
||||
t.Fatalf("Build with drift: %v %v", err, problems)
|
||||
}
|
||||
if _, err := os.Stat(out); err == nil {
|
||||
@@ -362,10 +365,10 @@ func TestSyncRewritesDrift(t *testing.T) {
|
||||
if res, _, err := Sync(Options{Root: root}); err != nil || res != (SyncResult{}) {
|
||||
t.Fatalf("second Sync = %+v, %v; want up to date", res, err)
|
||||
}
|
||||
if problems, err := Check(Options{Root: root}); err != nil || len(problems) > 0 {
|
||||
if problems, err := Check(Options{Root: root, Commands: fixtureCommands}); err != nil || len(problems) > 0 {
|
||||
t.Fatalf("Check after Sync: %v %q", err, problemLines(problems))
|
||||
}
|
||||
if _, problems, err := Build(Options{Root: root, Out: out}); err != nil || len(problems) > 0 {
|
||||
if _, problems, err := Build(Options{Root: root, Commands: fixtureCommands, Out: out}); err != nil || len(problems) > 0 {
|
||||
t.Fatalf("Build after Sync: %v %v", err, problems)
|
||||
}
|
||||
md, err := os.ReadFile(filepath.Join(out, "setup/start.md"))
|
||||
|
||||
Reference in New Issue
Block a user