This repository has been archived by the owner on Aug 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
transclusion.go
144 lines (131 loc) · 4.34 KB
/
transclusion.go
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package blocks
import (
"fmt"
"github.com/bouncepaw/mycomarkup/v4/links"
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
"github.com/bouncepaw/mycomarkup/v4/util"
"strings"
)
// Transclusion is the block representing an extract from a different document.
type Transclusion struct {
// Target is the name of the hypha to be transcluded.
Target string
Blend bool
Selector TransclusionSelector
TransclusionError
}
// ID returns the transclusion's id which is transclusion- and a number.
func (t Transclusion) ID(counter *IDCounter) string {
counter.transclusions++
return fmt.Sprintf("transclusion-%d", counter.transclusions)
}
// MakeTransclusion parses the line and returns a transclusion block. V3
func MakeTransclusion(ctx mycocontext.Context, line string) Transclusion {
if !ctx.TransclusionSupported() {
return Transclusion{
"",
false,
SelectorOverview,
TransclusionError{TransclusionNotSupported},
}
}
line = strings.TrimSpace(line[2:])
// The second operand matches transclusion like <= | tututu or <= |
if line == "" || strings.HasPrefix(line, "|") {
return Transclusion{
"",
false,
SelectorOverview,
TransclusionError{TransclusionErrorNoTarget},
}
}
if strings.ContainsRune(line, '|') {
var (
parts = strings.SplitN(line, "|", 2)
targetHypha = util.CanonicalName(strings.TrimSpace(parts[0]))
)
if strings.ContainsRune(targetHypha, ':') {
return Transclusion{
Target: targetHypha,
Blend: false,
Selector: SelectorOverview,
TransclusionError: TransclusionError{TransclusionErrorOldSyntax},
}
}
// Sorry for party rocking
targetHypha = links.From(targetHypha, "", ctx.HyphaName()).TargetHypha()
if !mycocontext.HyphaExists(ctx, targetHypha) {
return Transclusion{
Target: targetHypha,
Blend: false,
Selector: SelectorOverview,
TransclusionError: TransclusionError{TransclusionErrorNotExists},
}
}
return Transclusion{
Target: links.From(targetHypha, "", ctx.HyphaName()).TargetHypha(),
Blend: strings.Contains(parts[1], "blend"),
Selector: selectorFrom(parts[1]),
}
}
return Transclusion{
Target: links.From(strings.TrimSpace(line), "", ctx.HyphaName()).TargetHypha(),
Blend: false,
Selector: SelectorOverview,
}
}
// TransclusionErrorReason is the reason why the transclusion failed during parsing.
type TransclusionErrorReason int
const (
// TransclusionNoError means there is no error.
TransclusionNoError TransclusionErrorReason = iota
// TransclusionNotSupported means that transclusion is not supported.
TransclusionNotSupported
// TransclusionErrorNoTarget means that no target hypha was specified.
TransclusionErrorNoTarget
// TransclusionErrorOldSyntax means : was found in the target.
TransclusionErrorOldSyntax
// TransclusionErrorNotExists means the target hypha does not exist.
TransclusionErrorNotExists
)
// TransclusionError is the error that occurred during transclusion.
type TransclusionError struct {
Reason TransclusionErrorReason
}
// HasError is true if there is indeed an error.
func (te *TransclusionError) HasError() bool {
return te.Reason != TransclusionNoError
}
// TransclusionSelector is the thing that specifies what parts of the document shall be transcluded.
type TransclusionSelector int
const (
// SelectorOverview is SelectorAttachment and SelectorDescription combined.
SelectorOverview TransclusionSelector = iota
// SelectorAttachment selects the attachment of the target hypha.
SelectorAttachment
// SelectorDescription selects the description of the target hypha. The first paragraph of the text part of the hypha is considered its description.
SelectorDescription
// SelectorText selects all of the text in the hypha, but not the attachment.
SelectorText
// SelectorFull selects everything in the hypha, including the attachment.
SelectorFull
)
func selectorFrom(s string) TransclusionSelector {
switch {
case strings.Contains(s, "full"):
return SelectorFull
case strings.Contains(s, "text"):
return SelectorText
case strings.Contains(s, "overview"):
return SelectorOverview
case strings.Contains(s, "description"):
if strings.Contains(s, "attachment") {
return SelectorOverview
}
return SelectorDescription
case strings.Contains(s, "attachment"):
return SelectorAttachment
default:
return SelectorOverview
}
}