Index: VERSION
==================================================================
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
-0.0.15
+0.0.14
Index: api/api.go
==================================================================
--- api/api.go
+++ api/api.go
@@ -18,41 +18,45 @@
Expires int `json:"expires_in"`
}
// ZidJSON contains the identifier data of a zettel.
type ZidJSON struct {
- ID string `json:"id"`
+ ID string `json:"id"`
+ URL string `json:"url"`
}
// 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"`
- 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"`
+ 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"`
Cites []string `json:"cites,omitempty"`
}
// ZettelDataJSON contains all data for a zettel.
type ZettelDataJSON struct {
@@ -62,18 +66,19 @@
}
// 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 []ZidMetaJSON `json:"list"`
+ List []ZettelJSON `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,11 +9,13 @@
//-----------------------------------------------------------------------------
// 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
@@ -23,55 +25,54 @@
HeaderLocation = "Location"
)
// Values for HTTP query parameter.
const (
- QueryKeyDepth = "depth"
- QueryKeyDir = "dir"
- QueryKeyEncoding = "_enc"
- QueryKeyLimit = "_limit"
- QueryKeyNegate = "_negate"
- QueryKeyOffset = "_offset"
- QueryKeyOrder = "_order"
- QueryKeyPart = "_part"
- QueryKeySearch = "_s"
- QueryKeySort = "_sort"
+ QueryKeyDepth = "depth"
+ QueryKeyDir = "dir"
+ QueryKeyFormat = "_format"
+ QueryKeyLimit = "limit"
+ QueryKeyPart = "_part"
)
// Supported dir values.
const (
DirBackward = "backward"
DirForward = "forward"
)
-// 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 {
+// 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 {
return e
}
return EncoderUnknown
}
@@ -81,24 +82,27 @@
// 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 := mapEnumEncoding[e]; ok {
+ if f, ok := encoderFormat[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,15 +20,16 @@
)
// 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 *BlockListNode // Zettel abstract syntax tree is a sequence of block nodes.
+ Ast BlockSlice // Zettel abstract syntax tree is a sequence of block nodes.
}
// Node is the interface, all nodes must implement.
type Node interface {
WalkChildren(v Visitor)
@@ -37,10 +38,13 @@
// BlockNode is the interface that all block nodes must implement.
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()
@@ -47,22 +51,10 @@
}
// 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()
}
@@ -73,10 +65,13 @@
// InlineNode is the interface that all inline nodes must implement.
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
Index: ast/attr.go
==================================================================
--- ast/attr.go
+++ ast/attr.go
@@ -18,13 +18,10 @@
// 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
@@ -80,13 +77,10 @@
// 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,40 +11,23 @@
// 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 *InlineListNode
+ 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{Inlines: &InlineListNode{}} }
+func (pn *ParaNode) blockNode() { /* Just a marker */ }
+func (pn *ParaNode) itemNode() { /* Just a marker */ }
+func (pn *ParaNode) descriptionNode() { /* Just a marker */ }
// WalkChildren walks down the inline elements.
func (pn *ParaNode) WalkChildren(v Visitor) {
- Walk(v, pn.Inlines)
+ WalkInlineSlice(v, pn.Inlines)
}
//--------------------------------------------------------------------------
// VerbatimNode contains lines of uninterpreted text
@@ -63,24 +46,24 @@
VerbatimProg // Program code.
VerbatimComment // Block comment
VerbatimHTML // Block HTML, e.g. for Markdown
)
-func (*VerbatimNode) blockNode() { /* Just a marker */ }
-func (*VerbatimNode) itemNode() { /* Just a marker */ }
+func (vn *VerbatimNode) blockNode() { /* Just a marker */ }
+func (vn *VerbatimNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*VerbatimNode) WalkChildren(Visitor) { /* No children*/ }
+func (vn *VerbatimNode) WalkChildren(v Visitor) { /* No children*/ }
//--------------------------------------------------------------------------
// RegionNode encapsulates a region of block nodes.
type RegionNode struct {
Kind RegionKind
Attrs *Attributes
- Blocks *BlockListNode
- Inlines *InlineListNode // Optional text at the end of the region
+ Blocks BlockSlice
+ Inlines InlineSlice // Additional text at the end of the region
}
// RegionKind specifies the actual region type.
type RegionKind uint8
@@ -90,52 +73,49 @@
RegionSpan // Just a span of blocks
RegionQuote // A longer quotation
RegionVerse // Line breaks matter
)
-func (*RegionNode) blockNode() { /* Just a marker */ }
-func (*RegionNode) itemNode() { /* Just a marker */ }
+func (rn *RegionNode) blockNode() { /* Just a marker */ }
+func (rn *RegionNode) itemNode() { /* Just a marker */ }
// WalkChildren walks down the blocks and the text.
func (rn *RegionNode) WalkChildren(v Visitor) {
- Walk(v, rn.Blocks)
- if iln := rn.Inlines; iln != nil {
- Walk(v, iln)
- }
+ WalkBlockSlice(v, rn.Blocks)
+ WalkInlineSlice(v, rn.Inlines)
}
//--------------------------------------------------------------------------
// HeadingNode stores the heading text and level.
type HeadingNode struct {
- 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
+ Level int
+ Inlines InlineSlice // Heading text, possibly formatted
+ Slug string // Heading text, suitable to be used as an URL fragment
+ Attrs *Attributes
}
-func (*HeadingNode) blockNode() { /* Just a marker */ }
-func (*HeadingNode) itemNode() { /* Just a marker */ }
+func (hn *HeadingNode) blockNode() { /* Just a marker */ }
+func (hn *HeadingNode) itemNode() { /* Just a marker */ }
// WalkChildren walks the heading text.
func (hn *HeadingNode) WalkChildren(v Visitor) {
- Walk(v, hn.Inlines)
+ WalkInlineSlice(v, hn.Inlines)
}
//--------------------------------------------------------------------------
// HRuleNode specifies a horizontal rule.
type HRuleNode struct {
Attrs *Attributes
}
-func (*HRuleNode) blockNode() { /* Just a marker */ }
-func (*HRuleNode) itemNode() { /* Just a marker */ }
+func (hn *HRuleNode) blockNode() { /* Just a marker */ }
+func (hn *HRuleNode) itemNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*HRuleNode) WalkChildren(Visitor) { /* No children*/ }
+func (hn *HRuleNode) WalkChildren(v Visitor) { /* No children*/ }
//--------------------------------------------------------------------------
// NestedListNode specifies a nestable list, either ordered or unordered.
type NestedListNode struct {
@@ -153,12 +133,12 @@
NestedListOrdered // Ordered list.
NestedListUnordered // Unordered list.
NestedListQuote // Quote list.
)
-func (*NestedListNode) blockNode() { /* Just a marker */ }
-func (*NestedListNode) itemNode() { /* Just a marker */ }
+func (ln *NestedListNode) blockNode() { /* Just a marker */ }
+func (ln *NestedListNode) itemNode() { /* Just a marker */ }
// WalkChildren walks down the items.
func (ln *NestedListNode) WalkChildren(v Visitor) {
for _, item := range ln.Items {
WalkItemSlice(v, item)
@@ -172,20 +152,20 @@
Descriptions []Description
}
// Description is one element of a description list.
type Description struct {
- Term *InlineListNode
+ Term InlineSlice
Descriptions []DescriptionSlice
}
-func (*DescriptionListNode) blockNode() { /* Just a marker */ }
+func (dn *DescriptionListNode) blockNode() {}
// WalkChildren walks down to the descriptions.
func (dn *DescriptionListNode) WalkChildren(v Visitor) {
for _, desc := range dn.Descriptions {
- Walk(v, desc.Term)
+ WalkInlineSlice(v, desc.Term)
for _, dns := range desc.Descriptions {
WalkDescriptionSlice(v, dns)
}
}
}
@@ -199,12 +179,12 @@
Rows []TableRow // The slice of cell rows
}
// TableCell contains the data for one table cell
type TableCell struct {
- Align Alignment // Cell alignment
- Inlines *InlineListNode // Cell content
+ Align Alignment // Cell alignment
+ Inlines InlineSlice // Cell content
}
// TableRow is a slice of cells.
type TableRow []*TableCell
@@ -219,20 +199,20 @@
AlignLeft // Left alignment
AlignCenter // Center the content
AlignRight // Right alignment
)
-func (*TableNode) blockNode() { /* Just a marker */ }
+func (tn *TableNode) blockNode() { /* Just a marker */ }
// WalkChildren walks down to the cells.
func (tn *TableNode) WalkChildren(v Visitor) {
for _, cell := range tn.Header {
- Walk(v, cell.Inlines)
+ WalkInlineSlice(v, cell.Inlines)
}
for _, row := range tn.Rows {
for _, cell := range row {
- Walk(v, cell.Inlines)
+ WalkInlineSlice(v, cell.Inlines)
}
}
}
//--------------------------------------------------------------------------
@@ -243,9 +223,9 @@
Title string
Syntax string
Blob []byte
}
-func (*BLOBNode) blockNode() { /* Just a marker */ }
+func (bn *BLOBNode) blockNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*BLOBNode) WalkChildren(Visitor) { /* No children*/ }
+func (bn *BLOBNode) WalkChildren(v Visitor) { /* No children*/ }
Index: ast/inline.go
==================================================================
--- ast/inline.go
+++ ast/inline.go
@@ -11,191 +11,143 @@
// 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 (*TextNode) inlineNode() { /* Just a marker */ }
+func (tn *TextNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*TextNode) WalkChildren(Visitor) { /* No children*/ }
+func (tn *TextNode) WalkChildren(v Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// TagNode contains a tag.
type TagNode struct {
Tag string // The text itself.
}
-func (*TagNode) inlineNode() { /* Just a marker */ }
+func (tn *TagNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*TagNode) WalkChildren(Visitor) { /* No children*/ }
+func (tn *TagNode) WalkChildren(v Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// SpaceNode tracks inter-word space characters.
type SpaceNode struct {
Lexeme string
}
-func (*SpaceNode) inlineNode() { /* Just a marker */ }
+func (sn *SpaceNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*SpaceNode) WalkChildren(Visitor) { /* No children*/ }
+func (sn *SpaceNode) WalkChildren(v 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 (*BreakNode) inlineNode() { /* Just a marker */ }
+func (bn *BreakNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*BreakNode) WalkChildren(Visitor) { /* No children*/ }
+func (bn *BreakNode) WalkChildren(v Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// LinkNode contains the specified link.
type LinkNode struct {
Ref *Reference
- Inlines *InlineListNode // The text associated with the link.
- OnlyRef bool // True if no text was specified.
- Attrs *Attributes // Optional attributes
+ Inlines InlineSlice // The text associated with the link.
+ OnlyRef bool // True if no text was specified.
+ Attrs *Attributes // Optional attributes
}
-func (*LinkNode) inlineNode() { /* Just a marker */ }
+func (ln *LinkNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the link text.
func (ln *LinkNode) WalkChildren(v Visitor) {
- if iln := ln.Inlines; iln != nil {
- Walk(v, iln)
- }
+ WalkInlineSlice(v, ln.Inlines)
}
// --------------------------------------------------------------------------
-// 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
+// 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
}
-func (*EmbedNode) inlineNode() { /* Just a marker */ }
+func (in *ImageNode) inlineNode() { /* Just a marker */ }
-// 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)
- }
+// WalkChildren walks to the image text.
+func (in *ImageNode) WalkChildren(v Visitor) {
+ WalkInlineSlice(v, in.Inlines)
}
// --------------------------------------------------------------------------
// CiteNode contains the specified citation.
type CiteNode struct {
- Key string // The citation key
- Inlines *InlineListNode // Optional text associated with the citation.
- Attrs *Attributes // Optional attributes
+ Key string // The citation key
+ Inlines InlineSlice // The text associated with the citation.
+ Attrs *Attributes // Optional attributes
}
-func (*CiteNode) inlineNode() { /* Just a marker */ }
+func (cn *CiteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the cite text.
func (cn *CiteNode) WalkChildren(v Visitor) {
- if iln := cn.Inlines; iln != nil {
- Walk(v, iln)
- }
+ WalkInlineSlice(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 {
- Text string
- Slug string // Slugified form of Text
- Fragment string // Unique form of Slug
+ Text string
}
-func (*MarkNode) inlineNode() { /* Just a marker */ }
+func (mn *MarkNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*MarkNode) WalkChildren(Visitor) { /* No children*/ }
+func (mn *MarkNode) WalkChildren(v Visitor) { /* No children*/ }
// --------------------------------------------------------------------------
// FootnoteNode contains the specified footnote.
type FootnoteNode struct {
- Inlines *InlineListNode // The footnote text.
- Attrs *Attributes // Optional attributes
+ Inlines InlineSlice // The footnote text.
+ Attrs *Attributes // Optional attributes
}
-func (*FootnoteNode) inlineNode() { /* Just a marker */ }
+func (fn *FootnoteNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the footnote text.
func (fn *FootnoteNode) WalkChildren(v Visitor) {
- Walk(v, fn.Inlines)
+ WalkInlineSlice(v, fn.Inlines)
}
// --------------------------------------------------------------------------
// FormatNode specifies some inline formatting.
type FormatNode struct {
Kind FormatKind
Attrs *Attributes // Optional attributes.
- Inlines *InlineListNode
+ Inlines InlineSlice
}
// FormatKind specifies the format that is applied to the inline nodes.
type FormatKind uint8
@@ -217,15 +169,15 @@
FormatSmall // Smaller text.
FormatSpan // Generic inline container.
FormatMonospace // Monospaced text.
)
-func (*FormatNode) inlineNode() { /* Just a marker */ }
+func (fn *FormatNode) inlineNode() { /* Just a marker */ }
// WalkChildren walks to the formatted text.
func (fn *FormatNode) WalkChildren(v Visitor) {
- Walk(v, fn.Inlines)
+ WalkInlineSlice(v, fn.Inlines)
}
// --------------------------------------------------------------------------
// LiteralNode specifies some uninterpreted text.
@@ -246,9 +198,9 @@
LiteralOutput // Sample output.
LiteralComment // Inline comment
LiteralHTML // Inline HTML, e.g. for Markdown
)
-func (*LiteralNode) inlineNode() { /* Just a marker */ }
+func (ln *LiteralNode) inlineNode() { /* Just a marker */ }
// WalkChildren does nothing.
-func (*LiteralNode) WalkChildren(Visitor) { /* No children*/ }
+func (ln *LiteralNode) WalkChildren(v Visitor) { /* No children*/ }
DELETED ast/material.go
Index: ast/material.go
==================================================================
--- ast/material.go
+++ /dev/null
@@ -1,43 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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
@@ -22,10 +22,24 @@
return
}
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)
- testRead(tt, pol, ts.withAuth, ts.expert)
+ testCreate(tt, pol, ts.withAuth, ts.readonly, ts.expert)
+ testRead(tt, pol, ts.withAuth, ts.readonly, 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 bool) {
+func testCreate(t *testing.T, pol auth.Policy, withAuth, readonly, isExpert bool) {
t.Helper()
anonUser := newAnon()
creator := newCreator()
reader := newReader()
writer := newWriter()
@@ -139,11 +139,11 @@
}
})
}
}
-func testRead(t *testing.T, pol auth.Policy, withAuth, expert bool) {
+func testRead(t *testing.T, pol auth.Policy, withAuth, readonly, expert bool) {
t.Helper()
anonUser := newAnon()
creator := newCreator()
reader := newReader()
writer := newWriter()
Index: box/box.go
==================================================================
--- box/box.go
+++ box/box.go
@@ -40,10 +40,13 @@
// GetZettel retrieves a specific zettel.
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.
@@ -60,25 +63,16 @@
// 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
- // 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
+ // SelectMeta returns all zettel meta data that match the selection criteria.
+ SelectMeta(ctx context.Context, match search.MetaMatchFunc) ([]*meta.Meta, error)
// ReadStats populates st with box statistics
ReadStats(st *ManagedBoxStats)
}
@@ -103,13 +97,10 @@
// 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.
GetAllZettel(ctx context.Context, zid id.Zid) ([]domain.Zettel, error)
Index: box/compbox/compbox.go
==================================================================
--- box/compbox/compbox.go
+++ box/compbox/compbox.go
@@ -18,10 +18,11 @@
"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",
@@ -54,19 +55,20 @@
}
// Setup remembers important values.
func Setup(cfg *meta.Meta) { myConfig = cfg.Clone() }
-func (*compBox) Location() string { return "" }
+func (pp *compBox) Location() string { return "" }
-func (*compBox) CanCreateZettel(context.Context) bool { return false }
+func (pp *compBox) CanCreateZettel(ctx context.Context) bool { return false }
-func (*compBox) CreateZettel(context.Context, domain.Zettel) (id.Zid, error) {
+func (pp *compBox) CreateZettel(
+ ctx context.Context, zettel domain.Zettel) (id.Zid, error) {
return id.Invalid, box.ErrReadOnly
}
-func (*compBox) GetZettel(_ context.Context, zid id.Zid) (domain.Zettel, error) {
+func (pp *compBox) GetZettel(ctx 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{
@@ -78,11 +80,11 @@
}
}
return domain.Zettel{}, box.ErrNotFound
}
-func (*compBox) GetMeta(_ context.Context, zid id.Zid) (*meta.Meta, error) {
+func (pp *compBox) GetMeta(ctx 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
@@ -90,60 +92,67 @@
}
}
return nil, box.ErrNotFound
}
-func (*compBox) ApplyZid(_ context.Context, handle box.ZidFunc) error {
+func (pp *compBox) FetchZids(ctx context.Context) (id.Set, error) {
+ result := id.NewSetCap(len(myZettel))
for zid, gen := range myZettel {
if genMeta := gen.meta; genMeta != nil {
if genMeta(zid) != nil {
- handle(zid)
+ result[zid] = true
}
}
}
- return nil
+ return result, nil
}
-func (pp *compBox) ApplyMeta(ctx context.Context, handle box.MetaFunc) error {
+func (pp *compBox) SelectMeta(ctx context.Context, match search.MetaMatchFunc) (res []*meta.Meta, err 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)
- handle(m)
+ if match(m) {
+ res = append(res, m)
+ }
}
}
}
- return nil
+ return res, 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 (*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 {
+func (pp *compBox) AllowRenameZettel(ctx context.Context, zid id.Zid) bool {
_, ok := myZettel[zid]
return !ok
}
-func (*compBox) RenameZettel(_ context.Context, curZid, _ id.Zid) error {
+func (pp *compBox) RenameZettel(ctx context.Context, curZid, newZid id.Zid) error {
if _, ok := myZettel[curZid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (*compBox) CanDeleteZettel(context.Context, id.Zid) bool { return false }
+func (pp *compBox) CanDeleteZettel(ctx context.Context, zid id.Zid) bool { return false }
-func (*compBox) DeleteZettel(_ context.Context, zid id.Zid) error {
+func (pp *compBox) DeleteZettel(ctx context.Context, zid id.Zid) error {
if _, ok := myZettel[zid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (*compBox) ReadStats(st *box.ManagedBoxStats) {
+func (pp *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,13 +254,10 @@
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,10 +19,11 @@
"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",
@@ -34,10 +35,18 @@
}, nil
})
}
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
}
@@ -46,66 +55,75 @@
number int
zettel map[id.Zid]constZettel
enricher box.Enricher
}
-func (*constBox) Location() string { return "const:" }
+func (cp *constBox) Location() string {
+ return "const:"
+}
-func (*constBox) CanCreateZettel(context.Context) bool { return false }
+func (cp *constBox) CanCreateZettel(ctx context.Context) bool { return false }
-func (*constBox) CreateZettel(context.Context, domain.Zettel) (id.Zid, error) {
+func (cp *constBox) CreateZettel(ctx context.Context, zettel domain.Zettel) (id.Zid, error) {
return id.Invalid, box.ErrReadOnly
}
-func (cp *constBox) GetZettel(_ context.Context, zid id.Zid) (domain.Zettel, error) {
+func (cp *constBox) GetZettel(ctx context.Context, zid id.Zid) (domain.Zettel, error) {
if z, ok := cp.zettel[zid]; ok {
- return domain.Zettel{Meta: meta.NewWithData(zid, z.header), Content: z.content}, nil
+ return domain.Zettel{Meta: makeMeta(zid, z.header), Content: z.content}, nil
}
return domain.Zettel{}, box.ErrNotFound
}
-func (cp *constBox) GetMeta(_ context.Context, zid id.Zid) (*meta.Meta, error) {
+func (cp *constBox) GetMeta(ctx context.Context, zid id.Zid) (*meta.Meta, error) {
if z, ok := cp.zettel[zid]; ok {
- return meta.NewWithData(zid, z.header), nil
+ return makeMeta(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)
+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)
- 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 {
+ 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 {
_, ok := cp.zettel[zid]
return !ok
}
-func (cp *constBox) RenameZettel(_ context.Context, curZid, _ id.Zid) error {
+func (cp *constBox) RenameZettel(ctx context.Context, curZid, newZid id.Zid) error {
if _, ok := cp.zettel[curZid]; ok {
return box.ErrReadOnly
}
return box.ErrNotFound
}
-func (*constBox) CanDeleteZettel(context.Context, id.Zid) bool { return false }
+func (cp *constBox) CanDeleteZettel(ctx context.Context, zid id.Zid) bool { return false }
-func (cp *constBox) DeleteZettel(_ context.Context, zid id.Zid) error {
+func (cp *constBox) DeleteZettel(ctx 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,17 +3,18 @@
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]]: {{00000000000001}}
+* [[Zettelstore Version|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,29 +29,18 @@
{{.}}
{{/ExtLinks}}
{{/HasExtLinks}}
{{/HasLinks}}
-Parts and encodings
-
-{{#EvalMatrix}}
-
-{{Header}} |
-{{#Elements}}{{Text}} |
-{{/Elements}}
-
-{{/EvalMatrix}}
-
-Parsed (not evaluated)
-
-{{#ParseMatrix}}
-
-{{Header}} |
-{{#Elements}}{{Text}} |
-{{/Elements}}
-
-{{/ParseMatrix}}
+Parts and format
+
+{{#Matrix}}
+
+{{#Elements}}{{#HasURL}}{{Text}} | {{/HasURL}}{{^HasURL}}{{Text}} | {{/HasURL}}
+{{/Elements}}
+
+{{/Matrix}}
{{#HasShadowLinks}}
Shadowed Boxes
{{#ShadowLinks}}- {{.}}
{{/ShadowLinks}}
{{/HasShadowLinks}}
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}}
-