Zettelstore Client

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From v0.21.0 To trunk

2025-06-26
12:52
Add constant for CONTEXT/Thread directive; add suffix types -ref and -refs ... (Leaf check-in: aeaaa36dab user: stern tags: trunk)
09:32
Remove predefined metadata keys predecessor, successor ... (check-in: e250b76bf1 user: stern tags: trunk)
2025-05-02
14:34
Remove Zid for SxnPrelude ... (check-in: b5c74e61e1 user: stern tags: trunk)
2025-04-17
14:58
Version 0.21.0 ... (check-in: ef331b4f0c user: stern tags: release, trunk, v0.21.0)
09:21
Update changelog ... (check-in: 6f32e74255 user: stern tags: trunk)

Changes to api/const.go.
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
const (
	CommandAuthenticated = Command("authenticated")
	CommandRefresh       = Command("refresh")
)

// Supported search operator representations.
const (
	BackwardDirective = "BACKWARD" // Backward-only context
	ContextDirective  = "CONTEXT"  // Context directive
	CostDirective     = "COST"     // Maximum cost of a context operation


	ForwardDirective  = "FORWARD"  // Forward-only context
	FullDirective     = "FULL"     // Include tags in context
	IdentDirective    = "IDENT"    // Use only specified zettel
	ItemsDirective    = "ITEMS"    // Select list elements in a zettel
	MaxDirective      = "MAX"      // Maximum number of context results
	MinDirective      = "MIN"      // Minimum number of context results
	LimitDirective    = "LIMIT"    // Maximum number of zettel
	OffsetDirective   = "OFFSET"   // Offset to start returned zettel list
	OrDirective       = "OR"       // Combine several search expression with an "or"
	OrderDirective    = "ORDER"    // Specify metadata keys for the order of returned list
	PhraseDirective   = "PHRASE"   // Only unlinked zettel with given phrase
	PickDirective     = "PICK"     // Pick some random zettel
	RandomDirective   = "RANDOM"   // Order zettel list randomly
	ReverseDirective  = "REVERSE"  // Reverse the order of a zettel list


	UnlinkedDirective = "UNLINKED" // Search for zettel that contain a phase(s) but do not link

	ActionSeparator = "|" // Separates action list of previous elements of query expression

	KeysAction     = "KEYS"     // Provide metadata key used
	MinAction      = "MIN"      // Return only those values with a minimum amount of zettel
	MaxAction      = "MAX"      // Return only those values with a maximum amount of zettel







|


>
>
|



|









>
>







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
const (
	CommandAuthenticated = Command("authenticated")
	CommandRefresh       = Command("refresh")
)

// Supported search operator representations.
const (
	BackwardDirective = "BACKWARD" // Backward-only context / thread
	ContextDirective  = "CONTEXT"  // Context directive
	CostDirective     = "COST"     // Maximum cost of a context operation
	DirectedDirective = "DIRECTED" // Context/thread collection can have general directions
	FolgeDirective    = "FOLGE"    // Folge thread
	ForwardDirective  = "FORWARD"  // Forward-only context / thread
	FullDirective     = "FULL"     // Include tags in context
	IdentDirective    = "IDENT"    // Use only specified zettel
	ItemsDirective    = "ITEMS"    // Select list elements in a zettel
	MaxDirective      = "MAX"      // Maximum number of context / thread results
	MinDirective      = "MIN"      // Minimum number of context results
	LimitDirective    = "LIMIT"    // Maximum number of zettel
	OffsetDirective   = "OFFSET"   // Offset to start returned zettel list
	OrDirective       = "OR"       // Combine several search expression with an "or"
	OrderDirective    = "ORDER"    // Specify metadata keys for the order of returned list
	PhraseDirective   = "PHRASE"   // Only unlinked zettel with given phrase
	PickDirective     = "PICK"     // Pick some random zettel
	RandomDirective   = "RANDOM"   // Order zettel list randomly
	ReverseDirective  = "REVERSE"  // Reverse the order of a zettel list
	SequelDirective   = "SEQUEL"   // Sequel / branching thread
	ThreadDirective   = "THREAD"   // Both folge and Sequel thread
	UnlinkedDirective = "UNLINKED" // Search for zettel that contain a phase(s) but do not link

	ActionSeparator = "|" // Separates action list of previous elements of query expression

	KeysAction     = "KEYS"     // Provide metadata key used
	MinAction      = "MIN"      // Return only those values with a minimum amount of zettel
	MaxAction      = "MAX"      // Return only those values with a maximum amount of zettel
Changes to client/client_test.go.
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
	"t73f.de/r/zsc/api"
	"t73f.de/r/zsc/client"
	"t73f.de/r/zsc/domain/id"
)

func TestZettelList(t *testing.T) {
	c := getClient()
	_, err := c.QueryZettel(context.Background(), "")
	if err != nil {
		t.Error(err)
		return
	}
}

func TestGetProtectedZettel(t *testing.T) {
	c := getClient()
	_, err := c.GetZettel(context.Background(), id.ZidStartupConfiguration, api.PartZettel)
	if err != nil {
		if cErr, ok := err.(*client.Error); ok && cErr.StatusCode == http.StatusForbidden {
			return
		} else {
			t.Error(err)
		}
		return
	}
}

func TestGetSzZettel(t *testing.T) {
	c := getClient()
	value, err := c.GetEvaluatedSz(context.Background(), id.ZidDefaultHome, api.PartContent)
	if err != nil {







|
<

<





|
<
|
<
<


<







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
	"t73f.de/r/zsc/api"
	"t73f.de/r/zsc/client"
	"t73f.de/r/zsc/domain/id"
)

func TestZettelList(t *testing.T) {
	c := getClient()
	if _, err := c.QueryZettel(context.Background(), ""); err != nil {

		t.Error(err)

	}
}

func TestGetProtectedZettel(t *testing.T) {
	c := getClient()
	if _, err := c.GetZettel(context.Background(), id.ZidStartupConfiguration, api.PartZettel); err != nil {

		if cErr, ok := err.(*client.Error); !ok || cErr.StatusCode != http.StatusForbidden {


			t.Error(err)
		}

	}
}

func TestGetSzZettel(t *testing.T) {
	c := getClient()
	value, err := c.GetEvaluatedSz(context.Background(), id.ZidDefaultHome, api.PartContent)
	if err != nil {
Changes to domain/id/id.go.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

	// WebUI JS zettel are in the range 30000..39999

	// WebUI image zettel are in the range 40000..49999
	ZidEmoji = Zid(40001)

	// Other sxn code zettel are in the range 50000..59999
	ZidSxnPrelude = Zid(59900)

	// Predefined Zettelmarkup zettel are in the range 60000..69999
	ZidRoleZettelZettel        = Zid(60010)
	ZidRoleConfigurationZettel = Zid(60020)
	ZidRoleRoleZettel          = Zid(60030)
	ZidRoleTagZettel           = Zid(60040)








<







85
86
87
88
89
90
91

92
93
94
95
96
97
98

	// WebUI JS zettel are in the range 30000..39999

	// WebUI image zettel are in the range 40000..49999
	ZidEmoji = Zid(40001)

	// Other sxn code zettel are in the range 50000..59999


	// Predefined Zettelmarkup zettel are in the range 60000..69999
	ZidRoleZettelZettel        = Zid(60010)
	ZidRoleConfigurationZettel = Zid(60020)
	ZidRoleRoleZettel          = Zid(60030)
	ZidRoleTagZettel           = Zid(60040)

Changes to domain/meta/meta.go.
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
175
176
177
178
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
	KeyFolge        = "folge"
	KeyFolgeRole    = "folge-role"
	KeyForward      = "forward"
	KeyLang         = "lang"
	KeyLicense      = "license"
	KeyModified     = "modified"
	KeyPrecursor    = "precursor"
	KeyPredecessor  = "predecessor"
	KeyPrequel      = "prequel"
	KeyPublished    = "published"
	KeyQuery        = "query"
	KeyReadOnly     = "read-only"
	KeySequel       = "sequel"
	KeySubordinates = "subordinates"
	KeySuccessors   = "successors"
	KeySummary      = "summary"
	KeySuperior     = "superior"
	KeyURL          = "url"
	KeyUselessFiles = "useless-files"
	KeyUserID       = "user-id"
	KeyUserRole     = "user-role"
	KeyVisibility   = "visibility"
)

// Supported keys.
func init() {
	registerKey(KeyID, TypeID, usageComputed, "")
	registerKey(KeyTitle, TypeEmpty, usageUser, "")
	registerKey(KeyRole, TypeWord, usageUser, "")
	registerKey(KeyTags, TypeTagSet, usageUser, "")
	registerKey(KeySyntax, TypeWord, usageUser, "")

	// Properties that are inverse keys
	registerKey(KeyFolge, TypeIDSet, usageProperty, "")
	registerKey(KeySequel, TypeIDSet, usageProperty, "")
	registerKey(KeySuccessors, TypeIDSet, usageProperty, "")
	registerKey(KeySubordinates, TypeIDSet, usageProperty, "")

	// Non-inverse keys
	registerKey(KeyAuthor, TypeString, usageUser, "")
	registerKey(KeyBack, TypeIDSet, usageProperty, "")
	registerKey(KeyBackward, TypeIDSet, usageProperty, "")
	registerKey(KeyBoxNumber, TypeNumber, usageProperty, "")
	registerKey(KeyCopyright, TypeString, usageUser, "")
	registerKey(KeyCreated, TypeTimestamp, usageComputed, "")
	registerKey(KeyCredential, TypeCredential, usageUser, "")
	registerKey(KeyDead, TypeIDSet, usageProperty, "")
	registerKey(KeyExpire, TypeTimestamp, usageUser, "")
	registerKey(KeyFolgeRole, TypeWord, usageUser, "")
	registerKey(KeyForward, TypeIDSet, usageProperty, "")
	registerKey(KeyLang, TypeWord, usageUser, "")
	registerKey(KeyLicense, TypeEmpty, usageUser, "")
	registerKey(KeyModified, TypeTimestamp, usageComputed, "")
	registerKey(KeyPrecursor, TypeIDSet, usageUser, KeyFolge)
	registerKey(KeyPredecessor, TypeID, usageUser, KeySuccessors)
	registerKey(KeyPrequel, TypeIDSet, usageUser, KeySequel)
	registerKey(KeyPublished, TypeTimestamp, usageProperty, "")
	registerKey(KeyQuery, TypeEmpty, usageUser, "")
	registerKey(KeyReadOnly, TypeWord, usageUser, "")
	registerKey(KeySummary, TypeString, usageUser, "")
	registerKey(KeySuperior, TypeIDSet, usageUser, KeySubordinates)
	registerKey(KeyURL, TypeURL, usageUser, "")







<






<




















<


















<







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

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
	KeyFolge        = "folge"
	KeyFolgeRole    = "folge-role"
	KeyForward      = "forward"
	KeyLang         = "lang"
	KeyLicense      = "license"
	KeyModified     = "modified"
	KeyPrecursor    = "precursor"

	KeyPrequel      = "prequel"
	KeyPublished    = "published"
	KeyQuery        = "query"
	KeyReadOnly     = "read-only"
	KeySequel       = "sequel"
	KeySubordinates = "subordinates"

	KeySummary      = "summary"
	KeySuperior     = "superior"
	KeyURL          = "url"
	KeyUselessFiles = "useless-files"
	KeyUserID       = "user-id"
	KeyUserRole     = "user-role"
	KeyVisibility   = "visibility"
)

// Supported keys.
func init() {
	registerKey(KeyID, TypeID, usageComputed, "")
	registerKey(KeyTitle, TypeEmpty, usageUser, "")
	registerKey(KeyRole, TypeWord, usageUser, "")
	registerKey(KeyTags, TypeTagSet, usageUser, "")
	registerKey(KeySyntax, TypeWord, usageUser, "")

	// Properties that are inverse keys
	registerKey(KeyFolge, TypeIDSet, usageProperty, "")
	registerKey(KeySequel, TypeIDSet, usageProperty, "")

	registerKey(KeySubordinates, TypeIDSet, usageProperty, "")

	// Non-inverse keys
	registerKey(KeyAuthor, TypeString, usageUser, "")
	registerKey(KeyBack, TypeIDSet, usageProperty, "")
	registerKey(KeyBackward, TypeIDSet, usageProperty, "")
	registerKey(KeyBoxNumber, TypeNumber, usageProperty, "")
	registerKey(KeyCopyright, TypeString, usageUser, "")
	registerKey(KeyCreated, TypeTimestamp, usageComputed, "")
	registerKey(KeyCredential, TypeCredential, usageUser, "")
	registerKey(KeyDead, TypeIDSet, usageProperty, "")
	registerKey(KeyExpire, TypeTimestamp, usageUser, "")
	registerKey(KeyFolgeRole, TypeWord, usageUser, "")
	registerKey(KeyForward, TypeIDSet, usageProperty, "")
	registerKey(KeyLang, TypeWord, usageUser, "")
	registerKey(KeyLicense, TypeEmpty, usageUser, "")
	registerKey(KeyModified, TypeTimestamp, usageComputed, "")
	registerKey(KeyPrecursor, TypeIDSet, usageUser, KeyFolge)

	registerKey(KeyPrequel, TypeIDSet, usageUser, KeySequel)
	registerKey(KeyPublished, TypeTimestamp, usageProperty, "")
	registerKey(KeyQuery, TypeEmpty, usageUser, "")
	registerKey(KeyReadOnly, TypeWord, usageUser, "")
	registerKey(KeySummary, TypeString, usageUser, "")
	registerKey(KeySuperior, TypeIDSet, usageUser, KeySubordinates)
	registerKey(KeyURL, TypeURL, usageUser, "")
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
300
301
302
303
304
305
	}
}

// SetNonEmpty stores the given value under the given key, if the value is non-empty.
// An empty value will delete the previous association.
func (m *Meta) SetNonEmpty(key string, value Value) {
	if value == "" {

		delete(m.pairs, key) // TODO: key != KeyID

	} else {
		m.Set(key, value.TrimSpace())
	}
}











// Get retrieves the string value of a given key. The bool value signals,
// whether there was a value stored or not.
func (m *Meta) Get(key string) (Value, bool) {
	if m == nil {

		return "", false
	}
	if key == KeyID {
		return Value(m.Zid.String()), true
	}
	value, ok := m.pairs[key]

	return value, ok
}

// GetDefault retrieves the string value of the given key. If no value was
// stored, the given default value is returned.
func (m *Meta) GetDefault(key string, def Value) Value {
	if value, found := m.Get(key); found {
		return value







>
|
>




>
>
>
>
>
>
>
>
>
>




|
>
|
|
|
|
|
<
>
|







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
300
301
302
303
304
305

306
307
308
309
310
311
312
313
314
	}
}

// SetNonEmpty stores the given value under the given key, if the value is non-empty.
// An empty value will delete the previous association.
func (m *Meta) SetNonEmpty(key string, value Value) {
	if value == "" {
		if key != KeyID {
			delete(m.pairs, key)
		}
	} else {
		m.Set(key, value.TrimSpace())
	}
}

// Has returns true, if the given key is used in the metadata.
func (m *Meta) Has(key string) bool {
	if m != nil {
		if _, found := m.pairs[key]; found || key == KeyID {
			return true
		}
	}
	return false
}

// Get retrieves the string value of a given key. The bool value signals,
// whether there was a value stored or not.
func (m *Meta) Get(key string) (Value, bool) {
	if m != nil {
		if value, found := m.pairs[key]; found {
			return value, true
		}
		if key == KeyID {
			return Value(m.Zid.String()), true
		}

	}
	return "", false
}

// GetDefault retrieves the string value of the given key. If no value was
// stored, the given default value is returned.
func (m *Meta) GetDefault(key string, def Value) Value {
	if value, found := m.Get(key); found {
		return value
Changes to domain/meta/type.go.
90
91
92
93
94
95
96


97
98
99
100
101
102
103

var (
	cachedTypedKeys = make(map[string]*DescriptionType)
	mxTypedKey      sync.RWMutex
	suffixTypes     = map[string]*DescriptionType{
		"-date":       TypeTimestamp,
		"-number":     TypeNumber,


		SuffixKeyRole: TypeWord,
		"-time":       TypeTimestamp,
		SuffixKeyURL:  TypeURL,
		"-zettel":     TypeID,
		"-zid":        TypeID,
		"-zids":       TypeIDSet,
	}







>
>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

var (
	cachedTypedKeys = make(map[string]*DescriptionType)
	mxTypedKey      sync.RWMutex
	suffixTypes     = map[string]*DescriptionType{
		"-date":       TypeTimestamp,
		"-number":     TypeNumber,
		"-ref":        TypeID,
		"-refs":       TypeIDSet,
		SuffixKeyRole: TypeWord,
		"-time":       TypeTimestamp,
		SuffixKeyURL:  TypeURL,
		"-zettel":     TypeID,
		"-zid":        TypeID,
		"-zids":       TypeIDSet,
	}
Changes to go.mod.
1
2
3
4
5
6
7
8
9
10
11
module t73f.de/r/zsc

go 1.24

require (
	t73f.de/r/sx v0.0.0-20250415161954-42ed9c4d6abc
	t73f.de/r/sxwebs v0.0.0-20250415162443-110f49c5a1ae
	t73f.de/r/webs v0.0.0-20250311182734-f263a38b32d5
	t73f.de/r/zero v0.0.0-20250226205915-c4194684acb7
	t73f.de/r/zsx v0.0.0-20250415162540-fc13b286b6ce
)





|
|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
module t73f.de/r/zsc

go 1.24

require (
	t73f.de/r/sx v0.0.0-20250620141036-553aa22c59dc
	t73f.de/r/sxwebs v0.0.0-20250621125212-c25706b6e4b3
	t73f.de/r/webs v0.0.0-20250604132257-c12dbd1f7046
	t73f.de/r/zero v0.0.0-20250604143210-ce1230735c4c
	t73f.de/r/zsx v0.0.0-20250526093914-c34f0bae8fd2
)
Changes to go.sum.
1
2
3
4
5
6
7
8
9
10
t73f.de/r/sx v0.0.0-20250415161954-42ed9c4d6abc h1:tlsP+47Rf8i9Zv1TqRnwfbQx3nN/F/92RkT6iCA6SVA=
t73f.de/r/sx v0.0.0-20250415161954-42ed9c4d6abc/go.mod h1:hzg05uSCMk3D/DWaL0pdlowfL2aWQeGIfD1S04vV+Xg=
t73f.de/r/sxwebs v0.0.0-20250415162443-110f49c5a1ae h1:K6nxN/bb0BCSiDffwNPGTF2uf5WcTdxcQXzByXNuJ7M=
t73f.de/r/sxwebs v0.0.0-20250415162443-110f49c5a1ae/go.mod h1:0LQ9T1svSg9ADY/6vQLKNUu6LqpPi8FGr7fd2qDT5H8=
t73f.de/r/webs v0.0.0-20250311182734-f263a38b32d5 h1:nnKfs/2i9n3S5VjbSj98odcwZKGcL96qPSIUATT/2P8=
t73f.de/r/webs v0.0.0-20250311182734-f263a38b32d5/go.mod h1:zk92hSKB4iWyT290+163seNzu350TA9XLATC9kOldqo=
t73f.de/r/zero v0.0.0-20250226205915-c4194684acb7 h1:OuzHSfniY8UzLmo5zp1w23Kd9h7x9CSXP2jQ+kppeqU=
t73f.de/r/zero v0.0.0-20250226205915-c4194684acb7/go.mod h1:T1vFcHoymUQcr7+vENBkS1yryZRZ3YB8uRtnMy8yRBA=
t73f.de/r/zsx v0.0.0-20250415162540-fc13b286b6ce h1:R9rtg4ecx4YYixsMmsh+wdcqLdY9GxoC5HZ9mMS33to=
t73f.de/r/zsx v0.0.0-20250415162540-fc13b286b6ce/go.mod h1:tXOlmsQBoY4mY7Plu0LCCMZNSJZJbng98fFarZXAWvM=
|
|
|
|
|
|
|
|
|
|
1
2
3
4
5
6
7
8
9
10
t73f.de/r/sx v0.0.0-20250620141036-553aa22c59dc h1:5s02C7lwQKjOXyY4ghR6oLo+0SagSBiEiC26ju3VG40=
t73f.de/r/sx v0.0.0-20250620141036-553aa22c59dc/go.mod h1:Ow4Btc5PCykSct4TrS1kbEB386msl/tmfmLSsEz6OAw=
t73f.de/r/sxwebs v0.0.0-20250621125212-c25706b6e4b3 h1:+tqWPX3z5BgsRZJDpMtReHmGUioUFP+LsPpXieZ2ZsY=
t73f.de/r/sxwebs v0.0.0-20250621125212-c25706b6e4b3/go.mod h1:zZBXrGeTfUqElkSMJhGUCuDDWNOUaZE0EH3IZwkW+RA=
t73f.de/r/webs v0.0.0-20250604132257-c12dbd1f7046 h1:BZWNT/wYlX5sHmEtClRG0rHzZnoh8J35NcRnTvXlqy0=
t73f.de/r/webs v0.0.0-20250604132257-c12dbd1f7046/go.mod h1:EVohQwCAlRK0kuVBEw5Gw+S44vj+6f6NU8eNJdAIK6s=
t73f.de/r/zero v0.0.0-20250604143210-ce1230735c4c h1:Zy7GaPv/uVSjKQY7t2c0OOIdSue36x+/0sXt+xoxlpQ=
t73f.de/r/zero v0.0.0-20250604143210-ce1230735c4c/go.mod h1:T1vFcHoymUQcr7+vENBkS1yryZRZ3YB8uRtnMy8yRBA=
t73f.de/r/zsx v0.0.0-20250526093914-c34f0bae8fd2 h1:GWLCd3n8mN6AGhiv8O7bhdjK0BqXQS5EExRlBdx3OPU=
t73f.de/r/zsx v0.0.0-20250526093914-c34f0bae8fd2/go.mod h1:IQdyC9JP1i6RK55+LJVGjP3hSA9H766yCyUt1AkOU9c=
Changes to sexp/sexp.go.
17
18
19
20
21
22
23

24
25
26
27
28
29
30

import (
	"errors"
	"fmt"
	"sort"

	"t73f.de/r/sx"

	"t73f.de/r/zsc/api"
)

// EncodeZettel transforms zettel data into a sx object.
func EncodeZettel(zettel api.ZettelData) sx.Object {
	return sx.MakeList(
		sx.MakeSymbol("zettel"),







>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

import (
	"errors"
	"fmt"
	"sort"

	"t73f.de/r/sx"
	"t73f.de/r/sx/sxbuiltins"
	"t73f.de/r/zsc/api"
)

// EncodeZettel transforms zettel data into a sx object.
func EncodeZettel(zettel api.ZettelData) sx.Object {
	return sx.MakeList(
		sx.MakeSymbol("zettel"),
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
		Content:  contentVals[1].(sx.String).GetValue(),
	}, nil
}

// EncodeMetaRights translates metadata/rights into a sx object.
func EncodeMetaRights(mr api.MetaRights) *sx.Pair {
	return sx.MakeList(
		sx.SymbolList,
		meta2sz(mr.Meta),
		sx.MakeList(sx.MakeSymbol("rights"), sx.Int64(int64(mr.Rights))),
	)
}

func meta2sz(m api.ZettelMeta) sx.Object {
	var result sx.ListBuilder







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
		Content:  contentVals[1].(sx.String).GetValue(),
	}, nil
}

// EncodeMetaRights translates metadata/rights into a sx object.
func EncodeMetaRights(mr api.MetaRights) *sx.Pair {
	return sx.MakeList(
		sx.MakeSymbol(sxbuiltins.List.Name),
		meta2sz(mr.Meta),
		sx.MakeList(sx.MakeSymbol("rights"), sx.Int64(int64(mr.Rights))),
	)
}

func meta2sz(m api.ZettelMeta) sx.Object {
	var result sx.ListBuilder
Changes to sz/zmk/zmk_test.go.
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
			}
		})
	}
}

type astWalker struct{}

func (astWalker) VisitBefore(node *sx.Pair, env *sx.Pair) (sx.Object, bool) { return sx.Nil(), false }
func (astWalker) VisitAfter(node *sx.Pair, env *sx.Pair) sx.Object          { return node }

func TestEdges(t *testing.T) {
	t.Parallel()
	checkTcs(t, TestCases{
		{"\"\"\"\n; \n0{{0}}{0}\n\"\"\"", "(BLOCK (REGION-VERSE () ((DESCRIPTION () ()) (PARA (TEXT \"0\") (EMBED ((\"0\" . \"\")) (HOSTED \"0\") \"\")))))"},
	})
}







|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
			}
		})
	}
}

type astWalker struct{}

func (astWalker) VisitBefore(*sx.Pair, *sx.Pair) (sx.Object, bool) { return sx.Nil(), false }
func (astWalker) VisitAfter(node *sx.Pair, _ *sx.Pair) sx.Object   { return node }

func TestEdges(t *testing.T) {
	t.Parallel()
	checkTcs(t, TestCases{
		{"\"\"\"\n; \n0{{0}}{0}\n\"\"\"", "(BLOCK (REGION-VERSE () ((DESCRIPTION () ()) (PARA (TEXT \"0\") (EMBED ((\"0\" . \"\")) (HOSTED \"0\") \"\")))))"},
	})
}