Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From v0.4
To v0.5.1
2022-08-02
| | |
10:06 |
|
...
(check-in: ad7c201f7e user: stern tags: trunk)
|
09:27 |
|
...
(Leaf
check-in: e10f2a270d user: stern tags: release, v0.5.1, release-0.5)
|
09:09 |
|
...
(check-in: b6687c0706 user: stern tags: release-0.5)
|
2022-03-10
| | |
13:20 |
|
...
(check-in: 73f6c7eb13 user: stern tags: trunk)
|
2022-03-09
| | |
14:06 |
|
...
(check-in: 54ed47f372 user: stern tags: trunk, release, v0.4)
|
13:54 |
|
...
(check-in: 711a670d7a user: stern tags: trunk)
|
| | |
Changes to VERSION.
Changes to ast/ast.go.
︙ | | |
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
-
-
-
-
-
-
-
|
// InlineNode is the interface that all inline nodes must implement.
type InlineNode interface {
Node
inlineNode()
}
// InlineEmbedNode is a node that specifies some embeddings in inline mode.
// It is abstract, b/c there are different concrete type implementations.
type InlineEmbedNode interface {
InlineNode
inlineEmbedNode()
}
// Reference is a reference to external or internal material.
type Reference struct {
URL *url.URL
Value string
State RefState
}
|
︙ | | |
Changes to ast/block.go.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package ast
import "zettelstore.de/c/zjson"
import "zettelstore.de/c/attrs"
// Definition of Block nodes.
// BlockSlice is a slice of BlockNodes.
type BlockSlice []BlockNode
func (*BlockSlice) blockNode() { /* Just a marker */ }
|
︙ | | |
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
|
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
|
-
-
-
-
+
-
-
+
-
-
+
-
-
-
+
-
+
+
+
+
+
+
+
+
-
+
-
+
|
Inlines InlineSlice
}
func (*ParaNode) blockNode() { /* Just a marker */ }
func (*ParaNode) itemNode() { /* Just a marker */ }
func (*ParaNode) descriptionNode() { /* Just a marker */ }
// NewParaNode creates an empty ParaNode.
func NewParaNode() *ParaNode { return &ParaNode{} }
// CreateParaNode creates a parameter block from inline nodes.
func CreateParaNode(nodes ...InlineNode) *ParaNode {
func CreateParaNode(nodes ...InlineNode) *ParaNode { return &ParaNode{Inlines: nodes} }
return &ParaNode{Inlines: nodes}
}
// WalkChildren walks down the inline elements.
func (pn *ParaNode) WalkChildren(v Visitor) {
func (pn *ParaNode) WalkChildren(v Visitor) { Walk(v, &pn.Inlines) }
Walk(v, &pn.Inlines)
}
//--------------------------------------------------------------------------
// VerbatimNode contains uninterpreted text
type VerbatimNode struct {
Kind VerbatimKind
Attrs zjson.Attributes
Attrs attrs.Attributes
Content []byte
}
// VerbatimKind specifies the format that is applied to code inline nodes.
type VerbatimKind uint8
type VerbatimKind int
// Constants for VerbatimCode
const (
_ VerbatimKind = iota
VerbatimZettel // Zettel content
VerbatimProg // Program code
VerbatimEval // Code to be externally interpreted. Syntax is stored in default attribute.
VerbatimComment // Block comment
VerbatimHTML // Block HTML, e.g. for Markdown
VerbatimMath // Block math mode
)
func (*VerbatimNode) blockNode() { /* Just a marker */ }
func (*VerbatimNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
func (*VerbatimNode) WalkChildren(Visitor) { /* No children*/ }
// Supported syntax values for VerbatimEval.
const (
VerbatimEvalSyntaxDraw = "draw"
)
//--------------------------------------------------------------------------
// RegionNode encapsulates a region of block nodes.
type RegionNode struct {
Kind RegionKind
Attrs zjson.Attributes
Attrs attrs.Attributes
Blocks BlockSlice
Inlines InlineSlice // Optional text at the end of the region
}
// RegionKind specifies the actual region type.
type RegionKind uint8
type RegionKind int
// Values for RegionCode
const (
_ RegionKind = iota
RegionSpan // Just a span of blocks
RegionQuote // A longer quotation
RegionVerse // Line breaks matter
|
︙ | | |
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
-
+
-
+
-
+
-
-
-
+
-
+
|
}
//--------------------------------------------------------------------------
// HeadingNode stores the heading text and level.
type HeadingNode struct {
Level int
Inlines InlineSlice // Heading text, possibly formatted
Attrs attrs.Attributes
Slug string // Heading text, normalized
Fragment string // Heading text, suitable to be used as an unique URL fragment
Attrs zjson.Attributes
Inlines InlineSlice // Heading text, possibly formatted
}
func (*HeadingNode) blockNode() { /* Just a marker */ }
func (*HeadingNode) itemNode() { /* Just a marker */ }
// WalkChildren walks the heading text.
func (hn *HeadingNode) WalkChildren(v Visitor) {
func (hn *HeadingNode) WalkChildren(v Visitor) { Walk(v, &hn.Inlines) }
Walk(v, &hn.Inlines)
}
//--------------------------------------------------------------------------
// HRuleNode specifies a horizontal rule.
type HRuleNode struct {
Attrs zjson.Attributes
Attrs attrs.Attributes
}
func (*HRuleNode) blockNode() { /* Just a marker */ }
func (*HRuleNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
func (*HRuleNode) WalkChildren(Visitor) { /* No children*/ }
//--------------------------------------------------------------------------
// NestedListNode specifies a nestable list, either ordered or unordered.
type NestedListNode struct {
Kind NestedListKind
Items []ItemSlice
Attrs zjson.Attributes
Attrs attrs.Attributes
}
// NestedListKind specifies the actual list type.
type NestedListKind uint8
// Values for ListCode
const (
|
︙ | | |
Changes to ast/inline.go.
︙ | | |
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
+
|
//-----------------------------------------------------------------------------
package ast
import (
"unicode/utf8"
"zettelstore.de/c/zjson"
"zettelstore.de/c/attrs"
)
// Definitions of inline nodes.
// InlineSlice is a list of BlockNodes.
type InlineSlice []InlineNode
|
︙ | | |
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
+
-
+
-
+
-
-
+
-
+
-
-
+
-
-
-
+
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
|
// WalkChildren does nothing.
func (*BreakNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// LinkNode contains the specified link.
type LinkNode struct {
Attrs attrs.Attributes // Optional attributes
Ref *Reference
Inlines InlineSlice // The text associated with the link.
Inlines InlineSlice // The text associated with the link.
Attrs zjson.Attributes // Optional attributes
}
func (*LinkNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the link text.
func (ln *LinkNode) WalkChildren(v Visitor) {
if len(ln.Inlines) > 0 {
Walk(v, &ln.Inlines)
}
}
// --------------------------------------------------------------------------
// EmbedRefNode contains the specified embedded reference material.
type EmbedRefNode struct {
Attrs attrs.Attributes // Optional attributes
Ref *Reference // The reference to be embedded.
Inlines InlineSlice // Optional text associated with the image.
Attrs zjson.Attributes // Optional attributes
Syntax string // Syntax of referenced material, if known
Inlines InlineSlice // Optional text associated with the image.
}
func (*EmbedRefNode) inlineNode() { /* Just a marker */ }
func (*EmbedRefNode) inlineNode() { /* Just a marker */ }
func (*EmbedRefNode) inlineEmbedNode() { /* Just a marker */ }
// WalkChildren walks to the text that describes the embedded material.
func (en *EmbedRefNode) WalkChildren(v Visitor) {
func (en *EmbedRefNode) WalkChildren(v Visitor) { Walk(v, &en.Inlines) }
Walk(v, &en.Inlines)
}
// --------------------------------------------------------------------------
// EmbedBLOBNode contains the specified embedded BLOB material.
type EmbedBLOBNode struct {
Blob []byte // BLOB data itself.
Attrs attrs.Attributes // Optional attributes
Syntax string // Syntax of Blob
Blob []byte // BLOB data itself.
Inlines InlineSlice // Optional text associated with the image.
Attrs zjson.Attributes // Optional attributes
}
func (*EmbedBLOBNode) inlineNode() { /* Just a marker */ }
func (*EmbedBLOBNode) inlineNode() { /* Just a marker */ }
func (*EmbedBLOBNode) inlineEmbedNode() { /* Just a marker */ }
// WalkChildren walks to the text that describes the embedded material.
func (en *EmbedBLOBNode) WalkChildren(v Visitor) {
func (en *EmbedBLOBNode) WalkChildren(v Visitor) { Walk(v, &en.Inlines) }
Walk(v, &en.Inlines)
}
// --------------------------------------------------------------------------
// CiteNode contains the specified citation.
type CiteNode struct {
Attrs attrs.Attributes // Optional attributes
Key string // The citation key
Inlines InlineSlice // Optional text associated with the citation.
Attrs zjson.Attributes // Optional attributes
}
func (*CiteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the cite text.
func (cn *CiteNode) WalkChildren(v Visitor) {
func (cn *CiteNode) WalkChildren(v Visitor) { Walk(v, &cn.Inlines) }
Walk(v, &cn.Inlines)
}
// --------------------------------------------------------------------------
// MarkNode contains the specified merked position.
// It is a BlockNode too, because although it is typically parsed during inline
// mode, it is moved into block mode afterwards.
type MarkNode struct {
|
︙ | | |
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
+
-
-
+
-
-
-
+
-
+
-
+
-
-
-
+
-
+
+
|
}
}
// --------------------------------------------------------------------------
// FootnoteNode contains the specified footnote.
type FootnoteNode struct {
Attrs attrs.Attributes // Optional attributes
Inlines InlineSlice // The footnote text.
Attrs zjson.Attributes // Optional attributes
}
func (*FootnoteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the footnote text.
func (fn *FootnoteNode) WalkChildren(v Visitor) {
func (fn *FootnoteNode) WalkChildren(v Visitor) { Walk(v, &fn.Inlines) }
Walk(v, &fn.Inlines)
}
// --------------------------------------------------------------------------
// FormatNode specifies some inline formatting.
type FormatNode struct {
Kind FormatKind
Attrs zjson.Attributes // Optional attributes.
Attrs attrs.Attributes // Optional attributes.
Inlines InlineSlice
}
// FormatKind specifies the format that is applied to the inline nodes.
type FormatKind uint8
type FormatKind int
// Constants for FormatCode
const (
_ FormatKind = iota
FormatEmph // Emphasized text.
FormatStrong // Strongly emphasized text.
FormatInsert // Inserted text.
FormatDelete // Deleted text.
FormatSuper // Superscripted text.
FormatSub // SubscriptedText.
FormatQuote // Quoted text.
FormatSpan // Generic inline container.
)
func (*FormatNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the formatted text.
func (fn *FormatNode) WalkChildren(v Visitor) {
func (fn *FormatNode) WalkChildren(v Visitor) { Walk(v, &fn.Inlines) }
Walk(v, &fn.Inlines)
}
// --------------------------------------------------------------------------
// LiteralNode specifies some uninterpreted text.
type LiteralNode struct {
Kind LiteralKind
Attrs zjson.Attributes // Optional attributes.
Attrs attrs.Attributes // Optional attributes.
Content []byte
}
// LiteralKind specifies the format that is applied to code inline nodes.
type LiteralKind uint8
type LiteralKind int
// Constants for LiteralCode
const (
_ LiteralKind = iota
LiteralZettel // Zettel content
LiteralProg // Inline program code
LiteralInput // Computer input, e.g. Keyboard strokes
LiteralOutput // Computer output
LiteralComment // Inline comment
LiteralHTML // Inline HTML, e.g. for Markdown
LiteralMath // Inline math mode
)
func (*LiteralNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
func (*LiteralNode) WalkChildren(Visitor) { /* No children*/ }
|
Changes to ast/ref.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2021 Detlef Stern
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package ast
|
︙ | | |
Changes to ast/ref_test.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2021 Detlef Stern
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package ast_test
|
︙ | | |
Changes to ast/walk.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2021 Detlef Stern
// Copyright (c) 2021-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package ast
|
︙ | | |
Changes to ast/walk_test.go.
︙ | | |
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
+
|
//-----------------------------------------------------------------------------
package ast_test
import (
"testing"
"zettelstore.de/c/zjson"
"zettelstore.de/c/attrs"
"zettelstore.de/z/ast"
)
func BenchmarkWalk(b *testing.B) {
root := ast.BlockSlice{
&ast.HeadingNode{
Inlines: ast.CreateInlineSliceFromWords("A", "Simple", "Heading"),
|
︙ | | |
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
-
+
|
},
&ast.ParaNode{
Inlines: ast.CreateInlineSliceFromWords("This", "is", "some", "intermediate", "text."),
},
ast.CreateParaNode(
&ast.FormatNode{
Kind: ast.FormatEmph,
Attrs: zjson.Attributes(map[string]string{
Attrs: attrs.Attributes(map[string]string{
"": "class",
"color": "green",
}),
Inlines: ast.CreateInlineSliceFromWords("This", "is", "some", "emphasized", "text."),
},
&ast.SpaceNode{Lexeme: " "},
&ast.LinkNode{
|
︙ | | |
Changes to auth/impl/impl.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2021 Detlef Stern
// Copyright (c) 2021-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
// Package impl provides services for authentification / authorization.
|
︙ | | |
Changes to box/constbox/base.css.
︙ | | |
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
-
-
-
+
-
-
+
-
+
|
clear: both;
visibility: hidden;
}
main form div { margin: .5em 0 0 0 }
input { font-family: monospace }
input[type="submit"],button,select { font: inherit }
label { font-family: sans-serif; font-size:.9rem }
label::after { content:":" }
textarea {
font-family: monospace;
resize: vertical;
width: 100%;
}
.zs-input {
padding: .5em;
display:block;
border:none;
border-bottom:1px solid #ccc;
width:100%;
}
.zs-button {
float:right;
input.zs-primary { float:right }
margin: .5em 0 .5em 1em;
}
input.zs-secondary { float:left }
a:not([class]) { text-decoration-skip-ink: auto }
a.broken { text-decoration: line-through }
img { max-width: 100% }
img.right { float: right }
ol.endnotes {
ol.zs-endnotes {
padding-top: .5rem;
border-top: 1px solid;
}
kbd { font-family:monospace }
code,pre {
font-family: monospace;
font-size: 85%;
|
︙ | | |
Changes to box/constbox/base.mustache.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
+
+
+
+
|
<!DOCTYPE html>
<html{{#Lang}} lang="{{Lang}}"{{/Lang}}>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Zettelstore">
<meta name="format-detection" content="telephone=no">
{{{MetaHeader}}}
<link rel="stylesheet" href="{{{CSSBaseURL}}}">
<link rel="stylesheet" href="{{{CSSUserURL}}}">
{{#CSSRoleURL}}<link rel="stylesheet" href="{{{CSSRoleURL}}}">{{/CSSRoleURL}}
<title>{{Title}}</title>
</head>
<body>
<nav class="zs-menu">
<a href="{{{HomeURL}}}">Home</a>
{{#WithUser}}
<div class="zs-dropdown">
|
︙ | | |
52
53
54
55
56
57
58
59
60
61
62
63
|
56
57
58
59
60
61
62
63
64
65
66
|
-
-
+
+
+
-
-
+
-
|
<form action="{{{SearchURL}}}">
<input type="text" placeholder="Search.." name="{{QueryKeySearch}}">
</form>
</nav>
<main class="content">
{{{Content}}}
</main>
{{#FooterHTML}}
<footer>
{{#FooterHTML}}<footer>{{{FooterHTML}}}</footer>{{/FooterHTML}}
{{#DebugMode}}<div><b>WARNING: Debug mode is enabled. DO NOT USE IN PRODUCTION!</b></div>{{/DebugMode}}
</body>
{{{FooterHTML}}}
</footer>
</html>
{{/FooterHTML}}
|
| | |
Changes to box/constbox/constbox.go.
︙ | | |
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
|
+
+
+
+
+
+
+
+
-
+
|
constHeader{
api.KeyTitle: "Zettelstore User CSS",
api.KeyRole: api.ValueRoleConfiguration,
api.KeySyntax: "css",
api.KeyVisibility: api.ValueVisibilityPublic,
},
domain.NewContent([]byte("/* User-defined CSS */"))},
id.RoleCSSMapZid: {
constHeader{
api.KeyTitle: "Zettelstore Role to CSS Map",
api.KeyRole: api.ValueRoleConfiguration,
api.KeySyntax: api.ValueSyntaxNone,
api.KeyVisibility: api.ValueVisibilityExpert,
},
domain.NewContent(nil)},
id.EmojiZid: {
constHeader{
api.KeyTitle: "Generic Emoji",
api.KeyTitle: "Zettelstore Generic Emoji",
api.KeyRole: api.ValueRoleConfiguration,
api.KeySyntax: api.ValueSyntaxGif,
api.KeyReadOnly: api.ValueTrue,
api.KeyVisibility: api.ValueVisibilityPublic,
},
domain.NewContent(contentEmoji)},
id.TOCNewTemplateZid: {
|
︙ | | |
Changes to box/constbox/delete.mustache.
︙ | | |
33
34
35
36
37
38
39
40
41
42
43
|
33
34
35
36
37
38
39
40
41
42
43
|
-
+
|
{{/HasUselessFiles}}
<dl>
{{#MetaPairs}}
<dt>{{Key}}:</dt><dd>{{Value}}</dd>
{{/MetaPairs}}
</dl>
<form method="POST">
<input class="zs-button" type="submit" value="Delete">
<input class="zs-primary" type="submit" value="Delete">
</form>
</article>
{{end}}
|
Changes to box/constbox/form.mustache.
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
|
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
|
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
+
+
+
|
<article>
<header>
<h1>{{Heading}}</h1>
</header>
<form method="POST">
<div>
<label for="title">Title</label>
<input class="zs-input" type="text" id="title" name="title" placeholder="Title.." value="{{MetaTitle}}" autofocus>
<label for="zs-title">Title <a title="Main heading of this zettel. You can use inline zettelmarkup.">ⓘ</a></label>
<input class="zs-input" type="text" id="zs-title" name="title" placeholder="Title.." value="{{MetaTitle}}" autofocus>
</div>
<div>
<div>
<label for="role">Role</label>
<input class="zs-input" type="text" id="role" name="role" placeholder="role.." value="{{MetaRole}}">
<label for="zs-role">Role <a title="One word, without spaces, to set the main role of this zettel.">ⓘ</a></label>
<input class="zs-input" type="text" id="zs-role" {{#HasRoleData}}list="zs-role-data"{{/HasRoleData}} name="role" placeholder="role.." value="{{MetaRole}}">
{{#HasRoleData}}
<datalist id="zs-role-data">
{{#RoleData}}
<option value="{{.}}">
{{/RoleData}}
</datalist>
{{/HasRoleData}}
</div>
<label for="tags">Tags</label>
<input class="zs-input" type="text" id="tags" name="tags" placeholder="#tag" value="{{MetaTags}}">
<label for="zs-tags">Tags <a title="Tags must begin with an '#' sign. They are separated by spaces.">ⓘ</a></label>
<input class="zs-input" type="text" id="zs-tags" name="tags" placeholder="#tag" value="{{MetaTags}}">
</div>
<div>
<label for="meta">Metadata</label>
<textarea class="zs-input" id="meta" name="meta" rows="4" placeholder="metakey: metavalue">
<label for="zs-meta">Metadata <a title="Other metadata for this zettel. Each line contains a key/value pair, separated by a colon ':'.">ⓘ</a></label>
<textarea class="zs-input" id="zs-meta" name="meta" rows="4" placeholder="metakey: metavalue">
{{#MetaPairsRest}}
{{Key}}: {{Value}}
{{/MetaPairsRest}}
</textarea>
</div>
<div>
<label for="syntax">Syntax</label>
<input class="zs-input" type="text" id="syntax" name="syntax" placeholder="syntax.." value="{{MetaSyntax}}">
</div>
<label for="zs-syntax">Syntax <a title="Syntax of zettel content below, one word. Typically 'zmk' (for zettelmarkup).">ⓘ</a></label>
<input class="zs-input" type="text" id="zs-syntax" {{#HasSyntaxData}}list="zs-syntax-data"{{/HasSyntaxData}} name="syntax" placeholder="syntax.." value="{{MetaSyntax}}">
{{#HasSyntaxData}}
<datalist id="zs-syntax-data">
{{#SyntaxData}}
<option value="{{.}}">
{{/SyntaxData}}
</datalist>
{{/HasSyntaxData}}</div>
<div>
{{#IsTextContent}}
<label for="content">Content</label>
<textarea class="zs-input zs-content" id="meta" name="content" rows="20" placeholder="Your content..">{{Content}}</textarea>
<label for="zs-content">Content <a title="Content for this zettel, according to above syntax.">ⓘ</a></label>
<textarea class="zs-input zs-content" id="zs-content" name="content" rows="20" placeholder="Your content..">{{Content}}</textarea>
{{/IsTextContent}}
</div>
<div>
<input class="zs-button" type="submit" value="Submit">
<input class="zs-primary" type="submit" value="Submit">
<input class="zs-secondary" type="submit" value="Save" formaction="?save">
</div>
</form>
</article>
|
Changes to box/constbox/login.mustache.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-
+
-
+
-
+
|
<article>
<header>
<h1>{{Title}}</h1>
</header>
{{#Retry}}
<div class="zs-indication zs-error">Wrong user name / password. Try again.</div>
{{/Retry}}
<form method="POST" action="">
<div>
<label for="username">User name</label>
<label for="username">User name:</label>
<input class="zs-input" type="text" id="username" name="username" placeholder="Your user name.." autofocus>
</div>
<div>
<label for="password">Password</label>
<label for="password">Password:</label>
<input class="zs-input" type="password" id="password" name="password" placeholder="Your password..">
</div>
<input class="zs-button" type="submit" value="Login">
<div><input class="zs-primary" type="submit" value="Login"></div>
</form>
</article>
|
Changes to box/constbox/rename.mustache.
︙ | | |
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
-
+
|
{{/HasUselessFiles}}
<form method="POST">
<div>
<label for="newid">New zettel id</label>
<input class="zs-input" type="text" id="newzid" name="newzid" placeholder="ZID.." value="{{Zid}}" autofocus>
</div>
<input type="hidden" id="curzid" name="curzid" value="{{Zid}}">
<input class="zs-button" type="submit" value="Rename">
<div><input class="zs-primary" type="submit" value="Rename"></div>
</form>
<dl>
{{#MetaPairs}}
<dt>{{Key}}:</dt><dd>{{Value}}</dd>
{{/MetaPairs}}
</dl>
</article>
|
Changes to box/dirbox/dirbox.go.
︙ | | |
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
-
|
"context"
"errors"
"net/url"
"os"
"path/filepath"
"sync"
"zettelstore.de/c/api"
"zettelstore.de/z/box"
"zettelstore.de/z/box/manager"
"zettelstore.de/z/box/notify"
"zettelstore.de/z/domain"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
"zettelstore.de/z/kernel"
|
︙ | | |
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
|
-
-
|
if !entry.IsValid() {
return domain.Zettel{}, box.ErrNotFound
}
m, c, err := dp.srvGetMetaContent(ctx, entry, zid)
if err != nil {
return domain.Zettel{}, err
}
dp.cleanupMeta(m)
zettel := domain.Zettel{Meta: m, Content: domain.NewContent(c)}
dp.log.Trace().Zid(zid).Msg("GetZettel")
return zettel, nil
}
func (dp *dirBox) GetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error) {
m, err := dp.doGetMeta(ctx, zid)
dp.log.Trace().Zid(zid).Err(err).Msg("GetMeta")
return m, err
}
func (dp *dirBox) doGetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error) {
entry := dp.dirSrv.GetDirEntry(zid)
if !entry.IsValid() {
return nil, box.ErrNotFound
}
m, err := dp.srvGetMeta(ctx, entry, zid)
if err != nil {
return nil, err
}
dp.cleanupMeta(m)
return m, nil
}
func (dp *dirBox) ApplyZid(_ context.Context, handle box.ZidFunc, constraint search.RetrievePredicate) error {
entries := dp.dirSrv.GetDirEntries(constraint)
dp.log.Trace().Int("entries", int64(len(entries))).Msg("ApplyZid")
for _, entry := range entries {
|
︙ | | |
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
-
|
// The following loop could be parallelized if needed for performance.
for _, entry := range entries {
m, err := dp.srvGetMeta(ctx, entry, entry.Zid)
if err != nil {
dp.log.Trace().Err(err).Msg("ApplyMeta/getMeta")
return err
}
dp.cleanupMeta(m)
dp.cdata.Enricher.Enrich(ctx, m, dp.number)
handle(m)
}
return nil
}
func (dp *dirBox) CanUpdateZettel(context.Context, domain.Zettel) bool {
|
︙ | | |
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
|
393
394
395
396
397
398
399
|
-
-
-
-
-
-
-
-
-
|
}
func (dp *dirBox) ReadStats(st *box.ManagedBoxStats) {
st.ReadOnly = dp.readonly
st.Zettel = dp.dirSrv.NumDirEntries()
dp.log.Trace().Int("zettel", int64(st.Zettel)).Msg("ReadStats")
}
func (dp *dirBox) cleanupMeta(m *meta.Meta) {
if role, ok := m.Get(api.KeyRole); !ok || role == "" {
m.Set(api.KeyRole, dp.cdata.Config.GetDefaultRole())
}
if syntax, ok := m.Get(api.KeySyntax); !ok || syntax == "" {
m.Set(api.KeySyntax, dp.cdata.Config.GetDefaultSyntax())
}
}
|
Changes to box/dirbox/service.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package dirbox
|
︙ | | |
Changes to box/filebox/filebox.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2021-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
// Package filebox provides boxes that are stored in a file.
|
︙ | | |
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
|
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
-
-
-
-
-
|
}
return ext
}
// CalcDefaultMeta returns metadata with default values for the given entry.
func CalcDefaultMeta(zid id.Zid, ext string) *meta.Meta {
m := meta.New(zid)
m.Set(api.KeyTitle, zid.String())
m.Set(api.KeySyntax, calculateSyntax(ext))
return m
}
// CleanupMeta enhances the given metadata.
func CleanupMeta(m *meta.Meta, zid id.Zid, ext string, inMeta bool, uselessFiles []string) {
if title, ok := m.Get(api.KeyTitle); !ok || title == "" {
m.Set(api.KeyTitle, zid.String())
}
if inMeta {
if syntax, ok := m.Get(api.KeySyntax); !ok || syntax == "" {
dm := CalcDefaultMeta(zid, ext)
syntax, ok = dm.Get(api.KeySyntax)
if !ok {
panic("Default meta must contain syntax")
}
|
︙ | | |
Changes to box/filebox/zipbox.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2021-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package filebox
|
︙ | | |
Changes to box/manager/manager.go.
︙ | | |
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
-
+
|
// Package manager coordinates the various boxes and indexes of a Zettelstore.
package manager
import (
"context"
"io"
"net/url"
"sort"
"sync"
"time"
"zettelstore.de/c/maps"
"zettelstore.de/z/auth"
"zettelstore.de/z/box"
"zettelstore.de/z/box/manager/memstore"
"zettelstore.de/z/box/manager/store"
"zettelstore.de/z/config"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
|
︙ | | |
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
-
+
-
-
-
-
-
-
-
|
if _, ok := registry[scheme]; ok {
panic(scheme)
}
registry[scheme] = create
}
// GetSchemes returns all registered scheme, ordered by scheme string.
func GetSchemes() []string {
func GetSchemes() []string { return maps.Keys(registry) }
result := make([]string, 0, len(registry))
for scheme := range registry {
result = append(result, scheme)
}
sort.Strings(result)
return result
}
// Manager is a coordinating box.
type Manager struct {
mgrLog *logger.Logger
mgrMx sync.RWMutex
started bool
rtConfig config.Config
|
︙ | | |
Changes to box/manager/memstore/memstore.go.
︙ | | |
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
+
|
"fmt"
"io"
"sort"
"strings"
"sync"
"zettelstore.de/c/api"
"zettelstore.de/c/maps"
"zettelstore.de/z/box/manager/store"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
)
type metaRefs struct {
forward id.Slice
|
︙ | | |
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
|
587
588
589
590
591
592
593
594
595
596
597
598
|
-
-
-
-
-
-
+
|
}
func dumpStringRefs(w io.Writer, title, preString, postString string, srefs stringRefs) {
if len(srefs) == 0 {
return
}
fmt.Fprintln(w, "====", title)
slice := make([]string, 0, len(srefs))
for s := range srefs {
slice = append(slice, s)
}
sort.Strings(slice)
for _, s := range slice {
for _, s := range maps.Keys(srefs) {
fmt.Fprintf(w, "; %s%s%s\n", preString, s, postString)
fmt.Fprintln(w, ":", srefs[s])
}
}
|
Changes to box/notify/directory_test.go.
︙ | | |
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
-
|
import (
"testing"
"zettelstore.de/c/api"
"zettelstore.de/z/domain/id"
_ "zettelstore.de/z/parser/blob" // Allow to use BLOB parser.
_ "zettelstore.de/z/parser/draw" // Allow to use draw parser.
_ "zettelstore.de/z/parser/markdown" // Allow to use markdown parser.
_ "zettelstore.de/z/parser/none" // Allow to use none parser.
_ "zettelstore.de/z/parser/plain" // Allow to use plain parser.
_ "zettelstore.de/z/parser/zettelmark" // Allow to use zettelmark parser.
)
func TestSeekZid(t *testing.T) {
|
︙ | | |
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
-
+
|
}
}
}
func TestNewExtIsBetter(t *testing.T) {
extVals := []string{
// Main Formats
api.ValueSyntaxZmk, api.ValueSyntaxDraw, "markdown", "md",
api.ValueSyntaxZmk, "markdown", "md",
// Other supported text formats
"css", "txt", api.ValueSyntaxHTML, api.ValueSyntaxNone, "mustache", api.ValueSyntaxText, "plain",
// Supported graphics formats
api.ValueSyntaxGif, "png", api.ValueSyntaxSVG, "jpeg", "jpg",
// Unsupported syntax values
"gz", "cpp", "tar", "cppc",
}
|
︙ | | |
Changes to box/notify/entry.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package notify
|
︙ | | |
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
-
+
|
}
func calcContentExt(syntax string, yamlSep bool, getZettelFileSyntax func() []string) string {
if yamlSep {
return extZettel
}
switch syntax {
case api.ValueSyntaxDraw, api.ValueSyntaxNone, api.ValueSyntaxZmk:
case api.ValueSyntaxNone, api.ValueSyntaxZmk:
return extZettel
}
for _, s := range getZettelFileSyntax() {
if s == syntax {
return extZettel
}
}
|
︙ | | |
Changes to cmd/cmd_file.go.
︙ | | |
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
-
+
-
-
|
domain.Zettel{
Meta: m,
Content: domain.NewContent(inp.Src[inp.Pos:]),
},
m.GetDefault(api.KeySyntax, api.ValueSyntaxZmk),
nil,
)
encdr := encoder.Create(api.Encoder(enc), &encoder.Environment{
encdr := encoder.Create(api.Encoder(enc))
Lang: m.GetDefault(api.KeyLang, api.ValueLangEN),
})
if encdr == nil {
fmt.Fprintf(os.Stderr, "Unknown format %q\n", enc)
return 2, nil
}
_, err = encdr.WriteZettel(os.Stdout, z, parser.ParseMetadata)
if err != nil {
return 2, err
|
︙ | | |
Changes to cmd/cmd_run.go.
︙ | | |
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
-
+
|
"zettelstore.de/z/web/adapter/webui"
"zettelstore.de/z/web/server"
)
// ---------- Subcommand: run ------------------------------------------------
func flgRun(fs *flag.FlagSet) {
fs.String("c", defConfigfile, "configuration file")
fs.String("c", "", "configuration file")
fs.Uint("a", 0, "port number kernel service (0=disable)")
fs.Uint("p", 23123, "port number web service")
fs.String("d", "", "zettel directory")
fs.Bool("r", false, "system-wide read-only mode")
fs.Bool("v", false, "verbose mode")
fs.Bool("debug", false, "debug mode")
}
|
︙ | | |
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
|
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
|
+
-
+
-
+
-
+
+
-
-
|
ucCreateZettel := usecase.NewCreateZettel(ucLog, rtConfig, protectedBoxManager)
ucGetMeta := usecase.NewGetMeta(protectedBoxManager)
ucGetAllMeta := usecase.NewGetAllMeta(protectedBoxManager)
ucGetZettel := usecase.NewGetZettel(protectedBoxManager)
ucParseZettel := usecase.NewParseZettel(rtConfig, ucGetZettel)
ucEvaluate := usecase.NewEvaluate(rtConfig, ucGetZettel, ucGetMeta)
ucListMeta := usecase.NewListMeta(protectedBoxManager)
ucListSyntax := usecase.NewListSyntax(protectedBoxManager)
ucListRoles := usecase.NewListRole(protectedBoxManager)
ucListRoles := usecase.NewListRoles(protectedBoxManager)
ucListTags := usecase.NewListTags(protectedBoxManager)
ucZettelContext := usecase.NewZettelContext(protectedBoxManager, rtConfig)
ucDelete := usecase.NewDeleteZettel(ucLog, protectedBoxManager)
ucUpdate := usecase.NewUpdateZettel(ucLog, protectedBoxManager)
ucRename := usecase.NewRenameZettel(ucLog, protectedBoxManager)
ucUnlinkedRefs := usecase.NewUnlinkedReferences(protectedBoxManager, rtConfig)
ucRefresh := usecase.NewRefresh(ucLog, protectedBoxManager)
ucVersion := usecase.NewVersion(kernel.Main.GetConfig(kernel.CoreService, kernel.CoreVersion).(string))
webSrv.Handle("/", wui.MakeGetRootHandler(protectedBoxManager))
// Web user interface
if !authManager.IsReadonly() {
webSrv.AddZettelRoute('b', server.MethodGet, wui.MakeGetRenameZettelHandler(
ucGetMeta, &ucEvaluate))
webSrv.AddZettelRoute('b', server.MethodPost, wui.MakePostRenameZettelHandler(&ucRename))
webSrv.AddZettelRoute('c', server.MethodGet, wui.MakeGetCreateZettelHandler(
ucGetZettel, &ucCreateZettel))
ucGetZettel, &ucCreateZettel, ucListRoles, ucListSyntax))
webSrv.AddZettelRoute('c', server.MethodPost, wui.MakePostCreateZettelHandler(&ucCreateZettel))
webSrv.AddZettelRoute('d', server.MethodGet, wui.MakeGetDeleteZettelHandler(
ucGetMeta, ucGetAllMeta, &ucEvaluate))
webSrv.AddZettelRoute('d', server.MethodPost, wui.MakePostDeleteZettelHandler(&ucDelete))
webSrv.AddZettelRoute('e', server.MethodGet, wui.MakeEditGetZettelHandler(ucGetZettel))
webSrv.AddZettelRoute('e', server.MethodGet, wui.MakeEditGetZettelHandler(ucGetZettel, ucListRoles, ucListSyntax))
webSrv.AddZettelRoute('e', server.MethodPost, wui.MakeEditSetZettelHandler(&ucUpdate))
}
webSrv.AddListRoute('g', server.MethodGet, wui.MakeGetGoActionHandler(&ucRefresh))
webSrv.AddListRoute('h', server.MethodGet, wui.MakeListHTMLMetaHandler(
ucListMeta, ucListRoles, ucListTags, &ucEvaluate))
webSrv.AddZettelRoute('h', server.MethodGet, wui.MakeGetHTMLZettelHandler(
&ucEvaluate, ucGetMeta))
webSrv.AddListRoute('i', server.MethodGet, wui.MakeGetLoginOutHandler())
webSrv.AddListRoute('i', server.MethodPost, wui.MakePostLoginHandler(&ucAuthenticate))
webSrv.AddZettelRoute('i', server.MethodGet, wui.MakeGetInfoHandler(
ucParseZettel, &ucEvaluate, ucGetMeta, ucGetAllMeta, ucUnlinkedRefs))
webSrv.AddZettelRoute('k', server.MethodGet, wui.MakeZettelContextHandler(
ucZettelContext, &ucEvaluate))
// API
webSrv.AddListRoute('a', server.MethodPost, a.MakePostLoginHandler(&ucAuthenticate))
webSrv.AddListRoute('a', server.MethodPut, a.MakeRenewAuthHandler())
webSrv.AddListRoute('j', server.MethodGet, a.MakeListMetaHandler(ucListMeta))
webSrv.AddZettelRoute('j', server.MethodGet, a.MakeGetZettelHandler(ucGetZettel))
webSrv.AddListRoute('m', server.MethodGet, a.MakeListMapMetaHandler(ucListRoles, ucListTags))
webSrv.AddZettelRoute('m', server.MethodGet, a.MakeGetMetaHandler(ucGetMeta))
webSrv.AddZettelRoute('o', server.MethodGet, a.MakeGetOrderHandler(
usecase.NewZettelOrder(protectedBoxManager, ucEvaluate)))
webSrv.AddZettelRoute('p', server.MethodGet, a.MakeGetParsedZettelHandler(ucParseZettel))
webSrv.AddListRoute('r', server.MethodGet, a.MakeListRoleHandler(ucListRoles))
webSrv.AddListRoute('t', server.MethodGet, a.MakeListTagsHandler(ucListTags))
webSrv.AddZettelRoute('u', server.MethodGet, a.MakeListUnlinkedMetaHandler(
ucGetMeta, ucUnlinkedRefs, &ucEvaluate))
webSrv.AddZettelRoute('v', server.MethodGet, a.MakeGetEvalZettelHandler(ucEvaluate))
webSrv.AddListRoute('x', server.MethodGet, a.MakeGetDataHandler(ucVersion))
webSrv.AddListRoute('x', server.MethodPost, a.MakePostCommandHandler(&ucIsAuth, &ucRefresh))
webSrv.AddZettelRoute('x', server.MethodGet, a.MakeZettelContextHandler(ucZettelContext))
webSrv.AddListRoute('z', server.MethodGet, a.MakeListPlainHandler(ucListMeta))
|
︙ | | |
Changes to cmd/command.go.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
+
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2021 Detlef Stern
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package cmd
import (
"flag"
"sort"
"zettelstore.de/c/maps"
"zettelstore.de/z/logger"
)
// Command stores information about commands / sub-commands.
type Command struct {
Name string // command name as it appears on the command line
Func CommandFunc // function that executes a command
|
︙ | | |
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
59
60
61
62
63
64
65
66
|
-
+
-
-
-
-
-
-
-
|
// Get returns the command identified by the given name and a bool to signal success.
func Get(name string) (Command, bool) {
cmd, ok := commands[name]
return cmd, ok
}
// List returns a sorted list of all registered command names.
func List() []string {
func List() []string { return maps.Keys(commands) }
result := make([]string, 0, len(commands))
for name := range commands {
result = append(result, name)
}
sort.Strings(result)
return result
}
|
Changes to cmd/main.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
|
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
|
-
+
+
-
+
-
-
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
package cmd
import (
"errors"
"flag"
"fmt"
"net"
"net/url"
"os"
"runtime/debug"
"strconv"
"strings"
"zettelstore.de/c/api"
"zettelstore.de/z/auth"
"zettelstore.de/z/auth/impl"
"zettelstore.de/z/box"
"zettelstore.de/z/box/compbox"
"zettelstore.de/z/box/manager"
"zettelstore.de/z/config"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
"zettelstore.de/z/input"
"zettelstore.de/z/kernel"
"zettelstore.de/z/logger"
"zettelstore.de/z/web/server"
)
const (
const strRunSimple = "run-simple"
defConfigfile = ".zscfg"
)
func init() {
RegisterCommand(Command{
Name: "help",
Func: func(*flag.FlagSet) (int, error) {
fmt.Println("Available commands:")
for _, name := range List() {
|
︙ | | |
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
-
+
|
Func: runFunc,
Boxes: true,
Header: true,
LineServer: true,
SetFlags: flgRun,
})
RegisterCommand(Command{
Name: "run-simple",
Name: strRunSimple,
Func: runFunc,
Simple: true,
Boxes: true,
Header: true,
// LineServer: true,
SetFlags: func(fs *flag.FlagSet) {
// fs.Uint("a", 0, "port number kernel service (0=disable)")
|
︙ | | |
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
|
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
|
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
|
})
RegisterCommand(Command{
Name: "password",
Func: cmdPassword,
})
}
func readConfig(fs *flag.FlagSet) (cfg *meta.Meta) {
func fetchStartupConfiguration(fs *flag.FlagSet) (cfg *meta.Meta) {
var configFile string
if configFlag := fs.Lookup("c"); configFlag != nil {
configFile = configFlag.Value.String()
} else {
configFile = defConfigfile
}
content, err := os.ReadFile(configFile)
if filename := configFlag.Value.String(); filename != "" {
content, err := readConfiguration(filename)
return createConfiguration(content, err)
}
}
content, err := searchAndReadConfiguration()
return createConfiguration(content, err)
}
func createConfiguration(content []byte, err error) *meta.Meta {
if err != nil {
return meta.New(id.Invalid)
}
return meta.NewFromInput(id.Invalid, input.NewInput(content))
}
func readConfiguration(filename string) ([]byte, error) { return os.ReadFile(filename) }
func searchAndReadConfiguration() ([]byte, error) {
for _, filename := range []string{"zettelstore.cfg", "zsconfig.txt", "zscfg.txt", "_zscfg"} {
if content, err := readConfiguration(filename); err == nil {
return content, nil
}
}
return readConfiguration(".zscfg")
}
func getConfig(fs *flag.FlagSet) *meta.Meta {
cfg := readConfig(fs)
cfg := fetchStartupConfiguration(fs)
fs.Visit(func(flg *flag.Flag) {
switch flg.Name {
case "p":
if portStr, err := parsePort(flg.Value.String()); err == nil {
cfg.Set(keyListenAddr, net.JoinHostPort("127.0.0.1", portStr))
}
case "a":
|
︙ | | |
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
+
|
const (
keyAdminPort = "admin-port"
keyDebug = "debug-mode"
keyDefaultDirBoxType = "default-dir-box-type"
keyInsecureCookie = "insecure-cookie"
keyListenAddr = "listen-addr"
keyLogLevel = "log-level"
keyMaxRequestSize = "max-request-size"
keyOwner = "owner"
keyPersistentCookie = "persistent-cookie"
keyBoxOneURI = kernel.BoxURIs + "1"
keyReadOnly = "read-only-mode"
keyTokenLifetimeHTML = "token-lifetime-html"
keyTokenLifetimeAPI = "token-lifetime-api"
keyURLPrefix = "url-prefix"
|
︙ | | |
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
+
+
+
|
ok = setConfigValue(
ok, kernel.WebService, kernel.WebListenAddress,
cfg.GetDefault(keyListenAddr, "127.0.0.1:23123"))
ok = setConfigValue(ok, kernel.WebService, kernel.WebURLPrefix, cfg.GetDefault(keyURLPrefix, "/"))
ok = setConfigValue(ok, kernel.WebService, kernel.WebSecureCookie, !cfg.GetBool(keyInsecureCookie))
ok = setConfigValue(ok, kernel.WebService, kernel.WebPersistentCookie, cfg.GetBool(keyPersistentCookie))
if val, found := cfg.Get(keyMaxRequestSize); found {
ok = setConfigValue(ok, kernel.WebService, kernel.WebMaxRequestSize, val)
}
ok = setConfigValue(
ok, kernel.WebService, kernel.WebTokenLifetimeAPI, cfg.GetDefault(keyTokenLifetimeAPI, ""))
ok = setConfigValue(
ok, kernel.WebService, kernel.WebTokenLifetimeHTML, cfg.GetDefault(keyTokenLifetimeHTML, ""))
if !ok {
return errors.New("unable to set configuration")
|
︙ | | |
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
|
+
+
+
+
+
+
-
+
|
createManager = func(boxURIs []*url.URL, authManager auth.Manager, rtConfig config.Config) (box.Manager, error) {
compbox.Setup(cfg)
return manager.New(boxURIs, authManager, rtConfig)
}
} else {
createManager = func([]*url.URL, auth.Manager, config.Config) (box.Manager, error) { return nil, nil }
}
secret := cfg.GetDefault("secret", "")
if len(secret) < 16 && cfg.GetDefault(keyOwner, "") != "" {
fmt.Fprintf(os.Stderr, "secret must have at least length 16 when authentication is enabled, but is %q\n", secret)
return 2
}
kern.SetCreators(
func(readonly bool, owner id.Zid) (auth.Manager, error) {
return impl.New(readonly, owner, cfg.GetDefault("secret", "")), nil
return impl.New(readonly, owner, secret), nil
},
createManager,
func(srv server.Server, plMgr box.Manager, authMgr auth.Manager, rtConfig config.Config) error {
setupRouting(srv, plMgr, authMgr, rtConfig)
return nil
},
)
|
︙ | | |
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
|
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
kern.Shutdown(true)
return exitCode
}
// runSimple is called, when the user just starts the software via a double click
// or via a simple call ``./zettelstore`` on the command line.
func runSimple() int {
if _, err := searchAndReadConfiguration(); err == nil {
return executeCommand(strRunSimple)
}
dir := "./zettel"
if err := os.MkdirAll(dir, 0750); err != nil {
fmt.Fprintf(os.Stderr, "Unable to create zettel directory %q (%s)\n", dir, err)
return 1
}
return executeCommand("run-simple", "-d", dir)
return executeCommand(strRunSimple, "-d", dir)
}
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
// Main is the real entrypoint of the zettelstore.
func Main(progName, buildVersion string) int {
fullVersion := retrieveFullVersion(buildVersion)
kernel.Main.SetConfig(kernel.CoreService, kernel.CoreProgname, progName)
kernel.Main.SetConfig(kernel.CoreService, kernel.CoreVersion, buildVersion)
kernel.Main.SetConfig(kernel.CoreService, kernel.CoreVersion, fullVersion)
flag.Parse()
if *cpuprofile != "" || *memprofile != "" {
if *cpuprofile != "" {
kernel.Main.StartProfiling(kernel.ProfileCPU, *cpuprofile)
} else {
kernel.Main.StartProfiling(kernel.ProfileHead, *memprofile)
}
defer kernel.Main.StopProfiling()
}
args := flag.Args()
if len(args) == 0 {
return runSimple()
}
return executeCommand(args[0], args[1:]...)
}
func retrieveFullVersion(version string) string {
info, ok := debug.ReadBuildInfo()
if !ok {
return version
}
var revision, dirty string
for _, kv := range info.Settings {
switch kv.Key {
case "vcs.revision":
revision = "+" + kv.Value
if len(revision) > 11 {
revision = revision[:11]
}
case "vcs.modified":
if kv.Value == "true" {
dirty = "-dirty"
}
}
}
return version + revision + dirty
}
|
Changes to cmd/register.go.
︙ | | |
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
-
+
-
|
import (
_ "zettelstore.de/z/box/compbox" // Allow to use computed box.
_ "zettelstore.de/z/box/constbox" // Allow to use global internal box.
_ "zettelstore.de/z/box/dirbox" // Allow to use directory box.
_ "zettelstore.de/z/box/filebox" // Allow to use file box.
_ "zettelstore.de/z/box/membox" // Allow to use in-memory box.
_ "zettelstore.de/z/encoder/htmlenc" // Allow to use HTML encoder.
_ "zettelstore.de/z/encoder/nativeenc" // Allow to use native encoder.
_ "zettelstore.de/z/encoder/sexprenc" // Allow to use sexpr encoder.
_ "zettelstore.de/z/encoder/textenc" // Allow to use text encoder.
_ "zettelstore.de/z/encoder/zjsonenc" // Allow to use ZJSON encoder.
_ "zettelstore.de/z/encoder/zmkenc" // Allow to use zmk encoder.
_ "zettelstore.de/z/kernel/impl" // Allow kernel implementation to create itself
_ "zettelstore.de/z/parser/blob" // Allow to use BLOB parser.
_ "zettelstore.de/z/parser/draw" // Allow to use draw parser.
_ "zettelstore.de/z/parser/markdown" // Allow to use markdown parser.
_ "zettelstore.de/z/parser/none" // Allow to use none parser.
_ "zettelstore.de/z/parser/plain" // Allow to use plain parser.
_ "zettelstore.de/z/parser/zettelmark" // Allow to use zettelmark parser.
)
|
Changes to config/config.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2021 Detlef Stern
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
// Package config provides functions to retrieve runtime configuration data.
|
︙ | | |
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
|
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
-
-
-
-
-
-
-
-
-
-
-
-
|
// Config allows to retrieve all defined configuration values that can be changed during runtime.
type Config interface {
AuthConfig
// AddDefaultValues enriches the given meta data with its default values.
AddDefaultValues(m *meta.Meta) *meta.Meta
// GetDefaultTitle returns the current value of the "default-title" key.
GetDefaultTitle() string
// GetDefaultRole returns the current value of the "default-role" key.
GetDefaultRole() string
// GetDefaultSyntax returns the current value of the "default-syntax" key.
GetDefaultSyntax() string
// GetDefaultLang returns the current value of the "default-lang" key.
GetDefaultLang() string
// GetSiteName returns the current value of the "site-name" key.
GetSiteName() string
// GetHomeZettel returns the value of the "home-zettel" key.
GetHomeZettel() id.Zid
// GetDefaultVisibility returns the default value for zettel visibility.
GetDefaultVisibility() meta.Visibility
// GetMaxTransclusions return the maximum number of indirect transclusions.
GetMaxTransclusions() int
// GetYAMLHeader returns the current value of the "yaml-header" key.
GetYAMLHeader() bool
// GetZettelFileSyntax returns the current value of the "zettel-file-syntax" key.
|
︙ | | |
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
|
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
// GetExpertMode returns the current value of the "expert-mode" key.
GetExpertMode() bool
// GetVisibility returns the visibility value of the metadata.
GetVisibility(m *meta.Meta) meta.Visibility
}
// GetTitle returns the value of the "title" key of the given meta. If there
// is no such value, GetDefaultTitle is returned.
func GetTitle(m *meta.Meta, cfg Config) string {
if val, ok := m.Get(api.KeyTitle); ok {
return val
}
if cfg != nil {
return cfg.GetDefaultTitle()
}
return "Untitled"
}
// GetRole returns the value of the "role" key of the given meta. If there
// is no such value, GetDefaultRole is returned.
func GetRole(m *meta.Meta, cfg Config) string {
if val, ok := m.Get(api.KeyRole); ok {
return val
}
return cfg.GetDefaultRole()
}
// GetSyntax returns the value of the "syntax" key of the given meta. If there
// is no such value, GetDefaultSyntax is returned.
func GetSyntax(m *meta.Meta, cfg Config) string {
if val, ok := m.Get(api.KeySyntax); ok {
return val
}
return cfg.GetDefaultSyntax()
}
// GetLang returns the value of the "lang" key of the given meta. If there is
// no such value, GetDefaultLang is returned.
func GetLang(m *meta.Meta, cfg Config) string {
if val, ok := m.Get(api.KeyLang); ok {
return val
}
return cfg.GetDefaultLang()
}
|
Changes to docs/manual/00001003305000.zettel.
︙ | | |
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
-
+
|
All you have to do is to open your web browser, enter the appropriate URL, and there you go.
On the negative side, you will not be notified when you enter the wrong data in the Task scheduler and Zettelstore fails to start.
This can be mitigated by first using the command line prompt to start Zettelstore with the appropriate options.
Once everything works, you can register Zettelstore to be automatically started by the task scheduler.
There you should make sure that you have followed the first steps as described on the [[parent page|00001003300000]].
To sart the Task scheduler management console, press the Windows logo key and the key ''R'', type ''taskschd.msc''.
To start the Task scheduler management console, press the Windows logo key and the key ''R'', type ''taskschd.msc''.
Select the OK button.
{{00001003305102}}
This will start the ""Task Scheduler"".
Now, create a new task with ""Create Task ...""
|
︙ | | |
Changes to docs/manual/00001003310000.zettel.
︙ | | |
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
-
+
|
=== Launch Agent
If you want to execute Zettelstore automatically and less visible, and if you know a little bit about working in the terminal application, then you could try to run Zettelstore under the control of the [[Launchd system|https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Introduction.html]].
First, you have to create a description for ""Launchd"".
This is a text file named ''zettelstore.plist'' with the following content.
It assumes that you have copied the Zettelstore executable in a local folder called ''~/bin'' and have created a file for [[startup configuration|00001004010000]] called ''zettelstore.cfg'', which is placed in the same folder[^If you are not using a confguration file, just remove the lines ``<string>-c</string>`` and ``<string>/Users/USERNAME/bin/zettelstore.cfg</string>``.]:
It assumes that you have copied the Zettelstore executable in a local folder called ''~/bin'' and have created a file for [[startup configuration|00001004010000]] called ''zettelstore.cfg'', which is placed in the same folder[^If you are not using a configuration file, just remove the lines ``<string>-c</string>`` and ``<string>/Users/USERNAME/bin/zettelstore.cfg</string>``.]:
```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
|
︙ | | |
Changes to docs/manual/00001004010000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001004010000
title: Zettelstore startup configuration
role: manual
tags: #configuration #manual #zettelstore
syntax: zmk
modified: 20220304115353
modified: 20220419193611
The configuration file, as specified by the ''-c CONFIGFILE'' [[command line option|00001004051000]], allows you to specify some startup options.
These options cannot be stored in a [[configuration zettel|00001004020000]] because either they are needed before Zettelstore can start or because of security reasons.
For example, Zettelstore need to know in advance, on which network address is must listen or where zettel are stored.
An attacker that is able to change the owner can do anything.
Therefore only the owner of the computer on which Zettelstore runs can change this information.
|
︙ | | |
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
|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
|
; [!log-level|''log-level'']
: Specify the global [[logging level|00001004059700]] for the whole application, overwriting the level ""debug"" set by configuration [[''debug-mode''|#debug-mode]].
Can be changed at runtime, even for specific internal services, with the ''log-level'' command of the [[administrator console|00001004101000#log-level]].
Default: ""info"".
When you are familiar to operate the Zettelstore, you might set the level to ""warn"" or ""error"" to receive less noisy messages from the Zettelstore.
; [!max-request-size|''max-request-size'']
: Limits the maximum byte size of a web request body to prevent clients from accidentally or maliciously sending a large request and wasting server resources.
The minimum value is 1024.
Default: 16777216 (16 MiB).
; [!owner|''owner'']
: [[Identifier|00001006050000]] of a zettel that contains data about the owner of the Zettelstore.
The owner has full authorization for the Zettelstore.
Only if owner is set to some value, user [[authentication|00001010000000]] is enabled.
Ensure that key [[''secret''|#secret]] is set to a value of at least 16 bytes.
Otherwise the Zettelstore will not start for security reasons.
; [!persistent-cookie|''persistent-cookie'']
: A [[boolean value|00001006030500]] to make the access cookie persistent.
This is helpful if you access the Zettelstore via a mobile device.
On these devices, the operating system is free to stop the web browser and to remove temporary cookies.
Therefore, an authenticated user will be logged off.
If ""true"", a persistent cookie is used.
Its lifetime exceeds the lifetime of the authentication token (see option ''token-lifetime-html'') by 30 seconds.
Default: ""false""
; [!read-only-mode|''read-only-mode'']
: Puts the Zettelstore service into a read-only mode, if set to a [[true value|00001006030500]].
No changes are possible.
Default: ""false"".
; [!secret|''secret'']
: A string value to make the communication with external clients strong enough so that sessions of the [[web user interface|00001014000000]] or [[API access token|00001010040700]] cannot be modified by some external unfriendly party.
The string must have a length of at least 16 bytes.
It is only needed to set this value, if [[authentication is enabled|00001010040100]] by setting key [[''owner''|#owner]] to some user identification.
; [!token-lifetime-api|''token-lifetime-api''], [!token-lifetime-html|''token-lifetime-html'']
: Define lifetime of access tokens in minutes.
Values are only valid if authentication is enabled, i.e. key ''owner'' is set.
''token-lifetime-api'' is for accessing Zettelstore via its [[API|00001012000000]].
Default: ""10"".
|
︙ | | |
Changes to docs/manual/00001004011400.zettel.
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
|
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
|
-
+
-
+
|
id: 00001004011400
title: Configure file directory boxes
role: manual
tags: #configuration #manual #zettelstore
syntax: zmk
modified: 20220307121244
modified: 20220724200512
Under certain circumstances, it is preferable to further configure a file directory box.
This is done by appending query parameters after the base box URI ''dir:\//DIR''.
The following parameters are supported:
|= Parameter:|Description|Default value:|
|type|(Sub-) Type of the directory service|(value of ""[[default-dir-box-type|00001004010000#default-dir-box-type]]"")
|worker|Number of worker that can access the directory in parallel|7
|readonly|Allow only operations that do not create or change zettel|n/a
=== Type
On some operating systems, Zettelstore tries to detect changes to zettel files outside of Zettelstore's control[^This includes Linux, Windows, and macOS.].
On other operating systems, this may be not possible, due to technical limitations.
Automatic detection of external changes is also not possible, if zettel files are put on an external service, such as a file server accessed via SMD/CIFS or NFS.
Automatic detection of external changes is also not possible, if zettel files are put on an external service, such as a file server accessed via SMB/CIFS or NFS.
To cope with this uncertainty, Zettelstore provides various internal implementations of a directory box.
The default values should match the needs of different users, as explained in the [[installation part|00001003000000]] of this manual.
The following values are supported:
; simple
: Is not able to detect external changes.
|
︙ | | |
Changes to docs/manual/00001004020000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001004020000
title: Configure the running Zettelstore
role: manual
tags: #configuration #manual #zettelstore
syntax: zmk
modified: 20220304114412
modified: 20220628110920
You can configure a running Zettelstore by modifying the special zettel with the ID [[00000000000100]].
This zettel is called __configuration zettel__.
The following metadata keys change the appearance / behavior of Zettelstore:
; [!default-copyright|''default-copyright'']
: Copyright value to be used when rendering content.
|
︙ | | |
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
|
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
-
-
-
-
-
-
-
-
-
-
-
|
This value is also used to specify the language for all non-zettel content, e.g. lists or search results.
Use values according to the language definition of [[RFC-5646|https://tools.ietf.org/html/rfc5646]].
; [!default-license|''default-license'']
: License value to be used when rendering content.
Can be overwritten in a zettel with [[meta key|00001006020000]] ''license''.
Default: (the empty string).
; [!default-role|''default-role'']
: Role to be used, if a zettel specifies no ''role'' [[meta key|00001006020000]].
Default: ""zettel"".
; [!default-syntax|''default-syntax'']
: Syntax to be used, if a zettel specifies no ''syntax'' [[meta key|00001006020000]].
Default: ""zmk"" (""[[Zettelmarkup|00001007000000]]"").
; [!default-title|''default-title'']
: Title to be used, if a zettel specifies no ''title'' [[meta key|00001006020000]].
Default: ""Untitled"".
You can use all [[inline-structured elements|00001007040000]] of Zettelmarkup.
; [!default-visibility|''default-visibility'']
: Visibility to be used, if zettel does not specify a value for the [[''visibility''|00001006020000#visibility]] metadata key.
Default: ""login"".
; [!expert-mode|''expert-mode'']
: If set to a [[boolean true value|00001006030500]], all zettel with [[visibility ""expert""|00001010070200]] will be shown (to the owner, if [[authentication is enabled|00001010040100]]; to all, otherwise).
This affects most computed zettel.
Default: ""False"".
|
︙ | | |
Changes to docs/manual/00001004051000.zettel.
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
|
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
|
-
+
-
+
|
id: 00001004051000
title: The ''run'' sub-command
role: manual
tags: #command #configuration #manual #zettelstore
syntax: zmk
modified: 20220214175947
modified: 20220724162050
=== ``zettelstore run``
This starts the web service.
```
zettelstore run [-a PORT] [-c CONFIGFILE] [-d DIR] [-debug] [-p PORT] [-r] [-v]
```
; [!a|''-a PORT'']
: Specifies the TCP port through which you can reach the [[administrator console|00001004100000]].
See the explanation of [[''admin-port''|00001004010000#admin-port]] for more details.
; [!c|''-c CONFIGFILE'']
: Specifies ''CONFIGFILE'' as a file, where [[startup configuration data|00001004010000]] is read.
It is ignored, when the given file is not available, nor readable.
Default: ''./.zscfg''. (''.\\.zscfg'' on Windows)), where ''.'' denotes the ""current directory"".
Default: tries to read the following files in the ""current directory"": ''zettelstore.cfg'', ''zsconfig.txt'', ''zscfg.txt'', ''_zscfg'', and ''.zscfg''.
; [!d|''-d DIR'']
: Specifies ''DIR'' as the directory that contains all zettel.
Default is ''./zettel'' (''.\\zettel'' on Windows), where ''.'' denotes the ""current directory"".
; [!debug|''-debug'']
: Allows better debugging of the internal web server by disabling any timeout values.
You should specify this only as a developer.
|
︙ | | |
Changes to docs/manual/00001004051100.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
+
+
+
+
+
-
+
|
id: 00001004051100
title: The ''run-simple'' sub-command
role: manual
tags: #command #configuration #manual #zettelstore
syntax: zmk
modified: 20220214180253
modified: 20220724162843
=== ``zettelstore run-simple``
This sub-command is implicitly called, when an user starts Zettelstore by double-clicking on its GUI icon.
It is s simplified variant of the [[''run'' sub-command|00001004051000]].
First, this sub-command checks if it can read a [[Zettelstore startup configuration|00001004010000]] file by trying the [[default values|00001004051000#c]].
If this is the case, ''run-simple'' just continues as the [[''run'' sub-command|00001004051000]], but ignores any command line options (including ''-d DIR'').[^This allows a [[curious user|00001003000000]] to become an intermediate user.]
It allows only to specify a zettel directory.
If no startup configuration was found, the sub-command allows only to specify a zettel directory.
The directory will be created automatically, if it does not exist.
This is a difference to the ''run'' sub-command, where the directory must exists.
In contrast to the ''run'' sub-command, other command line parameter are not allowed.
```
zettelstore run-simple [-d DIR]
```
|
︙ | | |
Changes to docs/manual/00001004051200.zettel.
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
|
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
|
-
+
-
+
|
id: 00001004051200
title: The ''file'' sub-command
role: manual
tags: #command #configuration #manual #zettelstore
syntax: zmk
modified: 20220209114650
modified: 20220423131738
Reads zettel data from a file (or from standard input / stdin) and renders it to standard output / stdout.
This allows Zettelstore to render files manually.
```
zettelstore file [-t FORMAT] [file-1 [file-2]]
```
; ''-t FORMAT''
: Specifies the output format.
Supported values are:
[[''html''|00001012920510]] (default),
[[''native''|00001012920513]],
[[''sexpr''|00001012920516]],
[[''text''|00001012920519]],
[[''zjson''|00001012920503]],
and [[''zmk''|00001012920522]].
; ''file-1''
: Specifies the file name, where at least metadata is read.
If ''file-2'' is not given, the zettel content is also read from here.
; ''file-2''
|
︙ | | |
Changes to docs/manual/00001004100000.zettel.
︙ | | |
14
15
16
17
18
19
20
21
22
23
24
25
|
14
15
16
17
18
19
20
21
22
23
24
25
|
-
+
|
In fact, the administrator console is __not__ a full telnet service.
It is merely a simple line-oriented service where each input line is interpreted separately.
Therefore, you can also use tools like [[netcat|https://nc110.sourceforge.io/]], [[socat|http://www.dest-unreach.org/socat/]], etc.
After connecting to the administrator console, there is no further authentication.
It is not needed because you must be logged in on the same computer where Zettelstore is running.
You cannot connect to the administrator console if you are on a different computer.
Of course, on multi-user systems with untrusted users, you should not enable the administrator console.
Of course, on multi-user systems with encrusted users, you should not enable the administrator console.
* Enable via [[command line|00001004051000#a]]
* Enable via [[configuration file|00001004010000#admin-port]]
* [[List of supported commands|00001004101000]]
|
Changes to docs/manual/00001005000000.zettel.
︙ | | |
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
|
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
|
-
+
-
+
|
# the empty file extension is used, when the content must be stored in its own file, e.g. image data;
in this case, the filename just the 14 digits of the zettel identifier, and optional characters except the period ''"."''.
Other filename extensions are used to determine the ""syntax"" of a zettel.
This allows to use other content within the Zettelstore, e.g. images or HTML templates.
For example, you want to store an important figure in the Zettelstore that is encoded as a ''.png'' file.
Since each zettel contains some metadata, e.g. the title of the figure, the question arises where these data should be stores.
The solution is a metafile with the same zettel identifier, but without a filename extension.
The solution is a meta-file with the same zettel identifier, but without a filename extension.
Zettelstore recognizes this situation and reads in both files for the one zettel containing the figure.
It maintains this relationship as long as theses files exists.
In case of some textual zettel content you do not want to store the metadata and the zettel content in two different files.
Here the ''.zettel'' extension will signal that the metadata and the zettel content will be put in the same file, separated by an empty line or a line with three dashes (""''-\-\-''"", also known as ""YAML separator"").
=== Predefined zettel
Zettelstore contains some [[predefined zettel|00001005090000]] to work properly.
The [[configuration zettel|00001004020000]] is one example.
To render the builtin [[web user interface|00001014000000]], some templates are used, as well as a [[layout specification in CSS|00000000020001]].
The icon that visualizes a broken image is a [[predefined GIF image|00000000040001]].
All of these are visible to the Zettelstore as zettel.
One reason for this is to allow you to modify these zettel to adapt Zettelstore to your needs and visual preferences.
Where are these zettel stored?
They are stored within the Zettelstore software itself, because one [[design goal|00001002000000]] was to have just one executable file to use Zettelstore.
But data stored within an executable programm cannot be changed later[^Well, it can, but it is a very bad idea to allow this. Mostly for security reasons.].
But data stored within an executable program cannot be changed later[^Well, it can, but it is a very bad idea to allow this. Mostly for security reasons.].
To allow changing predefined zettel, both the file store and the internal zettel store are internally chained together.
If you change a zettel, it will be always stored as a file.
If a zettel is requested, Zettelstore will first try to read that zettel from a file.
If such a file was not found, the internal zettel store is searched secondly.
Therefore, the file store ""shadows"" the internal zettel store.
|
︙ | | |
Changes to docs/manual/00001005090000.zettel.
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
|
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
|
-
+
-
+
+
|
id: 00001005090000
title: List of predefined zettel
role: manual
tags: #manual #reference #zettelstore
syntax: zmk
modified: 20211229000646
modified: 20220321192401
The following table lists all predefined zettel with their purpose.
|= Identifier :|= Title | Purpose
| [[00000000000001]] | Zettelstore Version | Contains the version string of the running Zettelstore
| [[00000000000002]] | Zettelstore Host | Contains the name of the computer running the Zettelstore
| [[00000000000003]] | Zettelstore Operating System | Contains the operating system and CPU architecture of the computer running the Zettelstore
| [[00000000000004]] | Zettelstore License | Lists the license of Zettelstore
| [[00000000000005]] | Zettelstore Contributors | Lists all contributors of Zettelstore
| [[00000000000006]] | Zettelstore Dependencies | Lists all licensed content
| [[00000000000007]] | Zettelstore Log | Lists the last 8192 log messages
| [[00000000000020]] | Zettelstore Box Manager | Contains some statistics about zettel boxes and the the index process
| [[00000000000090]] | Zettelstore Supported Metadata Keys | Contains all supported metadata keys, their [[types|00001006030000]], and more
| [[00000000000092]] | Zettelstore Supported Parser | Lists all supported values for metadata [[syntax|00001006020000#syntax]] that are recognized by Zettelstore
| [[00000000000096]] | Zettelstore Startup Configuration | Contains the effective values of the [[startup configuration|00001004010000]]
| [[00000000000100]] | Zettelstore Runtime Configuration | Allows to [[configure Zettelstore at runtime|00001004020000]]
| [[00000000010100]] | Zettelstore Base HTML Template | Contains the general layout of the HTML view
| [[00000000010200]] | Zettelstore Login Form HTML Template | Layout of the login form, when authentication is [[enabled|00001010040100]]
| [[00000000010300]] | Zettelstore List Meta HTML Template | Used when displaying a list of zettel
| [[00000000010401]] | Zettelstore Detail HTML Template | Layout for the HTML detail view of one zettel
| [[00000000010402]] | Zettelstore Info HTML Templöate | Layout for the information view of a specific zettel
| [[00000000010402]] | Zettelstore Info HTML Template | Layout for the information view of a specific zettel
| [[00000000010403]] | Zettelstore Form HTML Template | Form that is used to create a new or to change an existing zettel that contains text
| [[00000000010404]] | Zettelstore Rename Form HTML Template | View that is displayed to change the [[zettel identifier|00001006050000]]
| [[00000000010405]] | Zettelstore Delete HTML Template | View to confirm the deletion of a zettel
| [[00000000010500]] | Zettelstore List Roles HTML Template | Layout for listing all roles
| [[00000000010600]] | Zettelstore List Tags HTML Template | Layout of tags lists
| [[00000000020001]] | Zettelstore Base CSS | System-defined CSS file that is included by the [[Base HTML Template|00000000010100]]
| [[00000000025001]] | Zettelstore User CSS | User-defined CSS file that is included by the [[Base HTML Template|00000000010100]]
| [[00000000029000]] | Zettelstore Role to CSS Map | Maps [[role|00001006020000#role]] to a zettel identifier that is included by the [[Base HTML Template|00000000010100]] as an CSS file
| [[00000000040001]] | Generic Emoji | Image that is shown if [[original image reference|00001007040322]] is invalid
| [[00000000090000]] | New Menu | Contains items that should contain in the zettel template menu
| [[00000000090001]] | New Zettel | Template for a new zettel with role ""[[zettel|00001006020100]]""
| [[00000000090002]] | New User | Template for a new [[user zettel|00001010040200]]
| [[00010000000000]] | Home | Default home zettel, contains some welcome information
If a zettel is not linked, it is not accessible for the current user.
**Important:** All identifier may change until a stable version of the software is released.
|
Changes to docs/manual/00001006000000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001006000000
title: Layout of a Zettel
role: manual
tags: #design #manual #zettelstore
syntax: zmk
modified: 20220113185522
modified: 20220724165931
A zettel consists of two parts: the metadata and the zettel content.
Metadata gives some information mostly about the zettel content, how it should be interpreted, how it is sorted within Zettelstore.
The zettel content is, well, the actual content.
In many cases, the content is in plain text form.
Plain text is long-lasting.
However, content in binary format is also possible.
|
︙ | | |
21
22
23
24
25
26
27
28
29
|
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
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
The zettel content is your valuable content.
Zettelstore contains some predefined parsers that interpret the zettel content to the syntax of the zettel.
This includes markup languages, like [[Zettelmarkup|00001007000000]] and [[CommonMark|00001008010500]].
Other text formats are also supported, like CSS and HTML templates.
Plain text content is always Unicode, encoded as UTF-8.
Other character encodings are not supported and will never be[^This is not a real problem, since every modern software should support UTF-8 as an encoding.].
There is support for a graphical format with a text represenation: SVG.
There is support for a graphical format with a text representation: SVG.
And there is support for some binary image formats, like GIF, PNG, and JPEG.
=== Plain, parsed, and evaluated zettel
Zettelstore may present your zettel in various forms.
One way is to present the zettel as it was read by Zettelstore.
This is called ""[[plain zettel|00001003000000#plain]]"", typically retrieved with the [[endpoint|00001012920000]] ''/z/{ID}''.
The second way is to present the zettel as it was recognized by Zettelstore.
This is called ""[[parsed zettel|00001012053600]]"", typically retrieved with the [[endpoint|00001012920000]] ''/p/{ID}''.
Such a zettel was read and analyzed.
It can be presented in various [[encodings|00001012920500]].[^The [[zmk encoding|00001012920522]] allows you to compare the plain, the parsed, and the evaluated form of a zettel.]
However, a zettel such as this one you are currently reading, is a ""[[evaluated zettel|00001012053500]]"", typically retrieved with the [[endpoint|00001012920000]] ''/v/{ID}''.
The biggest difference to a parsed zettel is the inclusion of [[block transclusions|00001007031100]] or [[inline transclusions|00001007040324]] for an evaluated zettel.
It can also be presented in various encoding, including the ""zmk"" encoding.
Evaluations also applies to metadata of a zettel, if appropriate.
Please note, that searching for content is based on parsed zettel.
Transcluded content will only be found in transcluded zettel, but not in the zettel that transcluded the content.
However, you will easily pick up that zettel by follow the [[backward|00001006020000#backward]] metadata key of the transcluded zettel.
|
Changes to docs/manual/00001006020000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
-
+
-
+
|
id: 00001006020000
title: Supported Metadata Keys
role: manual
tags: #manual #meta #reference #zettel #zettelstore
syntax: zmk
modified: 20220218130146
modified: 20220628111132
Although you are free to define your own metadata, by using any key (according to the [[syntax|00001006010000]]), some keys have a special meaning that is enforced by Zettelstore.
See the [[computed list of supported metadata keys|00000000000090]] for details.
Most keys conform to a [[type|00001006030000]].
; [!all-tags|''all-tags'']
: A property (a computed values that is not stored) that contains both the value of [[''tags''|#tags]] together with all [[tags|00001007040000#tag]] that are specified within the content.
; [!back|''back'']
: Is a property that contains the identifier of all zettel that reference the zettel of this metadata, that are not referenced by this zettel.
Basically, it is the value of [[''backward''|#bachward]], but without any zettel identifier that is contained in [[''forward''|#forward]].
Basically, it is the value of [[''backward''|#backward]], but without any zettel identifier that is contained in [[''forward''|#forward]].
; [!backward|''backward'']
: Is a property that contains the identifier of all zettel that reference the zettel of this metadata.
References within invertible values are not included here, e.g. [[''precursor''|#precursor]].
; [!box-number|''box-number'']
: Is a computed value and contains the number of the box where the zettel was found.
For all but the [[predefined zettel|00001005090000]], this number is equal to the number __X__ specified in startup configuration key [[''box-uri-__X__''|00001004010000#box-uri-x]].
; [!copyright|''copyright'']
|
︙ | | |
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
|
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
|
-
+
-
+
-
+
|
; [!read-only|''read-only'']
: Marks a zettel as read-only.
The interpretation of [[supported values|00001006020400]] for this key depends, whether authentication is [[enabled|00001010040100]] or not.
; [!role|''role'']
: Defines the role of the zettel.
Can be used for selecting zettel.
See [[supported zettel roles|00001006020100]].
If not given, the value ''default-role'' from the [[configuration zettel|00001004020000#default-role]] will be used.
If not given, it is ignored.
; [!syntax|''syntax'']
: Specifies the syntax that should be used for interpreting the zettel.
The zettel about [[other markup languages|00001008000000]] defines supported values.
If not given, the value ''default-syntax'' from the [[configuration zettel|00001004020000#default-syntax]] will be used.
If it is not given, it defaults to ''plain''.
; [!tags|''tags'']
: Contains a space separated list of tags to describe the zettel further.
Each Tag must begin with the number sign character (""''#''"", U+0023).
; [!title|''title'']
: Specifies the title of the zettel.
If not given, the value ''default-title'' from the [[configuration zettel|00001004020000#default-title]] will be used.
If not given, the value of [[''id''|#id]] will be used.
You can use all [[inline-structured elements|00001007040000]] of Zettelmarkup.
; [!url|''url'']
: Defines an URL / URI for this zettel that possibly references external material.
One use case is to specify the document that the current zettel comments on.
The URL will be rendered special in the [[web user interface|00001014000000]] if you use the default template.
; [!useless-files|''useless-files'']
|
︙ | | |
Changes to docs/manual/00001006020100.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
-
+
-
+
-
|
id: 00001006020100
title: Supported Zettel Roles
role: manual
tags: #manual #meta #reference #zettel #zettelstore
syntax: zmk
modified: 20220214174553
modified: 20220623183234
The [[''role'' key|00001006020000#role]] defines what kind of zettel you are writing.
You are free to define your own roles.
It is allowed to set an empty value or to omit the role.
The role ''zettel'' is predefined as the default role, but you can [[change this|00001004020000#default-role]].
Some roles are defined for technical reasons:
; [!configuration|''configuration'']
: A zettel that contains some configuration data for the Zettelstore.
Most prominent is [[00000000000100]], as described in [[00001004020000]].
; [!manual|''manual'']
|
︙ | | |
Changes to docs/manual/00001006036000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
-
+
-
+
|
id: 00001006036000
title: WordSet Key Type
role: manual
tags: #manual #meta #reference #zettel #zettelstore
syntax: zmk
modified: 20220111103714
modified: 20220724201056
Values of this type denote a (sorted) set of [[words|00001006035500]].
A set is different to a list, as no duplicate values are allowed.
=== Allowed values
Must be a sequence of at least one word, separated by space characters.
=== Match operator
A value matches an wordset value, if the first value is equal to one of the word values in the word set.
A value matches a WordSet value, if the first value is equal to one of the word values in the word set.
=== Sorting
Sorting is done by comparing the [[String|00001006033500]] values.
|
Changes to docs/manual/00001006055000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001006055000
title: Reserved zettel identifier
role: manual
tags: #design #manual #zettelstore
syntax: zmk
modified: 20211124182600
modified: 20220311111751
[[Zettel identifier|00001006050000]] are typically created by examine the current date and time.
By renaming a zettel, you are able to provide any sequence of 14 digits.
If no other zettel has the same identifier, you are allowed to rename a zettel.
To make things easier, you normally should not use zettel identifier that begin with four zeroes (''0000'').
|
︙ | | |
37
38
39
40
41
42
43
|
37
38
39
40
41
42
43
44
|
+
|
| 00009000000000 | 0000999999999 | Reserved for applications
This list may change in the future.
==== External Applications
|= From | To | Description
| 00009000001000 | 00009000001999 | [[Zettel Presenter|https://zettelstore.de/contrib]], an application to display zettel as a HTML-based slideshow
| 00009000002000 | 00009000002999 | [[Zettel Blog|https://zettelstore.de/contrib]], an application to collect and transform zettel into a blog
|
Changes to docs/manual/00001007000000.zettel.
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
|
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
|
-
-
+
+
-
+
-
+
-
+
|
id: 00001007000000
title: Zettelmarkup
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220113185501
Zettelmarkup is a rich plain-text based markup language for writing zettel content.
Besides the zettel content, Zettelmarkup is also used for specifying the title of a zettel, regardless of the syntax of a zettel.
Zettelmark supports the longevity of stored notes by providing a syntax that any person can easily read, as well as a computer.
Zettelmark can be much easier parsed / consumed by a software compared to other markup languages.
Zettelmarkup supports the longevity of stored notes by providing a syntax that any person can easily read, as well as a computer.
Zettelmarkup can be much easier parsed / consumed by a software compared to other markup languages.
Writing a parser for [[Markdown|https://daringfireball.net/projects/markdown/syntax]] is quite challenging.
[[CommonMark|00001008010500]] is an attempt to make it simpler by providing a comprehensive specification, combined with an extra chapter to give hints for the implementation.
Zettelmark follows some simple principles that anybody who knows to ho write software should be able understand to create an implementation.
Zettelmarkup follows some simple principles that anybody who knows to ho write software should be able understand to create an implementation.
Zettelmarkup is a markup language on its own.
This is in contrast to Markdown, which is basically a superset of HTML.
This is in contrast to Markdown, which is basically a super-set of HTML.
While HTML is a markup language that will probably last for a long time, it cannot be easily translated to other formats, such as PDF, JSON, or LaTeX.
Additionally, it is allowed to embed other languages into HTML, such as CSS or even JavaScript.
This could create problems with longevity as well as security problems.
Zettelmarkup is a rich markup language, but it focusses on relatively short zettel content.
Zettelmarkup is a rich markup language, but it focuses on relatively short zettel content.
It allows embedding other content, simple tables, quotations, description lists, and images.
It provides a broad range of inline formatting, including __emphasized__, **strong**, ~~deleted~~{-} and >>inserted>> text.
Footnotes[^like this] are supported, links to other zettel and to external material, as well as citation keys.
Zettelmarkup might be seen as a proprietary markup language.
But if you want to use [[Markdown/CommonMark|00001008010000]] and you need support for footnotes or tables, you'll end up with proprietary extensions.
However, the Zettelstore supports CommonMark as a zettel syntax, so you can mix both Zettelmarkup zettel and CommonMark zettel in one store to get the best of both worlds.
|
︙ | | |
Changes to docs/manual/00001007010000.zettel.
︙ | | |
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
-
+
|
Some inline elements do not follow the rule of two identical character, especially to specify [[footnotes|00001007040330]], [[citation keys|00001007040340]], and local marks.
These elements begin with one opening square bracket (""``[``""), use a character for specifying the kind of the inline, typically allow to specify some content, and end with one closing square bracket (""``]``"").
One inline element that does not begin with two characters is the ""entity"".
It allows to specify any Unicode character.
The specification of that character is put between an ampersand character and a semicolon: ``&...;``{=zmk}.
For exmple, an ""n-dash"" could also be specified as ``–``{==zmk}.
For example, an ""n-dash"" could also be specified as ``–``{==zmk}.
The backslash character (""``\\``"") possibly gives the next character a special meaning.
This allows to resolve some left ambiguities.
For example, a list of depth 2 will begin a line with ``** Item 2.2``{=zmk}.
An inline element to strongly emphasize some text begin with a space will be specified as ``** Text**``{=zmk}.
To force the inline element formatting at the beginning of a line, ``**\\ Text**``{=zmk} should better be specified.
|
︙ | | |
Changes to docs/manual/00001007030000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001007030000
title: Zettelmarkup: Block-Structured Elements
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220201133655
modified: 20220311181036
Every markup for blocks-structured elements (""blocks"") begins at the very first position of a line.
There are five kinds of blocks: lists, one-line blocks, line-range blocks, tables, and paragraphs.
=== Lists
|
︙ | | |
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
+
+
|
Additionally, all other blocks elements are allowed in line-range blocks.
* [[Verbatim blocks|00001007030500]] do not interpret their content,
* [[Quotation blocks|00001007030600]] specify a block-length quotations,
* [[Verse blocks|00001007030700]] allow to enter poetry, lyrics and similar text, where line endings are important,
* [[Region blocks|00001007030800]] just mark regions, e.g. for common formatting,
* [[Comment blocks|00001007030900]] allow to enter text that will be ignored when rendered.
* [[Evaluation blocks|00001007031300]] specify some content to be evaluated by either Zettelstore or external software.
* [[Math-mode blocks|00001007031400]] can be used to enter mathematical formulas / equations.
* [[Inline-Zettel blocks|00001007031200]] provide a mechanism to specify zettel content with a new syntax without creating a new zettel.
=== Tables
Similar to lists are tables not specified explicitly.
A sequence of table rows is considered a [[table|00001007031000]].
A table row itself is a sequence of table cells.
|
︙ | | |
Changes to docs/manual/00001007030200.zettel.
︙ | | |
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
-
+
|
*# A.3
* B
* C
:::
Please note that two lists cannot be separated by an empty line.
Instead you should put a horizonal rule (""thematic break"") between them.
Instead you should put a horizontal rule (""thematic break"") between them.
You could also use a [[mark element|00001007040350]] or a hard line break to separate the two lists:
```zmk
# One
# Two
[!sep]
# Uno
# Due
|
︙ | | |
Changes to docs/manual/00001007030600.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
-
+
|
id: 00001007030600
title: Zettelmarkup: Quotation Blocks
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218131806
A simple way to enter a quotation is to use the [[quotation list|00001007030200]].
A quotation list loosely follows the convention of quoting text within emails.
However, if you want to attribute the quotation to seomeone, a quotation block is more appropriately.
However, if you want to attribute the quotation to someone, a quotation block is more appropriately.
This kind of line-range block begins with at least three less-than characters (""''<''"", U+003C) at the first position of a line.
You can add some [[attributes|00001007050000]] on the beginning line of a quotation block, following the initiating characters.
The quotation does not support the default attribute, nor the generic attribute.
Attributes are interpreted on HTML rendering.
Any other character in this line will be ignored
|
︙ | | |
Changes to docs/manual/00001007030800.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
-
+
+
|
id: 00001007030800
title: Zettelmarkup: Region Blocks
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218131131
modified: 20220323190829
Region blocks does not directly have a visual representation.
They just group a range of lines.
You can use region blocks to enter [[attributes|00001007050000]] that apply only to this range of lines.
One example is to enter a multi-line warning that should be visible.
This kind of line-range block begins with at least three colon characters (""'':''"", U+003A) at the first position of a line[^Since a [[description text|00001007030100]] only use exactly one colon character at the first position of a line, there is no possible ambiguity between these elements.].
You can add some [[attributes|00001007050000]] on the beginning line of a region block, following the initiating characters.
The region block does not support the default attribute, but it supports the generic attribute.
Some generic attributes, like ``=note``, ``=warning`` will be rendered special.
All other generic attributes are used as a CSS class definition.
Attributes are interpreted on HTML rendering.
Any other character in this line will be ignored.
Text following the beginning line will be interpreted, until a line begins with at least the same number of the same characters given at the beginning line.
This allows to enter a region block within a region block.
At the ending line, you can enter some [[inline elements|00001007040000]] after the colon characters.
These will interpreted as some attribution text.
|
︙ | | |
64
65
66
67
68
69
70
|
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
+
+
+
+
+
+
+
+
+
+
+
+
+
|
Generic attributes that are result in a special HTML rendering are:
* example
* note
* tip
* important
* caution
* warning
All other generic attribute values are rendered as a CSS class:
```zmk
:::abc
def
:::
```
is rendered as
::::example
:::abc
def
:::
::::
|
Changes to docs/manual/00001007030900.zettel.
︙ | | |
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
+
|
While the text entered inside a verbatim block will be processed somehow, text inside a comment block will be ignored[^Well, not completely ignored: text is read, but it will typically not rendered visible.].
Comment blocks are typically used to give some internal comments, e.g. the license of a text or some internal remarks.
Comment blocks begin with at least three percent sign characters (""''%''"", U+0025) at the first position of a line.
You can add some [[attributes|00001007050000]] on the beginning line of a comment block, following the initiating characters.
The comment block supports the default attribute: when given, the text will be rendered, e.g. as an HTML comment.
When rendered to JSON, the comment block will not be ignored but it will output some JSON text.
Same for other renderers.
Same for other renderer.
Any other character in this line will be ignored
Text following the beginning line will not be interpreted, until a line begins with at least the same number of the same characters given at the beginning line.
This allows to enter some percent sign characters in the text that should not be interpreted.
For example:
|
︙ | | |
Changes to docs/manual/00001007031000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
+
|
id: 00001007031000
title: Zettelmarkup: Tables
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218131107
Tables are used to show some data in a two-dimenensional fashion.
Tables are used to show some data in a two-dimensional fashion.
In zettelmarkup, table are not specified explicitly, but by entering __table rows__.
Therefore, a table can be seen as a sequence of table rows.
A table row is nothing as a sequence of __table cells__.
The length of a table is the number of table rows, the width of a table is the maximum length of its rows.
The first cell of a row must begin with the vertical bar character (""''|''"", U+007C) at the first position of a line.
The other cells of a row begin with the same vertical bar character at later positions in that line.
|
︙ | | |
Changes to docs/manual/00001007031200.zettel.
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
|
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
|
-
+
-
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
id: 00001007031200
title: Zettelmarkup: Inline-Zettel Block
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218172121
modified: 20220311112247
An inline-zettel block allows to specify some content with another syntax without creating a new zettel.
This is useful, for example, if you want to specify a [[simple drawing|00001008050000]] within your zettel and you are sure that you do not need the drawing in another context.
Another example is to embed some [[Markdown|00001008010500]] content, because you are too lazy to translate Markdown into Zettelmarkup.[^However, translating into Zettelmarkup is quite easy with the [[zmk encoder|00001012920522]].]
A last example is to specify HTML code to use it for some kind of web frontend framework.
This is useful, for example, if you want to embed some [[Markdown|00001008010500]] content, because you are too lazy to translate Markdown into Zettelmarkup.
Another example is to specify HTML code to use it for some kind of web front-end framework.
As all other [[line-range blocks|00001007030000#line-range-blocks]], an inline-zettel block begins with at least three identical characters, starting at the first position of a line.
For inline-zettel blocks, the at-sign character (""''@''"", U+0040) is used.
You can add some [[attributes|00001007050000]] on the beginning line of a verbatim block, following the initiating characters.
The inline-zettel block uses the attribute key ""syntax"" to specify the [[syntax|00001008000000]] of the inline-zettel.
Alternatively, you can use the generic attribute to specify the syntax value.
If no value is provided, ""draw"" is assumed.
If no value is provided, ""[[text|00001008000000#text]]"" is assumed.
Any other character in this first line will be ignored.
Text following the beginning line will not be interpreted, until a line begins with at least the same number of the same at-sign characters given at the beginning line.
This allows to enter some at-sign characters in the text that should not be interpreted at this level.
Some examples:
```zmk
@@@draw
+-------+ +-------+
| Box 1 | ---> | Box 2 |
+-------+ +-------+
@@@
```
This will be rendered as:
:::example
@@@draw
+-------+ +-------+
| Box 1 | ---> | Box 2 |
+-------+ +-------+
@@@
:::
Using Markdown syntax:
```zmk
@@@markdown
A link to [this](00001007031200) zettel.
@@@
```
will be rendered as:
:::example
@@@markdown
|
︙ | | |
Added docs/manual/00001007031300.zettel.
|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
id: 00001007031300
title: Zettelmarkup: Evaluation Blocks
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220311120658
Evaluation blocks are used to enter text that could be evaluated by either Zettelstore or external software.
They begin with at least three tilde characters (""''~''"", U+007E) at the first position of a line.
You can add some [[attributes|00001007050000]] on the beginning line of a verbatim block, following the initiating characters.
The evaluation block supports the default attribute[^Depending on the syntax value.]: when given, all spaces in the text are rendered in HTML as open box characters (U+2423).
If you want to give only one attribute and this attribute is the generic attribute, you can omit the most of the attribute syntax and just specify the value.
It will be interpreted as a [[syntax|00001008000000]] value to evaluate its content.
Not all syntax values are supported by Zettelstore.[^Currently just ""[[draw|00001008050000]]"".]
The main reason for an evaluation block is to be used with external software via the [[ZJSON encoding|00001012920503]].
Any other character in this line will be ignored
Text following the beginning line will not be interpreted, until a line begins with at least the same number of the same characters given at the beginning line.
This allows to enter some tilde characters in the text that should not be interpreted.
For example:
`````zmk
~~~~
~~~
~~~~
`````
will be rendered in HTML as:
:::example
~~~~
~~~
~~~~
:::
`````zmk
~~~{-}
This is some
text with no
real sense.
~~~~
`````
will be rendered as:
:::example
~~~{-}
This is some
text with no
real sense.
~~~~
:::
`````zmk
~~~draw
+---+ +---+
| A | --> | B |
+---+ +---+
~~~
`````
will be rendered as:
:::example
~~~draw
+---+ +---+
| A | --> | B |
+---+ +---+
~~~
:::
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Added docs/manual/00001007031400.zettel.
|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
id: 00001007031400
title: Zettelmarkup: Math-mode Blocks
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220311182505
Math-mode blocks are used to enter mathematical formulas / equations in a display style mode.
Similar to a [[evaluation blocks|00001007031300]], the block content will be interpreted by either Zettelstore or an external software.
They begin with at least three dollar sign characters (""''$''"", U+0024) at the first position of a line.
You can add some [[attributes|00001007050000]] on the beginning line of a verbatim block, following the initiating characters.
A math-mode block supports the default attribute[^Depending on the syntax value.]: when given, all spaces in the text are rendered in HTML as open box characters (U+2423).
If you want to give only one attribute and this attribute is the generic attribute, you can omit the most of the attribute syntax and just specify the value.
It will be interpreted as a [[syntax|00001008000000]] value to evaluate its content.
Alternatively, you could provide an attribute with the key ""syntax"" and use the value to specify the syntax.
Not all syntax values are supported by Zettelstore.[^Currently: none.]
External software might support several values via the [[ZJSON encoding|00001012920503]].
Any other character in this line will be ignored
Text following the beginning line will not be interpreted, until a line begins with at least the same number of the same characters given at the beginning line.
This allows to enter some dollar-sign characters in the text that should not be interpreted.
For example:
`````zmk
$$$$
$$$
$$$$
`````
will be rendered in HTML as:
:::example
$$$$
$$$
$$$$
:::
`````zmk
$$${-}
This is some
text with no
real sense.
$$$$
`````
will be rendered as:
:::example
$$${-}
This is some
text with no
real sense.
$$$$
:::
In the future, Zettelstore might somehow support mathematical formulae with a $$\TeX$$-like syntax.
Until then,
`````zmk
$$$
\begin{align*}
f(x) &= x^2\\
g(x) &= \frac{1}{x}\\
F(x) &= \int^a_b \frac{1}{3}x^3
\end{align*}
$$$
`````
is rendered as:
:::example
$$$
\begin{align*}
f(x) &= x^2\\
g(x) &= \frac{1}{x}\\
F(x) &= \int^a_b \frac{1}{3}x^3
\end{align*}
$$$
:::
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Changes to docs/manual/00001007040100.zettel.
︙ | | |
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
-
+
-
+
|
** Example: ``abc __def__ ghi`` is rendered in HTML as: ::abc __def__ ghi::{=example}.
* The asterisk character (""''*''"", U+002A) strongly emphasized its enclosed text.
** Example: ``abc **def** ghi`` is rendered in HTML as: ::abc **def** ghi::{=example}.
* The greater-than sign character (""''>''"", U+003E) marks text as inserted.
** Example: ``abc >>def>> ghi`` is rendered in HTML as: ::abc >>def>> ghi::{=example}.
* Similar, the tilde character (""''~''"", U+007E) marks deleted text.
** Example: ``abc ~~def~~ ghi`` is rendered in HTML as: ::abc ~~def~~ ghi::{=example}.
* The circumflex accent character (""''^''"", U+005E) allows to enter superscripted text.
* The circumflex accent character (""''^''"", U+005E) allows to enter super-scripted text.
** Example: ``e=mc^^2^^`` is rendered in HTML as: ::e=mc^^2^^::{=example}.
* The comma character (""'',''"", U+002C) produces subscripted text.
* The comma character (""'',''"", U+002C) produces sub-scripted text.
** Example: ``H,,2,,O`` is rendered in HTML as: ::H,,2,,O::{=example}.
* The quotation mark character (""''"''"", U+0022) marks an inline quotation, according to the [[specified language|00001007050100]].
** Example: ``""To be or not""`` is rendered in HTML as: ::""To be or not""::{=example}.
** Example: ``""Sein oder nicht""{lang=de}`` is rendered in HTML as: ::""Sein oder nicht""{lang=de}::{=example}.
* The colon character (""'':''"", U+003A) mark some text that should belong together. It fills a similar role as [[region blocks|00001007030800]], but just for inline elements.
** Example: ``abc ::def::{=example} ghi`` is rendered in HTML as: abc ::def::{=example} ghi.
|
Changes to docs/manual/00001007040200.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001007040200
title: Zettelmarkup: Literal-like formatting
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218131420
modified: 20220311185110
There are some reasons to mark text that should be rendered as uninterpreted:
* Mark text as literal, sometimes as part of a program.
* Mark text as input you give into a computer via a keyboard.
* Mark text as output from some computer, e.g. shown at the command line.
=== Literal text
|
︙ | | |
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
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
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
Attributes can be specified, the default attribute has the same semantic as for literal text.
=== Inline-zettel snippet
To specify an inline snippet in a different [[syntax|00001008000000]], delimit your text with two at-sign characters (""''@''"", U+0040) on each side.
You can add some [[attributes|00001007050000]] immediate after the two closing at-sign characters to specify the syntax to use.
Either use the attribute key ""syntax"" or use the generic attribute to specify the syntax value.
If no value is provided, ""draw"" is assumed.
If no value is provided, ""[[text|00001008000000#text]]"" is assumed.
Examples:
* ``A @@-->@@ B`` renders in HTML as ::A @@-->@@ B::{=example}.
* ``@@<small>@@{=html}Small@@</small>@@{=html}`` renders in HTML as ::@@<small>@@{=html}Small@@</small>@@{=html}::{=example}.
To some degree, an inline-zettel snippet is the @@<small>@@{=html}smaller@@</small>@@{=html} sibling of the [[inline-zettel block|00001007031200]].
For HTML syntax, the same rules apply.
=== Math mode / $$\TeX$$ input
This allows to enter text, that is typically interpreted by $$\TeX$$ or similar software.
The main difference to all other literal-like formatting above is that the backslash character (""''\\''"", U+005C) has no special meaning.
Therefore it is well suited the enter text with a lot of backslash characters.
Math mode text is delimited with two dollar signs (""''$''"", U+0024) on each side.
You can add some [[attributes|00001007050000]] immediate after the two closing at-sign characters to specify the syntax to use.
Either use the attribute key ""syntax"" or use the generic attribute to specify the syntax value.
If no syntax value is provided, math mode text roughly corresponds to literal text.
Currently, Zettelstore does not support any syntax.
This will probably change.
However, external software might support specific syntax value, like ""tex"", ""latex"", ""mathjax"", ""itex"", or ""webtex"".
Even an empty syntax value might be supported.
Example:
* ``Happy $$\\TeX$$!``is rendered as ::Happy $$\TeX$$!::{=example}
|
Changes to docs/manual/00001007040324.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-
+
-
|
id: 00001007040324
title: Zettelmarkup: Inline-mode Transclusion
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220131155955
modified: 20220311110814
Inline-mode transclusion applies to all zettel that are parsed in a non-trivial way, e.g. as structured textual content.
For example, textual content is assumed if the [[syntax|00001006020000#syntax]] of a zettel is ""zmk"" ([[Zettelmarkup|00001007000000]]), or ""markdown"" / ""md"" ([[Markdown|00001008010000]]).
If the syntax is ""[[draw|00001008050000]]"", it is also a non-trivial way.
Since this type of transclusion is at the level of [[inline-structured elements|00001007040000]], the transclude specification must be replaced with some inline-structured elements.
First, the referenced zettel is read.
If it contains other transclusions, these will be expanded, recursively.
When an endless recursion is detected, expansion does not take place.
Instead an error message replaces the transclude specification.
|
︙ | | |
Changes to docs/manual/00001007040340.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
+
|
id: 00001007040340
title: Zettelmarkup: Citation Key
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218133447
A citation key references some external material that is part of a bibliografical collection.
A citation key references some external material that is part of a bibliographical collection.
Currently, Zettelstore implements this only partially, it is ""work in progress"".
However, the syntax is: beginning with a left square bracket and followed by an at sign character (""''@''"", U+0040), a the citation key is given.
The key is typically a sequence of letters and digits.
If a comma character (""'',''"", U+002C) or a vertical bar character is given, the following is interpreted as [[inline elements|00001007040000]].
A right square bracket ends the text and the citation key element.
|
Changes to docs/manual/00001007050000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001007050000
title: Zettelmarkup: Attributes
role: manual
tags: #manual #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218132935
modified: 20220630194106
Attributes allows to modify the way how material is presented.
Alternatively, they provide additional information to markup elements.
To some degree, attributes are similar to [[HTML attributes|https://html.spec.whatwg.org/multipage/dom.html#global-attributes]].
Typical use cases for attributes are to specify the (natural) [[language|00001007050100]] for a text region, to specify the [[programming language|00001007050200]] for highlighting program code, or to make white space visible in plain text.
|
︙ | | |
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
|
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
|
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
The key ""''-''"" (just hyphen-minus) is special.
It is called __default attribute__ and has a markup specific meaning.
For example, when used for plain text, it replaces the non-visible space with a visible representation:
* ''``Hello, world``{-}'' produces ==Hello, world=={-}.
* ''``Hello, world``'' produces ==Hello, world==.
For some [[block-structured elements|00001007030000]], there is a syntax variant if you only want to specify a generic attribute.
For all line-range blocks you can specify the generic attributes directly in the first line, after the three (or more) block characters.
Attributes may be continued on the next line when a space or line ending character is possible.
```
:::attr
...
:::
```
is equivalent to
```
:::{=attr}
...
:::
```.
In case of a quoted attribute value, the line ending character will be part of the attribute value.
For other blocks, the closing curly bracket must be on the same line where the block element begins.
However, spaces are allowed between the blocks characters and the attributes.
```
=== Heading {example}
For example:
```
is allowed and equivalent to
{key="quoted
```
=== Heading{example}
```.
But
value"}
```
=== Heading {class=example
background=grey}
```
is not allowed. Same for
```
=== Heading {background=color:"
green"}
```.
will produce a value ''quoted\\nvalue'' (where \\n denotes a line ending character).
For [[inline-structued elements|00001007040000]], the attributes must immediately follow the inline markup.
However, the attributes may be continued on the next line when a space or line ending character is possible.
``::GREEN::{example}`` is allowed, but not ``::GREEN:: {example}``.
```
::GREEN::{class=example
background=grey}
```
is allowed, but not
```
::GREEN::{background=color:
green}
```.
However,
```
::GREEN::{background=color:"
green"}
```
is allowed, because line endings are allowed within quotes.
For [[block-structured elements|00001007030000]], there is a syntax variant if you only want to specify a generic attribute.
For all line-range blocks you can specify the generic attributes directly in the first line, after the three (or more) characters starting the block.
```
:::attr
...
:::
```
is equivalent to
```
:::{=attr}
...
:::
```.
For block-structured elements, spaces are allowed between the blocks characters and the attributes.
```
=== Heading {example}
```
is allowed and equivalent to
```
=== Heading{example}
```.
For [[inline-structured elements|00001007040000]], the attributes must immediately follow the inline markup.
``::GREEN::{example}`` is allowed, but not ``::GREEN:: {example}``.
=== Reference material
* [[Supported attribute values for natural languages|00001007050100]]
* [[Supported attribute values for programming languages|00001007050200]]
|
Changes to docs/manual/00001007060000.zettel.
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
|
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
|
-
+
-
-
+
+
-
+
-
+
-
+
|
id: 00001007060000
title: Zettelmarkup: Summary of Formatting Characters
role: manual
tags: #manual #reference #zettelmarkup #zettelstore
syntax: zmk
modified: 20220218124943
modified: 20220311120759
The following table gives an overview about the use of all characters that begin a markup element.
|= Character :|= [[Blocks|00001007030000]] <|= [[Inlines|00001007040000]] <
| ''!'' | (free) | (free)
| ''"'' | [[Verse block|00001007030700]] | [[Short inline quote|00001007040100]]
| ''#'' | [[Ordered list|00001007030200]] | [[Tag|00001007040000]]
| ''$'' | (reserved) | (reserved)
| ''%'' | [[Comment block|00001007030900]] | [[Comment|00001007040000]]
| ''&'' | (free) | [[Entity|00001007040000]]
| ''\''' | (free) | [[Computer input|00001007040200]]
| ''('' | (free) | (free)
| '')'' | (free) | (free)
| ''*'' | [[Unordered list|00001007030200]] | [[strongly emphasized text|00001007040100]]
| ''+'' | (free) | (free)
| '','' | (free) | [[Subscripted text|00001007040100]]
| ''-'' | [[Horizonal rule|00001007030400]] | ""[[en-dash|00001007040000]]""
| '','' | (free) | [[Sub-scripted text|00001007040100]]
| ''-'' | [[Horizontal rule|00001007030400]] | ""[[en-dash|00001007040000]]""
| ''.'' | (free) | [[Horizontal ellipsis|00001007040000]]
| ''/'' | (free) | (free)
| '':'' | [[Region block|00001007030800]] / [[description text|00001007030100]] | [[Inline region|00001007040100]]
| '';'' | [[Description term|00001007030100]] | [[Small text|00001007040100]]
| ''<'' | [[Quotation block|00001007030600]] | (free)
| ''='' | [[Headings|00001007030300]] | [[Computer output|00001007040200]]
| ''>'' | [[Quotation lists|00001007030200]] | [[Inserted text|00001007040100]]
| ''?'' | (free) | (free)
| ''@'' | [[Inline-Zettel blocks|00001007031200]] | [[Inline-zettel snippets|00001007040200#inline-zettel-snippet]]
| ''@'' | [[Inline-Zettel block|00001007031200]] | [[Inline-zettel snippet|00001007040200#inline-zettel-snippet]]
| ''['' | (reserved) | [[Linked material|00001007040300]], [[citation key|00001007040300]], [[footnote|00001007040300]], [[mark|00001007040300]]
| ''\\'' | (blocked by inline meaning) | [[Escape character|00001007040000]]
| '']'' | (reserved) | End of [[link|00001007040300]], [[citation key|00001007040300]], [[footnote|00001007040300]], [[mark|00001007040300]]
| ''^'' | (free) | [[Superscripted text|00001007040100]]
| ''^'' | (free) | [[Super-scripted text|00001007040100]]
| ''_'' | (free) | [[Emphasized text|00001007040100]]
| ''`'' | [[Verbatim block|00001007030500]] | [[Literal text|00001007040200]]
| ''{'' | [[Transclusion|00001007031100]] | [[Embedded material|00001007040300]], [[Attribute|00001007050000]]
| ''|'' | [[Table row / table cell|00001007031000]] | Separator within link and [[embed|00001007040320]] formatting
| ''}'' | End of [[Transclusion|00001007031100]] | End of embedded material, End of Attribute
| ''~'' | (free) | [[Deleted text|00001007040100]]
| ''~'' | [[Evaluation block|00001007031300]] | [[Deleted text|00001007040100]]
|
Changes to docs/manual/00001008000000.zettel.
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
|
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
|
-
+
-
+
-
-
-
+
-
+
+
|
id: 00001008000000
title: Other Markup Languages
role: manual
tags: #manual #zettelstore
syntax: zmk
modified: 20220214180202
modified: 20220627192329
[[Zettelmarkup|00001007000000]] is not the only markup language you can use to define your content.
Zettelstore is quite agnostic with respect to markup languages.
Of course, Zettelmarkup plays an important role.
However, with the exception of zettel titles, you can use any (markup) language that is supported:
* CSS
* HTML template data
* Image formats: GIF, PNG, JPEG, SVG
* Markdown
* Plain text, not further interpreted
The [[metadata key|00001006020000#syntax]] ""''syntax''"" specifies which language should be used.
If it is not given, the key ""''default-syntax''"" will be used (specified in the [[configuration zettel|00001004020000#default-syntax]]).
If it is not given, it defaults to ''plain''.
The following syntax values are supported:
; [!css|''css'']
: A [[Cascading Style Sheet|https://www.w3.org/Style/CSS/]], to be used when rendering a zettel as HTML.
; [!draw|''draw'']
: A simple [[language|00001008050000]] to ""draw"" a graphic by using some simple Unicode characters.
; [!gif|''gif'']; [!jpeg|''jpeg'']; [!jpg|''jpg'']; [!png|''png'']
: The formats for pixel graphics.
Typically the data is stored in a separate file and the syntax is given in the metafile, which has the same name as the zettel identifier and has no file extension.[^Before version 0.2.0, the metafile had the file extension ''.meta'']
Typically the data is stored in a separate file and the syntax is given in the meta-file, which has the same name as the zettel identifier and has no file extension.[^Before version 0.2, the meta-file had the file extension ''.meta'']
; [!html|''html'']
: Hypertext Markup Language, will not be parsed further.
Instead, it is treated as [[text|#text]], but will be encoded differently for [[HTML format|00001012920510]] (same for the [[web user interface|00001014000000]]).
For security reasons, equivocal elements will not be encoded in the HTML format / web user interface, e.g. the ``<script ...`` tag.
For security reasons, equivocal elements will not be encoded in the HTML format / web user interface.
The ``< script ...>`` tag is an example.
See [[security aspects of Markdown|00001008010000#security-aspects]] for some details.
; [!markdown|''markdown''], [!md|''md'']
: For those who desperately need [[Markdown|https://daringfireball.net/projects/markdown/]].
Since the world of Markdown is so diverse, a [[CommonMark|00001008010500]] parser is used.
See [[Use Markdown within Zettelstore|00001008010000]].
; [!mustache|''mustache'']
: A [[Mustache template|https://mustache.github.io/]], used when rendering a zettel as HTML for the [[web user interface|00001014000000]].
|
︙ | | |
50
51
52
53
54
55
56
|
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
+
+
+
+
+
+
+
|
: Just plain text that must not be interpreted further.
; [!zmk|''zmk'']
: [[Zettelmarkup|00001007000000]].
The actual values are also listed in a zettel named [[Zettelstore Supported Parser|00000000000092]].
If you specify something else, your content will be interpreted as plain text.
=== Language for other elements of a zettel
[[Zettelmarkup|00001007000000]] allows to specify [[evaluation blocks|00001007031300]], which also receive a syntax value.
An evaluation blocks is typically interpreted by external software, for example [[Zettel Presenter|00001006055000#external-applications]].
However, some values are interpreted by Zettelstore during evaluation of a zettel:
; [!draw|''draw'']
: A [[language|00001008050000]] to ""draw"" a graphic by using some simple Unicode characters.
|
Changes to docs/manual/00001008010000.zettel.
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
|
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
|
-
+
-
+
-
+
|
id: 00001008010000
title: Use Markdown within Zettelstore
role: manual
tags: #manual #markdown #zettelstore
syntax: zmk
modified: 20220113185400
modified: 20220627192014
If you are customized to use Markdown as your markup language, you can configure Zettelstore to support your decision.
Zettelstore supports the [[CommonMark|00001008010500]] dialect of Markdown.
=== Use Markdown as the default markup language of Zettelstore
Add the key ''default-syntax'' with a value of ''md'' or ''markdown'' to the [[configuration zettel|00000000000100]].
Update the [[New Zettel|00000000090001]] template (and other relevant template zettel) by setting the syntax value to ''md'' or ''markdown''.
Whether to use ''md'' or ''markdown'' is not just a matter to taste.
It also depends on the value of [[''zettel-file-syntax''|00001004020000#zettel-file-syntax]] and, to some degree, on the value of [[''yaml-header''|00001004020000#yaml-header]].
If you set ''yaml-header'' to true, then new content is always stored in a file with the extension ''.zettel''.
Otherwise ''zettel-file-syntax'' lists all syntax values, where its content should be stored in a file with the extension ''.zettel''.
If neither ''yaml-header'' nor ''zettel-file-syntax'' is set, new content is stored in a file where its file name extension is the same as the syntax value of that zettel.
In this case it makes a difference, whether you specify ''md'' or ''markdown''.
If you specify the syntax ''md'', your content will be stored in a file with the ''.md'' extension.
Similar for the syntax ''markdown''.
If you want to process the files that store the zettel content, e.g. with some other Markdown tools, this may be important.
Not every Markdown tool allows both file extensions.
BTW, metadata is stored in a file without a file extension, if neither ''yaml-header'' nor ''zettel-file-syntax'' is set.
=== Security aspects
You should be aware that Markdown is a superset of HTML.
You should be aware that Markdown is a super-set of HTML.
Any HTML code is valid Markdown code.
If you write your own zettel, this is probably not a problem.
However, if you receive zettel from others, you should be careful.
An attacker might include malicious HTML code in your zettel.
For example, HTML allows to embed JavaScript, a full-sized programming language that drives many web sites.
When a zettel is displayed, JavaScript code might be executed, sometimes with harmful results.
|
︙ | | |
Changes to docs/manual/00001008010500.zettel.
︙ | | |
15
16
17
18
19
20
21
22
23
24
25
26
|
15
16
17
18
19
20
21
22
23
24
25
26
|
-
-
+
+
|
But they provide proprietary extensions, which makes it harder to change to another CommonMark implementation if needed.
Plus, they sometimes build on an older specification of CommonMark.
Zettelstore supports the latest CommonMark [[specification version 0.30 (2021-06-19)|https://spec.commonmark.org/0.30/]].
If possible, Zettelstore will adapt to newer versions when they are available.
To provide CommonMark support, Zettelstore uses currently the [[Goldmark|https://github.com/yuin/goldmark]] implementation, which passes all validation tests of CommonMark.
Internally, CommonMark is translated into some kind of superset of [[Zettelmarkup|00001007000000]], which additionally allows to use HTML code.[^Effectively, Markdown and CommonMark are itself supersets of HTML.]
This Zettelmarkup superset is later [[encoded|00001012920500]], often into [[HTML|00001012920510]].
Internally, CommonMark is translated into some kind of super-set of [[Zettelmarkup|00001007000000]], which additionally allows to use HTML code.[^Effectively, Markdown and CommonMark are itself super-sets of HTML.]
This Zettelmarkup super-set is later [[encoded|00001012920500]], often into [[HTML|00001012920510]].
Because Zettelstore HTML encoding philosophy differs a little bit to that of CommonMark, Zettelstore itself will not pass the CommonMark test suite fully.
However, no CommonMark language element will fail to be encoded as HTML.
In most cases, the differences are not visible for an user, but only by comparing the generated HTML code.
|
Changes to docs/manual/00001008050000.zettel.
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
|
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
|
-
+
-
+
+
-
+
-
+
+
-
-
+
+
-
+
-
+
|
id: 00001008050000
title: The ""draw"" language
role: manual
tags: #graphic #manual #zettelstore
syntax: zmk
modified: 20220217180713
modified: 20220311120439
Sometimes, ""a picture is worth a thousand words"".
To create some graphical representations, Zettelstore provides a simple mechanism.
To create some graphical representations, Zettelmarkup provides a simple mechanism.
Characters like ""''|''"" or ""''-''"" already provide some visual feedback.
For example, to create a picture containing two boxes that are connected via an arrow, the following representation is possible:
```
~~~draw
+-------+ +-------+
+-------+ .-------.
| Box 1 | ----> | Box 2 |
+-------+ +-------+
+-------+ '-------'
~~~
```
Zettelstore translates this to:
@@@draw
+-------+ +-------+
~~~draw
+-------+ .-------.
| Box 1 | ----> | Box 2 |
+-------+ +-------+
+-------+ '-------'
@@@
~~~
Technically spoken, the drawing is translated to a [[SVG|00001008000000#svg]] element.
The following characters are interpreted to create a graphical representation.
Some of them will start a path that results in a recognized object.
|=Character:|Meaning|Path Start:
|
︙ | | |
Changes to docs/manual/00001010000000.zettel.
︙ | | |
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
-
+
|
Or you want to allow them to create new zettel, or to change them.
It is up to you.
If someone is authenticated as the owner of the Zettelstore (hopefully you), no restrictions apply.
But as an owner, you can create ""user zettel"" to allow others to access your Zettelstore in various ways.
Even if you do not want to share your Zettelstore with other persons, creating user zettel can be useful if you plan to access your Zettelstore via the [[API|00001012000000]].
Additionally, you can specify that a zettel is publicily visible.
Additionally, you can specify that a zettel is publicly visible.
In this case no one has to authenticate itself to see the content of the zettel.
Or you can specify that a zettel is visible only to the owner.
In this case, no authenticated user will be able to read and change that protected zettel.
* [[Visibility rules for zettel|00001010070200]]
* [[User roles|00001010070300]] define basic rights of an user
* [[Authorization and read-only mode|00001010070400]]
|
︙ | | |
Changes to docs/manual/00001010040100.zettel.
1
2
3
4
5
6
7
8
9
|
1
2
3
4
5
6
7
8
9
10
11
12
|
+
+
+
|
id: 00001010040100
title: Enable authentication
role: manual
tags: #authentication #configuration #manual #security #zettelstore
syntax: zmk
modified: 20220419192817
To enable authentication, you must create a zettel that stores [[authentication data|00001010040200]] for the owner.
Then you must reference this zettel within the [[startup configuration|00001004010000#owner]] under the key ''owner''.
Once the startup configuration contains a valid [[zettel identifier|00001006050000]] under that key, authentication is enabled.
Please note that you must also set key ''secret'' of the [[startup configuration|00001004010000#secret]] to some random string data (minimum length is 16 bytes) to secure the data exchanged with a client system.
|
Changes to docs/manual/00001012000000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001012000000
title: API
role: manual
tags: #api #manual #zettelstore
syntax: zmk
modified: 20220304173249
modified: 20220627183444
The API (short for ""**A**pplication **P**rogramming **I**nterface"") is the primary way to communicate with a running Zettelstore.
Most integration with other systems and services is done through the API.
The [[web user interface|00001014000000]] is just an alternative, secondary way of interacting with a Zettelstore.
=== Background
The API is HTTP-based and uses plain text and JSON as its main encoding format for exchanging messages between a Zettelstore and its client software.
|
︙ | | |
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
-
+
-
|
=== Zettel lists
* [[List metadata of all zettel|00001012051200]]
* [[Shape the list of zettel metadata|00001012051800]]
** [[Selection of zettel|00001012051810]]
** [[Limit the list length|00001012051830]]
** [[Content search|00001012051840]]
** [[Sort the list of zettel metadata|00001012052000]]
* [[List all tags|00001012052400]]
* [[Map metadata values to lists of zettel identifier|00001012052400]]
* [[List all roles|00001012052600]]
=== Working with zettel
* [[Create a new zettel|00001012053200]]
* [[Retrieve metadata and content of an existing zettel|00001012053300]]
* [[Retrieve metadata of an existing zettel|00001012053400]]
* [[Retrieve evaluated metadata and content of an existing zettel in various encodings|00001012053500]]
* [[Retrieve parsed metadata and content of an existing zettel in various encodings|00001012053600]]
|
︙ | | |
Changes to docs/manual/00001012052400.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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
|
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
|
id: 00001012052400
title: API: List all tags
title: API: Map metadata values to list of zettel identifier
role: manual
tags: #api #manual #zettelstore
syntax: zmk
modified: 20220627183323
The [[endpoint|00001012920000]] ''/m'' allows to retrieve a map of metadata values (of a specific key) to the list of zettel identifier, which reference zettel containing this value under the given metadata key.
To list all [[tags|00001006020000#tags]] used in the Zettelstore just send a HTTP GET request to the [[endpoint|00001012920000]] ''/t''.
Currently, two keys are supported:
* [[''role''|00001006020100]]
* [[''tags''|00001006020000#tags]]
To list all roles used in the Zettelstore, send a HTTP GET request to the endpoint ''/m?_key=role''.
If successful, the output is a JSON object:
```sh
# curl http://127.0.0.1:23123/m?_key=role
{"map":{"configuration":["00000000090002","00000000090000", ... ,"00000000000001"],"manual":["00001014000000", ... ,"00001000000000"],"zettel":["00010000000000", ... ,"00001012070500","00000000090001"]}}
```
The JSON object only contains the key ''"map"'' with the value of another object.
This second object contains all role names as keys and the list of identifier of those zettel with this specific role as a value.
Similar, to list all tags used in the Zettelstore, send a HTTP GET request to the endpoint ''/m?_key=tags''.
If successful, the output is a JSON object:
```sh
# curl http://127.0.0.1:23123/t
{"tags":{"#api":[:["00001012921000","00001012920800","00001012920522",...],"#authorization":["00001010040700","00001010040400",...],...,"#zettelstore":["00010000000000","00001014000000",...,"00001001000000"]}}
# curl http://127.0.0.1:23123/m?_key=tags
{"map":{"#api":[:["00001012921000","00001012920800","00001012920522",...],"#authorization":["00001010040700","00001010040400",...],...,"#zettelstore":["00010000000000","00001014000000",...,"00001001000000"]}}
```
The JSON object only contains the key ''"tags"'' with the value of another object.
The JSON object only contains the key ''"map"'' with the value of another object.
This second object contains all tags as keys and the list of identifier of those zettel with this tag as a value.
Please note that this structure will likely change in the future to be more compliant with other API calls.
|
Deleted docs/manual/00001012052600.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
|
id: 00001012052600
title: API: List all roles
role: manual
tags: #api #manual #zettelstore
syntax: zmk
To list all [[roles|00001006020100]] used in the Zettelstore just send a HTTP GET request to the [[endpoint|00001012920000]] ''/r''.
If successful, the output is a JSON object:
```sh
# curl http://127.0.0.1:23123/r
{"role-list":["configuration","manual","user","zettel"]}
```
The JSON object only contains the key ''"role-list"'' with the value of a sorted string list.
Each string names one role.
Please note that this structure will likely change in the future to be more compliant with other API calls.
|
Changes to docs/manual/00001012053200.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001012053200
title: API: Create a new zettel
role: manual
tags: #api #manual #zettelstore
syntax: zmk
modified: 20211124180030
modified: 20220628111320
A zettel is created by adding it to the [[list of zettel|00001012000000#zettel-lists]].
Therefore, the [[endpoint|00001012920000]] to create a new zettel is also ''/j'', but you must send the data of the new zettel via a HTTP POST request.
The body of the POST request must contain a JSON object that specifies metadata and content of the zettel to be created.
The following keys of the JSON object are used:
; ''"meta"''
|
︙ | | |
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
-
+
|
Typically, text content is not encoded, and binary content is encoded via Base64.
Other keys will be ignored.
Even these three keys are just optional.
The body of the HTTP POST request must not be empty and it must contain a JSON object.
Therefore, a body containing just ''{}'' is perfectly valid.
The new zettel will have no content, its title will be set to the value of [[''default-title''|00001004020000#default-title]] (default: ""Untitled""), its role is set to the value of [[''default-role''|00001004020000#default-role]] (default: ""zettel""), and its syntax is set to the value of [[''default-syntax''|00001004020000#default-syntax]] (default: ""zmk"").
The new zettel will have no content, and only an identifier as [[metadata|00001006020000]]:
```
# curl -X POST --data '{}' http://127.0.0.1:23123/j
{"id":"20210713161000"}
```
If creating the zettel was successful, the HTTP response will contain a JSON object with one key:
; ''"id"''
|
︙ | | |
Changes to docs/manual/00001012053300.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
-
+
-
+
|
id: 00001012053300
title: API: Retrieve metadata and content of an existing zettel
role: manual
tags: #api #manual #zettelstore
syntax: zmk
modified: 20220201180121
modified: 20220724163741
The [[endpoint|00001012920000]] to work with metadata and content of a specific zettel is ''/j/{ID}'', where ''{ID}'' is a placeholder for the [[zettel identifier|00001006050000]].
For example, to retrieve some data about this zettel you are currently viewing, just send a HTTP GET request to the endpoint ''/j/00001012053300''[^If [[authentication is enabled|00001010040100]], you must include the a valid [[access token|00001012050200]] in the ''Authorization'' header].
If successful, the output is a JSON object:
```sh
# curl http://127.0.0.1:23123/j/00001012053300
{"id":"00001012053300","meta":{"title":"API: Retrieve data for an exisiting zettel","tags":"#api #manual #zettelstore","syntax":"zmk","role":"manual","copyright":"(c) 2020 by Detlef Stern <ds@zettelstore.de>","lang":"en","license":"CC BY-SA 4.0"},"content":"The endpoint to work with a specific zettel is ''/j/{ID}'', where ''{ID}'' is a placeholder for the [[zettel identifier|00001006050000}}.\n\nFor example, ...
{"id":"00001012053300","meta":{"title":"API: Retrieve data for an existing zettel","tags":"#api #manual #zettelstore","syntax":"zmk","role":"manual","copyright":"(c) 2020 by Detlef Stern <ds@zettelstore.de>","lang":"en","license":"CC BY-SA 4.0"},"content":"The endpoint to work with a specific zettel is ''/j/{ID}'', where ''{ID}'' is a placeholder for the [[zettel identifier|00001006050000}}.\n\nFor example, ...
```
Pretty-printed, this results in:
```
{
"id": "00001012053300",
"meta": {
|
︙ | | |
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
+
|
Other values will result in a HTTP response status code ''400''.
; ''"content"''
: Is a string value that contains the content of the zettel to be created.
Typically, text content is not encoded, and binary content is encoded via Base64.
; ''"rights"''
: An integer number that describes the [[access rights|00001012921200]] for the zettel.
=== Plain zettel
[!plain]Additionally, you can retrieve the plain zettel, without using JSON.
Just change the [[endpoint|00001012920000]] to ''/z/{ID}''
Optionally, you may provide which parts of the zettel you are requesting.
In this case, add an additional query parameter ''_part=[[PART|00001012920800]]''.
Valid values are ""zettel"", ""[[meta|00001012053400]]"", and ""content"" (the default value).
````sh
|
︙ | | |
Changes to docs/manual/00001012053500.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001012053500
title: API: Retrieve evaluated metadata and content of an existing zettel in various encodings
role: manual
tags: #api #manual #zettelstore
syntax: zmk
modified: 20220301174012
modified: 20220410153546
The [[endpoint|00001012920000]] to work with evaluated metadata and content of a specific zettel is ''/v/{ID}'', where ''{ID}'' is a placeholder for the [[zettel identifier|00001006050000]].
For example, to retrieve some evaluated data about this zettel you are currently viewing, just send a HTTP GET request to the endpoint ''/v/00001012053500''[^If [[authentication is enabled|00001010040100]], you must include the a valid [[access token|00001012050200]] in the ''Authorization'' header].
If successful, the output is a JSON object:
```sh
# curl http://127.0.0.1:23123/v/00001012053500
|
︙ | | |
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
-
-
|
<meta name="zs-box-number" content="1">
<meta name="copyright" content="(c) 2020-2021 by Detlef Stern <ds@zettelstore.de>">
<meta name="zs-forward" content="00001010040100 00001012050200 00001012920000 00001012920800">
<meta name="zs-lang" content="en">
<meta name="zs-published" content="00001012053500">
```
The optional query parameter ''_embed'' will embed all images into the returned encoding.
=== HTTP Status codes
; ''200''
: Retrieval was successful, the body contains an appropriate JSON object.
; ''400''
: Request was not valid.
There are several reasons for this.
Maybe the zettel identifier did not consist of exactly 14 digits or ''_enc'' / ''_part'' contained illegal values.
; ''403''
: You are not allowed to retrieve data of the given zettel.
; ''404''
: Zettel not found.
You probably used a zettel identifier that is not used in the Zettelstore.
|
Changes to docs/manual/00001012920000.zettel.
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
|
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
|
-
+
-
+
-
-
|
id: 00001012920000
title: Endpoints used by the API
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20220304173423
modified: 20220627183408
All API endpoints conform to the pattern ''[PREFIX]LETTER[/ZETTEL-ID]'', where:
; ''PREFIX''
: is the URL prefix (default: ""/""), configured via the ''url-prefix'' [[startup configuration|00001004010000]],
; ''LETTER''
: is a single letter that specifies the resource type,
; ''ZETTEL-ID''
: is an optional 14 digits string that uniquely [[identify a zettel|00001006050000]].
The following letters are currently in use:
|= Letter:| Without zettel identifier | With [[zettel identifier|00001006050000]] | Mnemonic
| ''a'' | POST: [[client authentication|00001012050200]] | | **A**uthenticate
| | PUT: [[renew access token|00001012050400]] |
| ''j'' | GET: [[list zettel AS JSON|00001012051200]] | GET: [[retrieve zettel AS JSON|00001012053300]] | **J**SON
| | POST: [[create new zettel|00001012053200]] | PUT: [[update a zettel|00001012054200]]
| | | DELETE: [[delete the zettel|00001012054600]]
| | | MOVE: [[rename the zettel|00001012054400]]
| ''m'' | | GET: [[retrieve metadata|00001012053400]] | **M**etadata
| ''m'' | GET: [[map metadata values|00001012052400]] | GET: [[retrieve metadata|00001012053400]] | **M**etadata
| ''o'' | | GET: [[list zettel order|00001012054000]] | **O**rder
| ''p'' | | GET: [[retrieve parsed zettel|00001012053600]]| **P**arsed
| ''r'' | GET: [[list roles|00001012052600]] | | **R**oles
| ''t'' | GET: [[list tags|00001012052400]] || **T**ags
| ''u'' | | GET [[unlinked references|00001012053900]] | **U**nlinked
| ''v'' | | GET: [[retrieve evaluated zettel|00001012053500]] | E**v**aluated
| ''x'' | GET: [[retrieve administrative data|00001012070500]] | GET: [[list zettel context|00001012053800]] | Conte**x**t
| | POST: [[execute command|00001012080100]]
| ''z'' | GET: [[list zettel|00001012051200#plain]] | GET: [[retrieve zettel|00001012053300#plain]] | **Z**ettel
| | POST: [[create new zettel|00001012053200#plain]] | PUT: [[update a zettel|00001012054200#plain]]
| | | DELETE: [[delete zettel|00001012054600#plain]]
| | | MOVE: [[rename zettel|00001012054400#plain]]
The full URL will contain either the ""http"" oder ""https"" scheme, a host name, and an optional port number.
The API examples will assume the ""http"" schema, the local host ""127.0.0.1"", the default port ""23123"", and the default empty ''PREFIX'' ""/"".
Therefore, all URLs in the API documentation will begin with ""http://127.0.0.1:23123/"".
|
Changes to docs/manual/00001012920500.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
+
-
-
+
+
|
id: 00001012920500
title: Encodings available via the [[API|00001012000000]]
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20220209114459
modified: 20220423131535
A zettel representation can be encoded in various formats for further processing.
* [[zjson|00001012920503]] (default)
* [[html|00001012920510]]
* [[native|00001012920513]]
* [[sexpr|00001012920516]]
* [[text|00001012920519]]
* [[zjson|00001012920503]] (default)
* [[zmk|00001012920522]]
|
Changes to docs/manual/00001012920503.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
-
+
-
+
|
id: 00001012920503
title: ZJSON Encoding
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20220223185826
modified: 20220422191748
A zettel representation that allows to process the syntactic structure of a zettel.
It is a JSON-based encoding format, but different to the structures returned by [[endpoint|00001012920000]] ''/j/{ID}''.
For an example, take a look at the JSON encoding of this page, which is available via the ""Info"" sub-page of this zettel:
For an example, take a look at the ZJSON encoding of this page, which is available via the ""Info"" sub-page of this zettel:
* [[//v/00001012920503?_enc=zjson&_part=zettel]],
* [[//v/00001012920503?_enc=zjson&_part=meta]],
* [[//v/00001012920503?_enc=zjson&_part=content]].
If transferred via HTTP, the content type will be ''application/json''.
|
︙ | | |
Deleted docs/manual/00001012920513.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
|
-
-
-
-
-
-
-
-
-
-
-
-
-
|
id: 00001012920513
title: Native Encoding
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20210726193049
A zettel representation shows the structure of a zettel in a more user-friendly way.
Mostly used for debugging.
If transferred via HTTP, the content type will be ''text/plain''.
TODO: formal description
|
Added docs/manual/00001012920516.zettel.
|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
id: 00001012920516
title: Sexpr Encoding
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20220724170637
A zettel representation that is a [[s-expression|https://en.wikipedia.org/wiki/S-expression]] (also known as symbolic expression).
It is an alternative to the [[ZJSON encoding|00001012920503]].
Both encodings are (relatively) easy to parse and contain all relevant information of a zettel, metadata and content.
For example, take a look at the Sexpr encoding of this page, which is available via the ""Info"" sub-page of this zettel:
* [[//v/00001012920516?_enc=sexpr&_part=zettel]],
* [[//v/00001012920516?_enc=sexpr&_part=meta]],
* [[//v/00001012920516?_enc=sexpr&_part=content]].
If transferred via HTTP, the content type will be ''text/plain''.
=== Syntax of s-expressions
There are only two types of elements: atoms and lists.
A list always starts with the left parenthesis (""''(''"", U+0028) and ends with a right parenthesis (""'')''"", U+0029).
A list may contain a possibly empty sequence of elements, i.e. lists and / or atoms.
There are three syntactic forms for an atom: numbers, symbols and strings.
A number is a non-empty sequence of digits (""0"" ... ""9"").
The smallest number is ``0``, there are no negative numbers.
A symbol is a non-empty sequence of printable characters, except left or right parenthesis.
Unicode characters of the following categories contains printable characters in the above sense: letter (L), number (N), punctuation (P), symbol (S).
Symbols are case-insensitive, i.e. ""''ZETTEL''"" and ""''zettel''"" denote the same symbol.
A string starts with a quotation mark (""''"''"", U+0022), contains a possibly empty sequence of Unicode characters, and ends with a quotation mark.
To allow a string to contain a quotations mark, it must be prefixed by one backslash (""''\\''"", U+005C).
To allow a string to contain a backslash, it also must be prefixed by one backslash.
Unicode characters with a code less than U+FF are encoded by by the sequence ""''\\xNM''"", where ''NM'' is the hex encoding of the character.
Unicode characters with a code less than U+FFFF are encoded by by the sequence ""''\\uNMOP''"", where ''NMOP'' is the hex encoding of the character.
Unicode characters with a code less than U+FFFFFF are encoded by by the sequence ""''\\UNMOPQR''"", where ''NMOPQR'' is the hex encoding of the character.
In addition, the sequence ""''\\t''"" encodes a horizontal tab (U+0009), the sequence ""''\\n''"" encodes a line feed (U+000A).
Atoms are separated by Unicode characters of category separator (Z).
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Changes to docs/manual/00001012920519.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-
+
|
id: 00001012920519
title: Text Encoding
role: manual
tags: #api #manual #reference #zettelstore
syntax: zmk
modified: 20210726193119
A zettel representation contains just all textual data of a zettel.
Could be used for creating a search index.
Every line may contain zero, one, or more words, spearated by space character.
Every line may contain zero, one, or more words, separated by space character.
If transferred via HTTP, the content type will be ''text/plain''.
|
Changes to docs/manual/00001012921000.zettel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-
+
|
id: 00001012921000
title: API: JSON structure of an access token
tags: #api #manual #reference #zettelstore
syntax: zmk
role: manual
If the [[authentiction process|00001012050200]] was successful, an access token with some additional data is returned.
If the [[authentication process|00001012050200]] was successful, an access token with some additional data is returned.
The same is true, if the access token was [[renewed|00001012050400]].
The response is structured as an JSON object, with the following named values:
|=Name|Description
|''access_token''|The access token itself, as string value, which is a [[JSON Web Token|https://tools.ietf.org/html/rfc7519]] (JWT, RFC 7915)
|''token_type''|The type of the token, always set to ''"Bearer"'', as described in [[RFC 6750|https://tools.ietf.org/html/rfc6750]]
|''expires_in''|An integer that gives a hint about the lifetime / endurance of the token, measured in seconds
|
Changes to domain/id/id.go.
1
2
3
4
5
6
7
8
9
10
11
|
1
2
3
4
5
6
7
8
9
10
11
|
-
+
-
+
|
//-----------------------------------------------------------------------------
// Copyright (c) 2020-2021 Detlef Stern
// Copyright (c) 2020-2022 Detlef Stern
//
// This file is part of zettelstore.
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//-----------------------------------------------------------------------------
// Package id provides domain specific types, constants, and functions about
|
︙ | | |
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
+
|
FormTemplateZid = MustParse(api.ZidFormTemplate)
RenameTemplateZid = MustParse(api.ZidRenameTemplate)
DeleteTemplateZid = MustParse(api.ZidDeleteTemplate)
ContextTemplateZid = MustParse(api.ZidContextTemplate)
RolesTemplateZid = MustParse(api.ZidRolesTemplate)
TagsTemplateZid = MustParse(api.ZidTagsTemplate)
ErrorTemplateZid = MustParse(api.ZidErrorTemplate)
RoleCSSMapZid = MustParse(api.ZidRoleCSSMap)
EmojiZid = MustParse(api.ZidEmoji)
TOCNewTemplateZid = MustParse(api.ZidTOCNewTemplate)
DefaultHomeZid = MustParse(api.ZidDefaultHome)
)
const maxZid = 99999999999999
|
︙ | | |
Added domain/meta/collection.go.