Index: VERSION
==================================================================
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
-0.0.14
+0.0.15
Index: api/api.go
==================================================================
--- api/api.go
+++ api/api.go
@@ -18,45 +18,41 @@
Expires int `json:"expires_in"`
}
// ZidJSON contains the identifier data of a zettel.
type ZidJSON struct {
- ID string `json:"id"`
- URL string `json:"url"`
+ ID string `json:"id"`
}
// ZidMetaJSON contains the identifier and the metadata of a zettel.
type ZidMetaJSON struct {
ID string `json:"id"`
- URL string `json:"url"`
Meta map[string]string `json:"meta"`
}
// ZidMetaRelatedList contains identifier/metadata of a zettel and the same for related zettel
type ZidMetaRelatedList struct {
ID string `json:"id"`
- URL string `json:"url"`
Meta map[string]string `json:"meta"`
List []ZidMetaJSON `json:"list"`
}
// ZettelLinksJSON store all links / connections from one zettel to other.
type ZettelLinksJSON struct {
- ID string `json:"id"`
- URL string `json:"url"`
- Links struct {
- Incoming []ZidJSON `json:"incoming,omitempty"`
- Outgoing []ZidJSON `json:"outgoing,omitempty"`
- Local []string `json:"local,omitempty"`
- External []string `json:"external,omitempty"`
- Meta []string `json:"meta,omitempty"`
- } `json:"links"`
- Images struct {
- Outgoing []ZidJSON `json:"outgoing,omitempty"`
- Local []string `json:"local,omitempty"`
- External []string `json:"external,omitempty"`
- } `json:"images,omitempty"`
+ ID string `json:"id"`
+ Linked struct {
+ Incoming []string `json:"incoming,omitempty"`
+ Outgoing []string `json:"outgoing,omitempty"`
+ Local []string `json:"local,omitempty"`
+ External []string `json:"external,omitempty"`
+ Meta []string `json:"meta,omitempty"`
+ } `json:"linked"`
+ Embedded struct {
+ Outgoing []string `json:"outgoing,omitempty"`
+ Local []string `json:"local,omitempty"`
+ External []string `json:"external,omitempty"`
+ } `json:"embedded,omitempty"`
Cites []string `json:"cites,omitempty"`
}
// ZettelDataJSON contains all data for a zettel.
type ZettelDataJSON struct {
@@ -66,19 +62,18 @@
}
// ZettelJSON contains all data for a zettel, the identifier, the metadata, and the content.
type ZettelJSON struct {
ID string `json:"id"`
- URL string `json:"url"`
Meta map[string]string `json:"meta"`
Encoding string `json:"encoding"`
Content string `json:"content"`
}
// ZettelListJSON contains data for a zettel list.
type ZettelListJSON struct {
- List []ZettelJSON `json:"list"`
+ List []ZidMetaJSON `json:"list"`
}
// TagListJSON specifies the list/map of tags
type TagListJSON struct {
Tags map[string][]string `json:"tags"`
Index: api/const.go
==================================================================
--- api/const.go
+++ api/const.go
@@ -9,13 +9,11 @@
//-----------------------------------------------------------------------------
// Package api contains common definition used for client and server.
package api
-import (
- "fmt"
-)
+import "fmt"
// Additional HTTP constants used.
const (
MethodMove = "MOVE" // HTTP method for renaming a zettel
@@ -25,54 +23,55 @@
HeaderLocation = "Location"
)
// Values for HTTP query parameter.
const (
- QueryKeyDepth = "depth"
- QueryKeyDir = "dir"
- QueryKeyFormat = "_format"
- QueryKeyLimit = "limit"
- QueryKeyPart = "_part"
+ QueryKeyDepth = "depth"
+ QueryKeyDir = "dir"
+ QueryKeyEncoding = "_enc"
+ QueryKeyLimit = "_limit"
+ QueryKeyNegate = "_negate"
+ QueryKeyOffset = "_offset"
+ QueryKeyOrder = "_order"
+ QueryKeyPart = "_part"
+ QueryKeySearch = "_s"
+ QueryKeySort = "_sort"
)
// Supported dir values.
const (
DirBackward = "backward"
DirForward = "forward"
)
-// Supported format values.
-const (
- FormatDJSON = "djson"
- FormatHTML = "html"
- FormatJSON = "json"
- FormatNative = "native"
- FormatRaw = "raw"
- FormatText = "text"
- FormatZMK = "zmk"
-)
-
-var formatEncoder = map[string]EncodingEnum{
- FormatDJSON: EncoderDJSON,
- FormatHTML: EncoderHTML,
- FormatJSON: EncoderJSON,
- FormatNative: EncoderNative,
- FormatRaw: EncoderRaw,
- FormatText: EncoderText,
- FormatZMK: EncoderZmk,
-}
-var encoderFormat = map[EncodingEnum]string{}
-
-func init() {
- for k, v := range formatEncoder {
- encoderFormat[v] = k
- }
-}
-
-// Encoder returns the internal encoder code for the given format string.
-func Encoder(format string) EncodingEnum {
- if e, ok := formatEncoder[format]; ok {
+// Supported encoding values.
+const (
+ EncodingDJSON = "djson"
+ EncodingHTML = "html"
+ EncodingNative = "native"
+ EncodingText = "text"
+ EncodingZMK = "zmk"
+)
+
+var mapEncodingEnum = map[string]EncodingEnum{
+ EncodingDJSON: EncoderDJSON,
+ EncodingHTML: EncoderHTML,
+ EncodingNative: EncoderNative,
+ EncodingText: EncoderText,
+ EncodingZMK: EncoderZmk,
+}
+var mapEnumEncoding = map[EncodingEnum]string{}
+
+func init() {
+ for k, v := range mapEncodingEnum {
+ mapEnumEncoding[v] = k
+ }
+}
+
+// Encoder returns the internal encoder code for the given encoding string.
+func Encoder(encoding string) EncodingEnum {
+ if e, ok := mapEncodingEnum[encoding]; ok {
return e
}
return EncoderUnknown
}
@@ -82,27 +81,24 @@
// Values for EncoderEnum
const (
EncoderUnknown EncodingEnum = iota
EncoderDJSON
EncoderHTML
- EncoderJSON
EncoderNative
- EncoderRaw
EncoderText
EncoderZmk
)
// String representation of an encoder key.
func (e EncodingEnum) String() string {
- if f, ok := encoderFormat[e]; ok {
+ if f, ok := mapEnumEncoding[e]; ok {
return f
}
return fmt.Sprintf("*Unknown*(%d)", e)
}
// Supported part values.
const (
- PartID = "id"
PartMeta = "meta"
PartContent = "content"
PartZettel = "zettel"
)
Index: ast/ast.go
==================================================================
--- ast/ast.go
+++ ast/ast.go
@@ -20,16 +20,15 @@
)
// ZettelNode is the root node of the abstract syntax tree.
// It is *not* part of the visitor pattern.
type ZettelNode struct {
- // Zettel domain.Zettel
Meta *meta.Meta // Original metadata
Content domain.Content // Original content
Zid id.Zid // Zettel identification.
InhMeta *meta.Meta // Metadata of the zettel, with inherited values.
- Ast BlockSlice // Zettel abstract syntax tree is a sequence of block nodes.
+ Ast *BlockListNode // Zettel abstract syntax tree is a sequence of block nodes.
}
// Node is the interface, all nodes must implement.
type Node interface {
WalkChildren(v Visitor)
@@ -39,21 +38,30 @@
type BlockNode interface {
Node
blockNode()
}
-// BlockSlice is a slice of BlockNodes.
-type BlockSlice []BlockNode
-
// ItemNode is a node that can occur as a list item.
type ItemNode interface {
BlockNode
itemNode()
}
// ItemSlice is a slice of ItemNodes.
type ItemSlice []ItemNode
+
+// ItemListNode is a list of BlockNodes.
+type ItemListNode struct {
+ List []ItemNode
+}
+
+// WalkChildren walks down to the descriptions.
+func (iln *ItemListNode) WalkChildren(v Visitor) {
+ for _, bn := range iln.List {
+ Walk(v, bn)
+ }
+}
// DescriptionNode is a node that contains just textual description.
type DescriptionNode interface {
ItemNode
descriptionNode()
@@ -66,13 +74,10 @@
type InlineNode interface {
Node
inlineNode()
}
-// InlineSlice is a slice of InlineNodes.
-type InlineSlice []InlineNode
-
// Reference is a reference to external or internal material.
type Reference struct {
URL *url.URL
Value string
State RefState
Index: ast/attr.go
==================================================================
--- ast/attr.go
+++ ast/attr.go
@@ -18,10 +18,13 @@
// Attributes store additional information about some node types.
type Attributes struct {
Attrs map[string]string
}
+// IsEmpty returns true if there are no attributes.
+func (a *Attributes) IsEmpty() bool { return a == nil || len(a.Attrs) == 0 }
+
// HasDefault returns true, if the default attribute "-" has been set.
func (a *Attributes) HasDefault() bool {
if a != nil {
_, ok := a.Attrs["-"]
return ok
@@ -77,10 +80,13 @@
// AddClass adds a value to the class attribute.
func (a *Attributes) AddClass(class string) *Attributes {
if a == nil {
return &Attributes{map[string]string{"class": class}}
}
+ if a.Attrs == nil {
+ a.Attrs = make(map[string]string)
+ }
classes := a.GetClasses()
for _, cls := range classes {
if cls == class {
return a
}
Index: ast/block.go
==================================================================
--- ast/block.go
+++ ast/block.go
@@ -11,23 +11,40 @@
// Package ast provides the abstract syntax tree.
package ast
// Definition of Block nodes.
+// BlockListNode is a list of BlockNodes.
+type BlockListNode struct {
+ List []BlockNode
+}
+
+// WalkChildren walks down to the descriptions.
+func (bln *BlockListNode) WalkChildren(v Visitor) {
+ for _, bn := range bln.List {
+ Walk(v, bn)
+ }
+}
+
+//--------------------------------------------------------------------------
+
// ParaNode contains just a sequence of inline elements.
// Another name is "paragraph".
type ParaNode struct {
- Inlines InlineSlice
+ Inlines *InlineListNode
}
-func (pn *ParaNode) blockNode() { /* Just a marker */ }
-func (pn *ParaNode) itemNode() { /* Just a marker */ }
-func (pn *ParaNode) descriptionNode() { /* Just a marker */ }
+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{Inlines: &InlineListNode{}} }
// WalkChildren walks down the inline elements.
func (pn *ParaNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, pn.Inlines)
+ Walk(v, pn.Inlines)
}
//--------------------------------------------------------------------------
// VerbatimNode contains lines of uninterpreted text
@@ -46,24 +63,24 @@
VerbatimProg // Program code.
VerbatimComment // Block comment
VerbatimHTML // Block HTML, e.g. for Markdown
)
-func (vn *VerbatimNode) blockNode() { /* Just a marker */ }
-func (vn *VerbatimNode) itemNode() { /* Just a marker */ }
+func (*VerbatimNode) blockNode() { /* Just a marker */ }
+func (*VerbatimNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (vn *VerbatimNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*VerbatimNode) WalkChildren(Visitor) { /* No children*/ }
//--------------------------------------------------------------------------
// RegionNode encapsulates a region of block nodes.
type RegionNode struct {
Kind RegionKind
Attrs *Attributes
- Blocks BlockSlice
- Inlines InlineSlice // Additional text at the end of the region
+ Blocks *BlockListNode
+ Inlines *InlineListNode // Optional text at the end of the region
}
// RegionKind specifies the actual region type.
type RegionKind uint8
@@ -73,49 +90,52 @@
RegionSpan // Just a span of blocks
RegionQuote // A longer quotation
RegionVerse // Line breaks matter
)
-func (rn *RegionNode) blockNode() { /* Just a marker */ }
-func (rn *RegionNode) itemNode() { /* Just a marker */ }
+func (*RegionNode) blockNode() { /* Just a marker */ }
+func (*RegionNode) itemNode() { /* Just a marker */ }
// WalkChildren walks down the blocks and the text.
func (rn *RegionNode) WalkChildren(v Visitor) {
- WalkBlockSlice(v, rn.Blocks)
- WalkInlineSlice(v, rn.Inlines)
+ Walk(v, rn.Blocks)
+ if iln := rn.Inlines; iln != nil {
+ Walk(v, iln)
+ }
}
//--------------------------------------------------------------------------
// HeadingNode stores the heading text and level.
type HeadingNode struct {
- Level int
- Inlines InlineSlice // Heading text, possibly formatted
- Slug string // Heading text, suitable to be used as an URL fragment
- Attrs *Attributes
+ Level int
+ Inlines *InlineListNode // Heading text, possibly formatted
+ Slug string // Heading text, normalized
+ Fragment string // Heading text, suitable to be used as an unique URL fragment
+ Attrs *Attributes
}
-func (hn *HeadingNode) blockNode() { /* Just a marker */ }
-func (hn *HeadingNode) itemNode() { /* Just a marker */ }
+func (*HeadingNode) blockNode() { /* Just a marker */ }
+func (*HeadingNode) itemNode() { /* Just a marker */ }
// WalkChildren walks the heading text.
func (hn *HeadingNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, hn.Inlines)
+ Walk(v, hn.Inlines)
}
//--------------------------------------------------------------------------
// HRuleNode specifies a horizontal rule.
type HRuleNode struct {
Attrs *Attributes
}
-func (hn *HRuleNode) blockNode() { /* Just a marker */ }
-func (hn *HRuleNode) itemNode() { /* Just a marker */ }
+func (*HRuleNode) blockNode() { /* Just a marker */ }
+func (*HRuleNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (hn *HRuleNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*HRuleNode) WalkChildren(Visitor) { /* No children*/ }
//--------------------------------------------------------------------------
// NestedListNode specifies a nestable list, either ordered or unordered.
type NestedListNode struct {
@@ -133,12 +153,12 @@
NestedListOrdered // Ordered list.
NestedListUnordered // Unordered list.
NestedListQuote // Quote list.
)
-func (ln *NestedListNode) blockNode() { /* Just a marker */ }
-func (ln *NestedListNode) itemNode() { /* Just a marker */ }
+func (*NestedListNode) blockNode() { /* Just a marker */ }
+func (*NestedListNode) itemNode() { /* Just a marker */ }
// WalkChildren walks down the items.
func (ln *NestedListNode) WalkChildren(v Visitor) {
for _, item := range ln.Items {
WalkItemSlice(v, item)
@@ -152,20 +172,20 @@
Descriptions []Description
}
// Description is one element of a description list.
type Description struct {
- Term InlineSlice
+ Term *InlineListNode
Descriptions []DescriptionSlice
}
-func (dn *DescriptionListNode) blockNode() {}
+func (*DescriptionListNode) blockNode() { /* Just a marker */ }
// WalkChildren walks down to the descriptions.
func (dn *DescriptionListNode) WalkChildren(v Visitor) {
for _, desc := range dn.Descriptions {
- WalkInlineSlice(v, desc.Term)
+ Walk(v, desc.Term)
for _, dns := range desc.Descriptions {
WalkDescriptionSlice(v, dns)
}
}
}
@@ -179,12 +199,12 @@
Rows []TableRow // The slice of cell rows
}
// TableCell contains the data for one table cell
type TableCell struct {
- Align Alignment // Cell alignment
- Inlines InlineSlice // Cell content
+ Align Alignment // Cell alignment
+ Inlines *InlineListNode // Cell content
}
// TableRow is a slice of cells.
type TableRow []*TableCell
@@ -199,20 +219,20 @@
AlignLeft // Left alignment
AlignCenter // Center the content
AlignRight // Right alignment
)
-func (tn *TableNode) blockNode() { /* Just a marker */ }
+func (*TableNode) blockNode() { /* Just a marker */ }
// WalkChildren walks down to the cells.
func (tn *TableNode) WalkChildren(v Visitor) {
for _, cell := range tn.Header {
- WalkInlineSlice(v, cell.Inlines)
+ Walk(v, cell.Inlines)
}
for _, row := range tn.Rows {
for _, cell := range row {
- WalkInlineSlice(v, cell.Inlines)
+ Walk(v, cell.Inlines)
}
}
}
//--------------------------------------------------------------------------
@@ -223,9 +243,9 @@
Title string
Syntax string
Blob []byte
}
-func (bn *BLOBNode) blockNode() { /* Just a marker */ }
+func (*BLOBNode) blockNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (bn *BLOBNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*BLOBNode) WalkChildren(Visitor) { /* No children*/ }
Index: ast/inline.go
==================================================================
--- ast/inline.go
+++ ast/inline.go
@@ -11,143 +11,191 @@
// Package ast provides the abstract syntax tree.
package ast
// Definitions of inline nodes.
+// InlineListNode is a list of BlockNodes.
+type InlineListNode struct {
+ List []InlineNode
+}
+
+func (*InlineListNode) inlineNode() { /* Just a marker */ }
+
+// CreateInlineListNode make a new inline list node from nodes
+func CreateInlineListNode(nodes ...InlineNode) *InlineListNode {
+ return &InlineListNode{List: nodes}
+}
+
+// CreateInlineListNodeFromWords makes a new inline list from words,
+// that will be space-separated.
+func CreateInlineListNodeFromWords(words ...string) *InlineListNode {
+ inl := make([]InlineNode, 0, 2*len(words)-1)
+ for i, word := range words {
+ if i > 0 {
+ inl = append(inl, &SpaceNode{Lexeme: " "})
+ }
+ inl = append(inl, &TextNode{Text: word})
+ }
+ return &InlineListNode{List: inl}
+}
+
+// WalkChildren walks down to the descriptions.
+func (iln *InlineListNode) WalkChildren(v Visitor) {
+ for _, bn := range iln.List {
+ Walk(v, bn)
+ }
+}
+
+// IsEmpty returns true if the list has no elements.
+func (iln *InlineListNode) IsEmpty() bool { return iln == nil || len(iln.List) == 0 }
+
+// Append inline node(s) to the list.
+func (iln *InlineListNode) Append(in ...InlineNode) {
+ iln.List = append(iln.List, in...)
+}
+
+// --------------------------------------------------------------------------
+
// TextNode just contains some text.
type TextNode struct {
Text string // The text itself.
}
-func (tn *TextNode) inlineNode() { /* Just a marker */ }
+func (*TextNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (tn *TextNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*TextNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// TagNode contains a tag.
type TagNode struct {
Tag string // The text itself.
}
-func (tn *TagNode) inlineNode() { /* Just a marker */ }
+func (*TagNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (tn *TagNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*TagNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// SpaceNode tracks inter-word space characters.
type SpaceNode struct {
Lexeme string
}
-func (sn *SpaceNode) inlineNode() { /* Just a marker */ }
+func (*SpaceNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (sn *SpaceNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*SpaceNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// BreakNode signals a new line that must / should be interpreted as a new line break.
type BreakNode struct {
Hard bool // Hard line break?
}
-func (bn *BreakNode) inlineNode() { /* Just a marker */ }
+func (*BreakNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (bn *BreakNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*BreakNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// LinkNode contains the specified link.
type LinkNode struct {
Ref *Reference
- Inlines InlineSlice // The text associated with the link.
- OnlyRef bool // True if no text was specified.
- Attrs *Attributes // Optional attributes
+ Inlines *InlineListNode // The text associated with the link.
+ OnlyRef bool // True if no text was specified.
+ Attrs *Attributes // Optional attributes
}
-func (ln *LinkNode) inlineNode() { /* Just a marker */ }
+func (*LinkNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the link text.
func (ln *LinkNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, ln.Inlines)
+ if iln := ln.Inlines; iln != nil {
+ Walk(v, iln)
+ }
}
// --------------------------------------------------------------------------
-// ImageNode contains the specified image reference.
-type ImageNode struct {
- Ref *Reference // Reference to image
- Blob []byte // BLOB data of the image, as an alternative to Ref.
- Syntax string // Syntax of Blob
- Inlines InlineSlice // The text associated with the image.
- Attrs *Attributes // Optional attributes
+// EmbedNode contains the specified embedded material.
+type EmbedNode struct {
+ Material MaterialNode // The material to be embedded
+ Inlines *InlineListNode // Optional text associated with the image.
+ Attrs *Attributes // Optional attributes
}
-func (in *ImageNode) inlineNode() { /* Just a marker */ }
+func (*EmbedNode) inlineNode() { /* Just a marker */ }
-// WalkChildren walks to the image text.
-func (in *ImageNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, in.Inlines)
+// WalkChildren walks to the text that describes the embedded material.
+func (en *EmbedNode) WalkChildren(v Visitor) {
+ if iln := en.Inlines; iln != nil {
+ Walk(v, iln)
+ }
}
// --------------------------------------------------------------------------
// CiteNode contains the specified citation.
type CiteNode struct {
- Key string // The citation key
- Inlines InlineSlice // The text associated with the citation.
- Attrs *Attributes // Optional attributes
+ Key string // The citation key
+ Inlines *InlineListNode // Optional text associated with the citation.
+ Attrs *Attributes // Optional attributes
}
-func (cn *CiteNode) inlineNode() { /* Just a marker */ }
+func (*CiteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the cite text.
func (cn *CiteNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, cn.Inlines)
+ if iln := cn.Inlines; iln != nil {
+ Walk(v, iln)
+ }
}
// --------------------------------------------------------------------------
// 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 {
- Text string
+ Text string
+ Slug string // Slugified form of Text
+ Fragment string // Unique form of Slug
}
-func (mn *MarkNode) inlineNode() { /* Just a marker */ }
+func (*MarkNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (mn *MarkNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*MarkNode) WalkChildren(Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// FootnoteNode contains the specified footnote.
type FootnoteNode struct {
- Inlines InlineSlice // The footnote text.
- Attrs *Attributes // Optional attributes
+ Inlines *InlineListNode // The footnote text.
+ Attrs *Attributes // Optional attributes
}
-func (fn *FootnoteNode) inlineNode() { /* Just a marker */ }
+func (*FootnoteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the footnote text.
func (fn *FootnoteNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, fn.Inlines)
+ Walk(v, fn.Inlines)
}
// --------------------------------------------------------------------------
// FormatNode specifies some inline formatting.
type FormatNode struct {
Kind FormatKind
Attrs *Attributes // Optional attributes.
- Inlines InlineSlice
+ Inlines *InlineListNode
}
// FormatKind specifies the format that is applied to the inline nodes.
type FormatKind uint8
@@ -169,15 +217,15 @@
FormatSmall // Smaller text.
FormatSpan // Generic inline container.
FormatMonospace // Monospaced text.
)
-func (fn *FormatNode) inlineNode() { /* Just a marker */ }
+func (*FormatNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the formatted text.
func (fn *FormatNode) WalkChildren(v Visitor) {
- WalkInlineSlice(v, fn.Inlines)
+ Walk(v, fn.Inlines)
}
// --------------------------------------------------------------------------
// LiteralNode specifies some uninterpreted text.
@@ -198,9 +246,9 @@
LiteralOutput // Sample output.
LiteralComment // Inline comment
LiteralHTML // Inline HTML, e.g. for Markdown
)
-func (ln *LiteralNode) inlineNode() { /* Just a marker */ }
+func (*LiteralNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (ln *LiteralNode) WalkChildren(v Visitor) { /* No children*/ }
+func (*LiteralNode) WalkChildren(Visitor) { /* No children*/ }
ADDED ast/material.go
Index: ast/material.go
==================================================================
--- ast/material.go
+++ ast/material.go
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2021 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 provides the abstract syntax tree.
+package ast
+
+// MaterialNode references the various types of zettel material.
+type MaterialNode interface {
+ Node
+ materialNode()
+}
+
+// --------------------------------------------------------------------------
+
+// ReferenceMaterialNode is material that can be retrieved by using a reference.
+type ReferenceMaterialNode struct {
+ Ref *Reference
+}
+
+func (*ReferenceMaterialNode) materialNode() { /* Just a marker */ }
+
+// WalkChildren does nothing.
+func (*ReferenceMaterialNode) WalkChildren(Visitor) { /* No children*/ }
+
+// --------------------------------------------------------------------------
+
+// BLOBMaterialNode represents itself.
+type BLOBMaterialNode struct {
+ Blob []byte // BLOB data itself.
+ Syntax string // Syntax of Blob
+}
+
+func (*BLOBMaterialNode) materialNode() { /* Just a marker */ }
+
+// WalkChildren does nothing.
+func (*BLOBMaterialNode) WalkChildren(Visitor) { /* No children*/ }
Index: ast/walk.go
==================================================================
--- ast/walk.go
+++ ast/walk.go
@@ -23,24 +23,10 @@
}
node.WalkChildren(v)
v.Visit(nil)
}
-// WalkBlockSlice traverse a block slice.
-func WalkBlockSlice(v Visitor, bns BlockSlice) {
- for _, bn := range bns {
- Walk(v, bn)
- }
-}
-
-// WalkInlineSlice traverses an inline slice.
-func WalkInlineSlice(v Visitor, ins InlineSlice) {
- for _, in := range ins {
- Walk(v, in)
- }
-}
-
// WalkItemSlice traverses an item slice.
func WalkItemSlice(v Visitor, ins ItemSlice) {
for _, in := range ins {
Walk(v, in)
}
Index: auth/policy/policy_test.go
==================================================================
--- auth/policy/policy_test.go
+++ auth/policy/policy_test.go
@@ -43,12 +43,12 @@
}
pol := newPolicy(authzManager, &authConfig{ts.expert})
name := fmt.Sprintf("readonly=%v/withauth=%v/expert=%v",
ts.readonly, ts.withAuth, ts.expert)
t.Run(name, func(tt *testing.T) {
- testCreate(tt, pol, ts.withAuth, ts.readonly, ts.expert)
- testRead(tt, pol, ts.withAuth, ts.readonly, ts.expert)
+ testCreate(tt, pol, ts.withAuth, ts.readonly)
+ testRead(tt, pol, ts.withAuth, ts.expert)
testWrite(tt, pol, ts.withAuth, ts.readonly, ts.expert)
testRename(tt, pol, ts.withAuth, ts.readonly, ts.expert)
testDelete(tt, pol, ts.withAuth, ts.readonly, ts.expert)
})
}
@@ -92,11 +92,11 @@
return meta.GetVisibility(vis)
}
return meta.VisibilityLogin
}
-func testCreate(t *testing.T, pol auth.Policy, withAuth, readonly, isExpert bool) {
+func testCreate(t *testing.T, pol auth.Policy, withAuth, readonly bool) {
t.Helper()
anonUser := newAnon()
creator := newCreator()
reader := newReader()
writer := newWriter()
@@ -139,11 +139,11 @@
}
})
}
}
-func testRead(t *testing.T, pol auth.Policy, withAuth, readonly, expert bool) {
+func testRead(t *testing.T, pol auth.Policy, withAuth, expert bool) {
t.Helper()
anonUser := newAnon()
creator := newCreator()
reader := newReader()
writer := newWriter()
Index: box/box.go
==================================================================
--- box/box.go
+++ box/box.go
@@ -41,13 +41,10 @@
GetZettel(ctx context.Context, zid id.Zid) (domain.Zettel, error)
// GetMeta retrieves just the meta data of a specific zettel.
GetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error)
- // FetchZids returns the set of all zettel identifer managed by the box.
- FetchZids(ctx context.Context) (id.Set, error)
-
// CanUpdateZettel returns true, if box could possibly update the given zettel.
CanUpdateZettel(ctx context.Context, zettel domain.Zettel) bool
// UpdateZettel updates an existing zettel.
UpdateZettel(ctx context.Context, zettel domain.Zettel) error
@@ -62,17 +59,26 @@
CanDeleteZettel(ctx context.Context, zid id.Zid) bool
// DeleteZettel removes the zettel from the box.
DeleteZettel(ctx context.Context, zid id.Zid) error
}
+
+// ZidFunc is a function that processes identifier of a zettel.
+type ZidFunc func(id.Zid)
+
+// MetaFunc is a function that processes metadata of a zettel.
+type MetaFunc func(*meta.Meta)
// ManagedBox is the interface of managed boxes.
type ManagedBox interface {
BaseBox
- // SelectMeta returns all zettel meta data that match the selection criteria.
- SelectMeta(ctx context.Context, match search.MetaMatchFunc) ([]*meta.Meta, error)
+ // Apply identifier of every zettel to the given function.
+ ApplyZid(context.Context, ZidFunc) error
+
+ // Apply metadata of every zettel to the given function.
+ ApplyMeta(context.Context, MetaFunc) error
// ReadStats populates st with box statistics
ReadStats(st *ManagedBoxStats)
}
@@ -96,10 +102,13 @@
}
// Box is to be used outside the box package and its descendants.
type Box interface {
BaseBox
+
+ // FetchZids returns the set of all zettel identifer managed by the box.
+ FetchZids(ctx context.Context) (id.Set, error)
// SelectMeta returns a list of metadata that comply to the given selection criteria.
SelectMeta(ctx context.Context, s *search.Search) ([]*meta.Meta, error)
// GetAllZettel retrieves a specific zettel from all managed boxes.
Index: box/compbox/compbox.go
==================================================================
--- box/compbox/compbox.go
+++ box/compbox/compbox.go
@@ -18,11 +18,10 @@
"zettelstore.de/z/box"
"zettelstore.de/z/box/manager"
"zettelstore.de/z/domain"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
- "zettelstore.de/z/search"
)
func init() {
manager.Register(
" comp",
@@ -55,20 +54,19 @@
}
// Setup remembers important values.
func Setup(cfg *meta.Meta) { myConfig = cfg.Clone() }
-func (pp *compBox) Location() string { return "" }
+func (*compBox) Location() string { return "" }
-func (pp *compBox) CanCreateZettel(ctx context.Context) bool { return false }
+func (*compBox) CanCreateZettel(context.Context) bool { return false }
-func (pp *compBox) CreateZettel(
- ctx context.Context, zettel domain.Zettel) (id.Zid, error) {
+func (*compBox) CreateZettel(context.Context, domain.Zettel) (id.Zid, error) {
return id.Invalid, box.ErrReadOnly
}
-func (pp *compBox) GetZettel(ctx context.Context, zid id.Zid) (domain.Zettel, error) {
+func (*compBox) GetZettel(_ context.Context, zid id.Zid) (domain.Zettel, error) {
if gen, ok := myZettel[zid]; ok && gen.meta != nil {
if m := gen.meta(zid); m != nil {
updateMeta(m)
if genContent := gen.content; genContent != nil {
return domain.Zettel{
@@ -80,11 +78,11 @@
}
}
return domain.Zettel{}, box.ErrNotFound
}
-func (pp *compBox) GetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error) {
+func (*compBox) GetMeta(_ context.Context, zid id.Zid) (*meta.Meta, error) {
if gen, ok := myZettel[zid]; ok {
if genMeta := gen.meta; genMeta != nil {
if m := genMeta(zid); m != nil {
updateMeta(m)
return m, nil
@@ -92,67 +90,60 @@
}
}
return nil, box.ErrNotFound
}
-func (pp *compBox) FetchZids(ctx context.Context) (id.Set, error) {
- result := id.NewSetCap(len(myZettel))
+func (*compBox) ApplyZid(_ context.Context, handle box.ZidFunc) error {
for zid, gen := range myZettel {
if genMeta := gen.meta; genMeta != nil {
if genMeta(zid) != nil {
- result[zid] = true
+ handle(zid)
}
}
}
- return result, nil
+ return nil
}
-func (pp *compBox) SelectMeta(ctx context.Context, match search.MetaMatchFunc) (res []*meta.Meta, err error) {
+func (pp *compBox) ApplyMeta(ctx context.Context, handle box.MetaFunc) error {
for zid, gen := range myZettel {
if genMeta := gen.meta; genMeta != nil {
if m := genMeta(zid); m != nil {
updateMeta(m)
pp.enricher.Enrich(ctx, m, pp.number)
- if match(m) {
- res = append(res, m)
- }
+ handle(m)
}
}
}
- return res, nil
+ return nil
}
-func (pp *compBox) CanUpdateZettel(ctx context.Context, zettel domain.Zettel) bool {
- return false
-}
-
-func (pp *compBox) UpdateZettel(ctx context.Context, zettel domain.Zettel) error {
- return box.ErrReadOnly
-}
-
-func (pp *compBox) AllowRenameZettel(ctx context.Context, zid id.Zid) bool {
+func (*compBox) CanUpdateZettel(context.Context, domain.Zettel) bool { return false }
+
+func (*compBox) UpdateZettel(context.Context, domain.Zettel) error { return box.ErrReadOnly }
+
+func (*compBox) AllowRenameZettel(_ context.Context, zid id.Zid) bool {
_, ok := myZettel[zid]
return !ok
}
-func (pp *compBox) RenameZettel(ctx context.Context, curZid, newZid id.Zid) error {
+func (*compBox) RenameZettel(_ context.Context, curZid, _ id.Zid) error {
if _, ok := myZettel[curZid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (pp *compBox) CanDeleteZettel(ctx context.Context, zid id.Zid) bool { return false }
+func (*compBox) CanDeleteZettel(context.Context, id.Zid) bool { return false }
-func (pp *compBox) DeleteZettel(ctx context.Context, zid id.Zid) error {
+func (*compBox) DeleteZettel(_ context.Context, zid id.Zid) error {
if _, ok := myZettel[zid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (pp *compBox) ReadStats(st *box.ManagedBoxStats) {
+func (*compBox) ReadStats(st *box.ManagedBoxStats) {
st.ReadOnly = true
st.Zettel = len(myZettel)
}
func updateMeta(m *meta.Meta) {
Index: box/constbox/base.css
==================================================================
--- box/constbox/base.css
+++ box/constbox/base.css
@@ -254,10 +254,13 @@
color:#444;
}
h1+.zs-meta {
margin-top:-1rem;
}
+ nav > details {
+ margin-top:1rem;
+ }
details > summary {
width: 100%;
background-color: #eee;
font-family:sans-serif;
}
Index: box/constbox/base.mustache
==================================================================
--- box/constbox/base.mustache
+++ box/constbox/base.mustache
@@ -24,11 +24,11 @@
{{/UserIsValid}}
{{^UserIsValid}}
Login
{{/UserIsValid}}
{{#UserIsValid}}
-Logout
+Logout
{{/UserIsValid}}
{{/WithAuth}}
{{/WithUser}}
@@ -49,11 +49,11 @@
{{/NewZettelLinks}}
{{/HasNewZettelLinks}}
{{{Content}}}
Index: box/constbox/constbox.go
==================================================================
--- box/constbox/constbox.go
+++ box/constbox/constbox.go
@@ -19,11 +19,10 @@
"zettelstore.de/z/box"
"zettelstore.de/z/box/manager"
"zettelstore.de/z/domain"
"zettelstore.de/z/domain/id"
"zettelstore.de/z/domain/meta"
- "zettelstore.de/z/search"
)
func init() {
manager.Register(
" const",
@@ -36,18 +35,10 @@
})
}
type constHeader map[string]string
-func makeMeta(zid id.Zid, h constHeader) *meta.Meta {
- m := meta.New(zid)
- for k, v := range h {
- m.Set(k, v)
- }
- return m
-}
-
type constZettel struct {
header constHeader
content domain.Content
}
@@ -55,75 +46,66 @@
number int
zettel map[id.Zid]constZettel
enricher box.Enricher
}
-func (cp *constBox) Location() string {
- return "const:"
-}
+func (*constBox) Location() string { return "const:" }
+
+func (*constBox) CanCreateZettel(context.Context) bool { return false }
-func (cp *constBox) CanCreateZettel(ctx context.Context) bool { return false }
-
-func (cp *constBox) CreateZettel(ctx context.Context, zettel domain.Zettel) (id.Zid, error) {
+func (*constBox) CreateZettel(context.Context, domain.Zettel) (id.Zid, error) {
return id.Invalid, box.ErrReadOnly
}
-func (cp *constBox) GetZettel(ctx context.Context, zid id.Zid) (domain.Zettel, error) {
+func (cp *constBox) GetZettel(_ context.Context, zid id.Zid) (domain.Zettel, error) {
if z, ok := cp.zettel[zid]; ok {
- return domain.Zettel{Meta: makeMeta(zid, z.header), Content: z.content}, nil
+ return domain.Zettel{Meta: meta.NewWithData(zid, z.header), Content: z.content}, nil
}
return domain.Zettel{}, box.ErrNotFound
}
-func (cp *constBox) GetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error) {
- if z, ok := cp.zettel[zid]; ok {
- return makeMeta(zid, z.header), nil
- }
- return nil, box.ErrNotFound
-}
-
-func (cp *constBox) FetchZids(ctx context.Context) (id.Set, error) {
- result := id.NewSetCap(len(cp.zettel))
- for zid := range cp.zettel {
- result[zid] = true
- }
- return result, nil
-}
-
-func (cp *constBox) SelectMeta(ctx context.Context, match search.MetaMatchFunc) (res []*meta.Meta, err error) {
- for zid, zettel := range cp.zettel {
- m := makeMeta(zid, zettel.header)
- cp.enricher.Enrich(ctx, m, cp.number)
- if match(m) {
- res = append(res, m)
- }
- }
- return res, nil
-}
-
-func (cp *constBox) CanUpdateZettel(ctx context.Context, zettel domain.Zettel) bool {
- return false
-}
-
-func (cp *constBox) UpdateZettel(ctx context.Context, zettel domain.Zettel) error {
- return box.ErrReadOnly
-}
-
-func (cp *constBox) AllowRenameZettel(ctx context.Context, zid id.Zid) bool {
+func (cp *constBox) GetMeta(_ context.Context, zid id.Zid) (*meta.Meta, error) {
+ if z, ok := cp.zettel[zid]; ok {
+ return meta.NewWithData(zid, z.header), nil
+ }
+ return nil, box.ErrNotFound
+}
+
+func (cp *constBox) ApplyZid(_ context.Context, handle box.ZidFunc) error {
+ for zid := range cp.zettel {
+ handle(zid)
+ }
+ return nil
+}
+
+func (cp *constBox) ApplyMeta(ctx context.Context, handle box.MetaFunc) error {
+ for zid, zettel := range cp.zettel {
+ m := meta.NewWithData(zid, zettel.header)
+ cp.enricher.Enrich(ctx, m, cp.number)
+ handle(m)
+ }
+ return nil
+}
+
+func (*constBox) CanUpdateZettel(context.Context, domain.Zettel) bool { return false }
+
+func (*constBox) UpdateZettel(context.Context, domain.Zettel) error { return box.ErrReadOnly }
+
+func (cp *constBox) AllowRenameZettel(_ context.Context, zid id.Zid) bool {
_, ok := cp.zettel[zid]
return !ok
}
-func (cp *constBox) RenameZettel(ctx context.Context, curZid, newZid id.Zid) error {
+func (cp *constBox) RenameZettel(_ context.Context, curZid, _ id.Zid) error {
if _, ok := cp.zettel[curZid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (cp *constBox) CanDeleteZettel(ctx context.Context, zid id.Zid) bool { return false }
+func (*constBox) CanDeleteZettel(context.Context, id.Zid) bool { return false }
-func (cp *constBox) DeleteZettel(ctx context.Context, zid id.Zid) error {
+func (cp *constBox) DeleteZettel(_ context.Context, zid id.Zid) error {
if _, ok := cp.zettel[zid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
Index: box/constbox/home.zettel
==================================================================
--- box/constbox/home.zettel
+++ box/constbox/home.zettel
@@ -3,18 +3,17 @@
You will find the lastest information about Zettelstore at [[https://zettelstore.de]].
Check that website regulary for [[upgrades|https://zettelstore.de/home/doc/trunk/www/download.wiki]] to the latest version.
You should consult the [[change log|https://zettelstore.de/home/doc/trunk/www/changes.wiki]] before upgrading.
Sometimes, you have to edit some of your Zettelstore-related zettel before upgrading.
Since Zettelstore is currently in a development state, every upgrade might fix some of your problems.
-To check for versions, there is a zettel with the [[current version|00000000000001]] of your Zettelstore.
If you have problems concerning Zettelstore,
do not hesitate to get in [[contact with the main developer|mailto:ds@zettelstore.de]].
=== Reporting errors
If you have encountered an error, please include the content of the following zettel in your mail (if possible):
-* [[Zettelstore Version|00000000000001]]
+* [[Zettelstore Version|00000000000001]]: {{00000000000001}}
* [[Zettelstore Operating System|00000000000003]]
* [[Zettelstore Startup Configuration|00000000000096]]
* [[Zettelstore Runtime Configuration|00000000000100]]
Additionally, you have to describe, what you have done before that error occurs
Index: box/constbox/info.mustache
==================================================================
--- box/constbox/info.mustache
+++ box/constbox/info.mustache
@@ -29,20 +29,31 @@
{{.}}
{{/ExtLinks}}
{{/HasExtLinks}}
{{/HasLinks}}
-Parts and format
+Parts and encodings
+
+{{#EvalMatrix}}
+
+{{Header}} |
+{{#Elements}}{{Text}} |
+{{/Elements}}
+
+{{/EvalMatrix}}
+
+Parsed (not evaluated)
-{{#Matrix}}
+{{#ParseMatrix}}
-{{#Elements}}{{#HasURL}}{{Text}} | {{/HasURL}}{{^HasURL}}{{Text}} | {{/HasURL}}
+{{Header}} |
+{{#Elements}}{{Text}} |
{{/Elements}}
-{{/Matrix}}
+{{/ParseMatrix}}
{{#HasShadowLinks}}
Shadowed Boxes
{{#ShadowLinks}}- {{.}}
{{/ShadowLinks}}
{{/HasShadowLinks}}
{{#Endnotes}}{{{Endnotes}}}{{/Endnotes}}
Index: box/constbox/login.mustache
==================================================================
--- box/constbox/login.mustache
+++ box/constbox/login.mustache
@@ -3,11 +3,11 @@
{{Title}}
{{#Retry}}
Wrong user name / password. Try again.
{{/Retry}}
-