Index: VERSION ================================================================== --- VERSION +++ VERSION @@ -1,1 +1,1 @@ -0.21.0 +0.22.0 Index: cmd/cmd_run.go ================================================================== --- cmd/cmd_run.go +++ cmd/cmd_run.go @@ -19,10 +19,11 @@ "net/http" "t73f.de/r/zsc/domain/meta" "zettelstore.de/z/internal/auth" + "zettelstore.de/z/internal/auth/user" "zettelstore.de/z/internal/box" "zettelstore.de/z/internal/config" "zettelstore.de/z/internal/kernel" "zettelstore.de/z/internal/usecase" "zettelstore.de/z/internal/web/adapter/api" @@ -53,19 +54,19 @@ } func setupRouting(webSrv server.Server, boxManager box.Manager, authManager auth.Manager, rtConfig config.Config) { protectedBoxManager, authPolicy := authManager.BoxWithPolicy(boxManager, rtConfig) kern := kernel.Main - webLog := kern.GetLogger(kernel.WebService) + webLogger := kern.GetLogger(kernel.WebService) var getUser getUserImpl - logAuth := kern.GetLogger(kernel.AuthService) - logUc := kern.GetLogger(kernel.CoreService).WithUser(&getUser) + authLogger := kern.GetLogger(kernel.AuthService) + ucLogger := kern.GetLogger(kernel.CoreService) ucGetUser := usecase.NewGetUser(authManager, boxManager) - ucAuthenticate := usecase.NewAuthenticate(logAuth, authManager, &ucGetUser) - ucIsAuth := usecase.NewIsAuthenticated(logUc, &getUser, authManager) - ucCreateZettel := usecase.NewCreateZettel(logUc, rtConfig, protectedBoxManager) + ucAuthenticate := usecase.NewAuthenticate(authLogger, authManager, &ucGetUser) + ucIsAuth := usecase.NewIsAuthenticated(ucLogger, &getUser, authManager) + ucCreateZettel := usecase.NewCreateZettel(ucLogger, rtConfig, protectedBoxManager) ucGetAllZettel := usecase.NewGetAllZettel(protectedBoxManager) ucGetZettel := usecase.NewGetZettel(protectedBoxManager) ucParseZettel := usecase.NewParseZettel(rtConfig, ucGetZettel) ucGetReferences := usecase.NewGetReferences() ucQuery := usecase.NewQuery(protectedBoxManager) @@ -73,21 +74,21 @@ ucQuery.SetEvaluate(&ucEvaluate) ucTagZettel := usecase.NewTagZettel(protectedBoxManager, &ucQuery) ucRoleZettel := usecase.NewRoleZettel(protectedBoxManager, &ucQuery) ucListSyntax := usecase.NewListSyntax(protectedBoxManager) ucListRoles := usecase.NewListRoles(protectedBoxManager) - ucDelete := usecase.NewDeleteZettel(logUc, protectedBoxManager) - ucUpdate := usecase.NewUpdateZettel(logUc, protectedBoxManager) - ucRefresh := usecase.NewRefresh(logUc, protectedBoxManager) - ucReIndex := usecase.NewReIndex(logUc, protectedBoxManager) + ucDelete := usecase.NewDeleteZettel(ucLogger, protectedBoxManager) + ucUpdate := usecase.NewUpdateZettel(ucLogger, protectedBoxManager) + ucRefresh := usecase.NewRefresh(ucLogger, protectedBoxManager) + ucReIndex := usecase.NewReIndex(ucLogger, protectedBoxManager) ucVersion := usecase.NewVersion(kernel.Main.GetConfig(kernel.CoreService, kernel.CoreVersion).(string)) a := api.New( - webLog.Clone().Str("adapter", "api").Child(), + webLogger.With("system", "WEBAPI"), webSrv, authManager, authManager, rtConfig, authPolicy) wui := webui.New( - webLog.Clone().Str("adapter", "wui").Child(), + webLogger.With("system", "WEBUI"), webSrv, authManager, rtConfig, authManager, boxManager, authPolicy, &ucEvaluate) webSrv.Handle("/", wui.MakeGetRootHandler(protectedBoxManager)) if assetDir := kern.GetConfig(kernel.WebService, kernel.WebAssetDir).(string); assetDir != "" { const assetPrefix = "/assets/" @@ -134,6 +135,6 @@ } } type getUserImpl struct{} -func (*getUserImpl) GetUser(ctx context.Context) *meta.Meta { return server.GetUser(ctx) } +func (*getUserImpl) GetCurrentUser(ctx context.Context) *meta.Meta { return user.GetCurrentUser(ctx) } Index: cmd/command.go ================================================================== --- cmd/command.go +++ cmd/command.go @@ -13,14 +13,13 @@ package cmd import ( "flag" + "log/slog" "maps" "slices" - - "zettelstore.de/z/internal/logger" ) // Command stores information about commands / sub-commands. type Command struct { Name string // command name as it appears on the command line @@ -50,11 +49,11 @@ } if _, ok := commands[cmd.Name]; ok { panic("Command already registered: " + cmd.Name) } cmd.flags = flag.NewFlagSet(cmd.Name, flag.ExitOnError) - cmd.flags.String("l", logger.InfoLevel.String(), "log level specification") + cmd.flags.String("l", slog.LevelInfo.String(), "log level specification") if cmd.SetFlags != nil { cmd.SetFlags(cmd.flags) } commands[cmd.Name] = cmd Index: cmd/main.go ================================================================== --- cmd/main.go +++ cmd/main.go @@ -16,10 +16,11 @@ import ( "crypto/sha256" "flag" "fmt" + "log/slog" "net" "net/url" "os" "runtime/debug" "strconv" @@ -36,11 +37,11 @@ "zettelstore.de/z/internal/box" "zettelstore.de/z/internal/box/compbox" "zettelstore.de/z/internal/box/manager" "zettelstore.de/z/internal/config" "zettelstore.de/z/internal/kernel" - "zettelstore.de/z/internal/logger" + "zettelstore.de/z/internal/logging" "zettelstore.de/z/internal/web/server" ) const strRunSimple = "run-simple" @@ -169,25 +170,28 @@ keyDefaultDirBoxType = "default-dir-box-type" keyInsecureCookie = "insecure-cookie" keyInsecureHTML = "insecure-html" keyListenAddr = "listen-addr" keyLogLevel = "log-level" + keyLoopbackIdent = "loopback-ident" + keyLoopbackZid = "loopback-zid" keyMaxRequestSize = "max-request-size" keyOwner = "owner" keyPersistentCookie = "persistent-cookie" keyReadOnly = "read-only-mode" keyRuntimeProfiling = "runtime-profiling" + keySxNesting = "sx-max-nesting" keyTokenLifetimeHTML = "token-lifetime-html" keyTokenLifetimeAPI = "token-lifetime-api" keyURLPrefix = "url-prefix" keyVerbose = "verbose-mode" ) func setServiceConfig(cfg *meta.Meta) bool { debugMode := cfg.GetBool(keyDebug) - if debugMode && kernel.Main.GetKernelLogger().Level() > logger.DebugLevel { - kernel.Main.SetLogLevel(logger.DebugLevel.String()) + if debugMode && kernel.Main.GetKernelLogLevel() > slog.LevelDebug { + kernel.Main.SetLogLevel(logging.LevelString(slog.LevelDebug)) } if logLevel, found := cfg.Get(keyLogLevel); found { kernel.Main.SetLogLevel(string(logLevel)) } err := setConfigValue(nil, kernel.CoreService, kernel.CoreDebug, debugMode) @@ -215,10 +219,12 @@ err = setConfigValue( err, kernel.ConfigService, kernel.ConfigInsecureHTML, cfg.GetDefault(keyInsecureHTML, kernel.ConfigSecureHTML)) err = setConfigValue( err, kernel.WebService, kernel.WebListenAddress, cfg.GetDefault(keyListenAddr, "127.0.0.1:23123")) + err = setConfigValue(err, kernel.WebService, kernel.WebLoopbackIdent, cfg.GetDefault(keyLoopbackIdent, "")) + err = setConfigValue(err, kernel.WebService, kernel.WebLoopbackZid, cfg.GetDefault(keyLoopbackZid, "")) if val, found := cfg.Get(keyBaseURL); found { err = setConfigValue(err, kernel.WebService, kernel.WebBaseURL, val) } if val, found := cfg.Get(keyURLPrefix); found { err = setConfigValue(err, kernel.WebService, kernel.WebURLPrefix, val) @@ -234,18 +240,21 @@ err, kernel.WebService, kernel.WebTokenLifetimeHTML, cfg.GetDefault(keyTokenLifetimeHTML, "")) err = setConfigValue(err, kernel.WebService, kernel.WebProfiling, debugMode || cfg.GetBool(keyRuntimeProfiling)) if val, found := cfg.Get(keyAssetDir); found { err = setConfigValue(err, kernel.WebService, kernel.WebAssetDir, val) } + if val, found := cfg.Get(keySxNesting); found { + err = setConfigValue(err, kernel.WebService, kernel.WebSxMaxNesting, val) + } return err == nil } func setConfigValue(err error, subsys kernel.Service, key string, val any) error { if err == nil { - err = kernel.Main.SetConfig(subsys, key, fmt.Sprint(val)) - if err != nil { - kernel.Main.GetKernelLogger().Error().Str("key", key).Str("value", fmt.Sprint(val)).Err(err).Msg("Unable to set configuration") + if err = kernel.Main.SetConfig(subsys, key, fmt.Sprint(val)); err != nil { + kernel.Main.GetKernelLogger().Error("Unable to set configuration", + "key", key, "value", val, "err", err) } } return err } @@ -295,11 +304,14 @@ return nil }, ) if command.Simple { - kern.SetConfig(kernel.ConfigService, kernel.ConfigSimpleMode, "true") + if err := kern.SetConfig(kernel.ConfigService, kernel.ConfigSimpleMode, "true"); err != nil { + kern.GetKernelLogger().Error("unable to set simple-mode", "err", err) + return 1 + } } kern.Start(command.Header, command.LineServer, filename) exitCode, err := command.Func(fs) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", name, err) @@ -333,16 +345,25 @@ fullVersion += "-dirty" } kernel.Main.Setup(progName, fullVersion, info.time) flag.Parse() if *cpuprofile != "" || *memprofile != "" { + var err error if *cpuprofile != "" { - kernel.Main.StartProfiling(kernel.ProfileCPU, *cpuprofile) + err = kernel.Main.StartProfiling(kernel.ProfileCPU, *cpuprofile) } else { - kernel.Main.StartProfiling(kernel.ProfileHead, *memprofile) + err = kernel.Main.StartProfiling(kernel.ProfileHead, *memprofile) + } + if err != nil { + kernel.Main.GetKernelLogger().Error("start profiling", "err", err) + return 1 } - defer kernel.Main.StopProfiling() + defer func() { + if err = kernel.Main.StopProfiling(); err != nil { + kernel.Main.GetKernelLogger().Error("stop profiling", "err", err) + } + }() } args := flag.Args() if len(args) == 0 { return runSimple() } Index: docs/development/20210916194900.zettel ================================================================== --- docs/development/20210916194900.zettel +++ docs/development/20210916194900.zettel @@ -1,18 +1,21 @@ id: 20210916194900 title: Checklist for Release role: zettel syntax: zmk created: 20210916194900 -modified: 20241213125640 +modified: 20250702180238 # Sync with the official repository: #* ``fossil sync -u`` # Make sure that there is no workspace defined: #* ``ls ..`` must not have a file ''go.work'', in no parent folder. # Make sure that all dependencies are up-to-date: #* ``cat go.mod`` +# Ensure clean indirect dependencies: +#* ``go mod graph | modgraphviz | dot -Tpdf -o /tmp/zsgraph.pdf`` +#* Grey boxes signal outdated dependencies # Clean up your Go workspace: #* ``go run tools/clean/clean.go`` (alternatively: ``make clean``) # All internal tests must succeed: #* ``go run tools/check/check.go -r`` (alternatively: ``make relcheck``) # The API tests must succeed on every development platform: Index: docs/manual/00001002000000.zettel ================================================================== --- docs/manual/00001002000000.zettel +++ docs/manual/00001002000000.zettel @@ -2,17 +2,17 @@ title: Design goals for the Zettelstore role: manual tags: #design #goal #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102191434 +modified: 20250602181324 Zettelstore supports the following design goals: ; Longevity of stored notes / zettel : Every zettel you create should be readable without the help of any tool, even without Zettelstore. -: It should not hard to write other software that works with your zettel. +: It should not be hard to write other software that works with your zettel. : Normal zettel should be stored in a single file. If this is not possible: at most in two files: one for the metadata, one for the content. The only exceptions are [[predefined zettel|00001005090000]] stored in the Zettelstore executable. : There is no additional database. ; Single user @@ -37,7 +37,7 @@ : External software can be written to deeply analyze your zettel and the structures they form. ; Security by default : Without any customization, Zettelstore provides its services in a safe and secure manner and does not expose you (or other users) to security risks. : If you know what you are doing, Zettelstore allows you to relax some security-related preferences. However, even in this case, the more secure way is chosen. -: The Zettelstore software uses a minimal design and uses other software dependencies only is essential needed. +: Zettelstore features a minimal design and relies on external software only when absolutely necessary. : There will be no plugin mechanism, which allows external software to control the inner workings of the Zettelstore software. Index: docs/manual/00001003300000.zettel ================================================================== --- docs/manual/00001003300000.zettel +++ docs/manual/00001003300000.zettel @@ -2,11 +2,11 @@ title: Zettelstore installation for the intermediate user role: manual tags: #installation #manual #zettelstore syntax: zmk created: 20211125191727 -modified: 20250227220050 +modified: 20250627152419 You have already tried the Zettelstore software and now you want to use it permanently. Zettelstore should start automatically when you log into your computer. * Grab the appropriate executable and copy it into the appropriate directory @@ -17,11 +17,11 @@ In most cases, this is done by the command ``cd DIR``, where ''DIR'' denotes the directory, where you placed the executable. ** Start the Zettelstore: *** On Windows execute the command ``zettelstore.exe run -c CONFIG_FILE`` *** On macOS execute the command ``./zettelstore run -c CONFIG_FILE`` *** On Linux execute the command ``./zettelstore run -c CONFIG_FILE`` -** In all cases ''CONFIG_FILE'' must be replaced with the file name where you wrote the startup configuration. +** In all cases, ''CONFIG_FILE'' must be replaced with the name of the file where you wrote the startup configuration. ** If you encounter some error messages, update the startup configuration, and try again. * Depending on your operating system, there are different ways to register Zettelstore to start automatically: ** [[Windows|00001003305000]] ** [[macOS|00001003310000]] ** [[Linux|00001003315000]] Index: docs/manual/00001003305000.zettel ================================================================== --- docs/manual/00001003305000.zettel +++ docs/manual/00001003305000.zettel @@ -2,17 +2,17 @@ title: Enable Zettelstore to start automatically on Windows role: manual tags: #installation #manual #zettelstore syntax: zmk created: 20211125191727 -modified: 20241213103259 +modified: 20250701130205 Windows is a complicated beast. There are several ways to automatically start Zettelstore. === Startup folder -One way is to use the [[autostart folder|https://support.microsoft.com/en-us/windows/add-an-app-to-run-automatically-at-startup-in-windows-10-150da165-dcd9-7230-517b-cf3c295d89dd]]. +One way is to use the [[autostart folder|https://support.microsoft.com/en-us/windows/configure-startup-applications-in-windows-115a420a-0bff-4a6f-90e0-1934c844e473]]. Open the folder where you have placed in the Explorer. Create a shortcut file for the Zettelstore executable. There are some ways to do this: * Execute a right-click on the executable, and choose the menu entry ""Create shortcut"", * Execute a right-click on the executable, and then click Send To > Desktop (Create shortcut). @@ -29,11 +29,11 @@ You can modify the behavior by changing some properties of the shortcut file. === Task scheduler -The Windows Task scheduler allows you to start Zettelstore as an background task. +The Windows Task scheduler allows you to start Zettelstore as a background task. This is both an advantage and a disadvantage. On the plus side, Zettelstore runs in the background, and it does not disturb you. All you have to do is to open your web browser, enter the appropriate URL, and there you go. @@ -111,10 +111,10 @@ As the last step, you could run the freshly created task manually. Open your browser, enter the appropriate URL and use your Zettelstore. In case of errors, the task will most likely stop immediately. Make sure that all data you have entered is valid. -To not forget to check the content of the startup configuration file. +Do not forget to check the content of the startup configuration file. Use the command prompt to debug your configuration. Sometimes, for example when your computer was in stand-by and it wakes up, these tasks are not started. In this case execute the task scheduler and run the task manually. Index: docs/manual/00001003315000.zettel ================================================================== --- docs/manual/00001003315000.zettel +++ docs/manual/00001003315000.zettel @@ -2,23 +2,23 @@ title: Enable Zettelstore to start automatically on Linux role: manual tags: #installation #manual #zettelstore syntax: zmk created: 20220114181521 -modified: 20250102221716 +modified: 20250701135817 Since there is no such thing as the one Linux, there are too many different ways to automatically start Zettelstore. * One way is to interpret your Linux desktop system as a server and use the [[recipe to install Zettelstore on a server|00001003600000]]. ** See below for a lighter alternative. -* If you are using the [[Gnome Desktop|https://www.gnome.org/]], you could use the tool [[Tweak|https://wiki.gnome.org/action/show/Apps/Tweaks]] (formerly known as ""GNOME Tweak Tool"" or just ""Tweak Tool""). - It allows to specify application that should run on startup / login. +* If you are using the [[Gnome Desktop|https://www.gnome.org/]], you could use the tool [[GNOME Tweaks|https://gitlab.gnome.org/GNOME/gnome-tweaks]]. + It allows you to specify applications that should run on startup / login. * [[KDE|https://kde.org/]] provides a system setting to [[autostart|https://docs.kde.org/stable5/en/plasma-workspace/kcontrol/autostart/]] applications. * [[Xfce|https://xfce.org/]] allows to specify [[autostart applications|https://docs.xfce.org/xfce/xfce4-session/preferences#application_autostart]]. -* [[LXDE|https://www.lxde.org/]] uses [[LXSession Edit|https://wiki.lxde.org/en/LXSession_Edit]] to allow users to specify autostart applications. +* [[LXDE|https://www.lxde.org/]] uses ""LXSession Edit"" to allow users to specify autostart applications. -If you use a different desktop environment, it often helps to to provide its name and the string ""autostart"" to google for it with the search engine of your choice. +If you're using a different desktop environment, try searching for its name together with the word ""autostart"". Yet another way is to make use of the middleware that is provided. Many Linux distributions make use of [[systemd|https://systemd.io/]], which allows to start processes on behalf of a user. On the command line, adapt the following script to your own needs and execute it: ``` Index: docs/manual/00001004010000.zettel ================================================================== --- docs/manual/00001004010000.zettel +++ docs/manual/00001004010000.zettel @@ -2,11 +2,11 @@ title: Zettelstore startup configuration role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102180346 +modified: 20250627155145 The configuration file, specified by the ''-c CONFIGFILE'' [[command line option|00001004051000]], allows you to specify some startup options. These cannot be stored in a [[configuration zettel|00001004020000]] because they are needed before Zettelstore can start or because of security reasons. For example, Zettelstore needs to know in advance on which network address it must listen or where zettel are stored. An attacker that is able to change the owner can do anything. @@ -43,11 +43,11 @@ Default: ""http://127.0.0.1:23123/"". ; [!box-uri-x|''box-uri-X''], where __X__ is a number greater or equal to one : Specifies a [[box|00001004011200]] where zettel are stored. During startup, __X__ is incremented, starting with one, until no key is found. - This allows to configuring than one box. + This allows you to configure than one box. If no ''box-uri-1'' key is given, the overall effect will be the same as if only ''box-uri-1'' was specified with the value ""dir://.zettel"". In this case, even a key ''box-uri-2'' will be ignored. ; [!debug-mode|''debug-mode''] : If set to [[true|00001006030500]], allows to debug the Zettelstore software (mostly used by Zettelstore developers). @@ -93,10 +93,22 @@ Examples: ""error"" will produce just error messages (e.g. no ""info"" messages). ""error;web:debug"" will emit debugging messages for the web component of Zettelstore while still producing error messages for all other components. When you are familiar with operating the Zettelstore, you might set the level to ""error"" to receive fewer noisy messages from it. +; [!loopback-ident|''loopback-ident''], [!loopback-zid|''loopback-zid''] +: These keys are effective only if [[authentication is enabled|00001010000000]]. + They must specify the user ID and zettel ID of a [[user zettel|00001010040200]]. + When these keys are set and an HTTP request originates from the loopback device, no further authentication is required. + + The loopback device typically uses the IP address ''127.0.0.1'' (IPv4) or ''::1'' (IPv6). + + This configuration allows client software running on the same computer as the Zettelstore to access it through its API or web user interface. + + However, this setup is not recommended if the Zettelstore is running on a computer shared with untrusted or unknown users. + + Default: (empty string)/00000000000000 ; [!max-request-size|''max-request-size''] : It limits the maximum byte size of a web request body to prevent clients from accidentally or maliciously sending a large request and wasting server resources. The minimum value is 1024. Default: 16777216 (16 MiB). @@ -115,11 +127,11 @@ If ""true"", a persistent cookie is used. Its lifetime exceeds the lifetime of the authentication token by 30 seconds (see option ''token-lifetime-html''). Default: ""false"" ; [!read-only-mode|''read-only-mode''] -: If set to a [[true value|00001006030500]] the Zettelstore service puts into a read-only mode. +: If set to a [[true value|00001006030500]] the Zettelstore service will beputs into a read-only mode. No changes are possible. Default: ""false"". ; [!runtime-profiling|''runtime-profiling''] : A boolean value that enables a web interface to obtain [[runtime profiling information|00001004010200]]. @@ -129,10 +141,16 @@ ; [!secret|''secret''] : A string value to make the communication with external clients strong enough so that sessions of the [[web user interface|00001014000000]] or [[API access token|00001010040700]] cannot be altered by some external unfriendly party. The string must have a length of at least 16 bytes. This value is only needed to be set if [[authentication is enabled|00001010040100]] by setting the key [[''owner''|#owner]] to some user identification value. +; [!sx-max-nesting|''sx-max-nesting''] +: Limits nesting of template evaluation to the given value. + + This is used to prevent the application from crashing when an error occurs in a template zettel of the Web User Interface. + + Default: ""32768"" ; [!token-lifetime-api|''token-lifetime-api''], [!token-lifetime-html|''token-lifetime-html''] : Define lifetime of access tokens in minutes. Values are only valid if authentication is enabled, i.e. key ''owner'' is set. ''token-lifetime-api'' is for accessing Zettelstore via its [[API|00001012000000]]. Index: docs/manual/00001004011200.zettel ================================================================== --- docs/manual/00001004011200.zettel +++ docs/manual/00001004011200.zettel @@ -2,11 +2,11 @@ title: Zettelstore boxes role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102185551 +modified: 20250627162212 A Zettelstore must store its zettel somehow and somewhere. In most cases you want to store your zettel as files in a directory. Under certain circumstances you may want to store your zettel elsewhere. @@ -23,11 +23,11 @@ ; [!dir|''dir://DIR''] : Specifies a directory where zettel files are stored. ''DIR'' is the file path. Although it is possible to use relative file paths, such as ''./zettel'' (→ URI is ''dir://.zettel''), it is preferable to use absolute file paths, e.g. ''/home/user/zettel''. - The directory must exist before starting the Zettelstore[^There is one exception: when Zettelstore is [[started without any parameter|00001004050000]], e.g. via double-clicking its icon, an directory called ''./zettel'' will be created.]. + The directory must exist before starting the Zettelstore[^There is one exception: when Zettelstore is [[started without any parameter|00001004050000]], e.g. via double-clicking its icon, a directory called ''./zettel'' will be created.]. It is possible to [[configure|00001004011400]] a directory box. ; [!file|''file:FILE.zip'' or ''file:///path/to/file.zip''] : Specifies a ZIP file which contains files that store zettel. You can create such a ZIP file, if you zip a directory full of zettel files. @@ -41,8 +41,8 @@ All boxes that you configure via the ''box-uri-X'' keys form a chain of boxes. If a zettel should be retrieved, a search starts in the box specified with the ''box-uri-2'' key, then ''box-uri-3'' and so on. If a zettel is created or changed, it is always stored in the box specified with the ''box-uri-1'' key. This allows to overwrite zettel from other boxes, e.g. the predefined zettel. -If you use the ''mem:'' box, where zettel are stored in volatile memory, it makes only sense if you configure it as ''box-uri-1''. -Such a box will be empty when Zettelstore starts and only the first box will receive updates. -You must make sure that your computer has enough RAM to store all zettel. +If you use the ''mem:'' box, where zettel are stored in volatile memory, it only makes sense if you configure it as ''box-uri-1''. +Such a box will be empty when Zettelstore starts, and only the first box will receive updates. +You must ensure that your computer has enough RAM to store all zettel. Index: docs/manual/00001004011400.zettel ================================================================== --- docs/manual/00001004011400.zettel +++ docs/manual/00001004011400.zettel @@ -2,11 +2,11 @@ title: Configure file directory boxes role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102180416 +modified: 20250701135923 Under certain circumstances, it is preferable to further configure a file directory box. This is done by appending query parameters after the base box URI ''dir:\//DIR''. The following parameters are supported: @@ -16,11 +16,11 @@ |worker|Number of workers that can access the directory in parallel|7 |readonly|Allow only operations that do not create or change zettel|n/a === Type On some operating systems, Zettelstore tries to detect changes to zettel files outside of Zettelstore's control[^This includes Linux, Windows, and macOS.]. -On other operating systems, this may be not possible, due to technical limitations. +On other operating systems, this may not be possible due to technical limitations. Automatic detection of external changes is also not possible, if zettel files are put on an external service, such as a file server accessed via SMB/CIFS or NFS. To cope with this uncertainty, Zettelstore provides various internal implementations of a directory box. The default values should match the needs of different users, as explained in the [[installation part|00001003000000]] of this manual. The following values are supported: @@ -35,17 +35,17 @@ === Worker Internally, Zettelstore parallels concurrent requests for a zettel or its metadata. The number of parallel activities is configured by the ''worker'' parameter. -A computer contains a limited number of internal processing units (CPU). -Its number ranges from 1 to (currently) 128, e.g. in bigger server environments. -Zettelstore typically runs on a system with 1 to 8 CPUs. -Access to zettel file is ultimately managed by the underlying operating system. -Depending on the hardware and on the type of the directory box, only a limited number of parallel accesses are desirable. +A computer contains a limited number of internal processing units (CPUs). +Their number ranges from 1 up to (currently) 128, for example in larger server environments. +Zettelstore typically runs on systems with 1 to 8 CPUs. +Access to zettel files is ultimately managed by the underlying operating system. +Depending on the hardware and the type of directory box, only a limited number of parallel accesses is desirable. -On smaller hardware[^In comparison to a normal desktop or laptop computer], such as the [[Raspberry Zero|https://www.raspberrypi.org/products/raspberry-pi-zero/]], a smaller value might be appropriate. +On smaller hardware[^In comparison to a normal desktop or laptop computer], such as the [[Raspberry Pi Zero|https://www.raspberrypi.com/products/raspberry-pi-zero/]], a smaller value might be appropriate. Every worker needs some amount of main memory (RAM) and some amount of processing power. On bigger hardware, with some fast file services, a bigger value could result in higher performance, if needed. For various reasons, the value should be a prime number. The software might enforce this restriction by selecting the next prime number of a specified non-prime value. Index: docs/manual/00001004011600.zettel ================================================================== --- docs/manual/00001004011600.zettel +++ docs/manual/00001004011600.zettel @@ -2,11 +2,11 @@ title: Configure memory boxes role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20220307112918 -modified: 20250102222236 +modified: 20250627155851 Under most circumstances, it is preferable to further configure a memory box. This is done by appending query parameters after the base box URI ''mem:''. The following parameters are supported: @@ -13,14 +13,13 @@ |= Parameter:|Description|Default value:|Maximum value: |max-bytes|Maximum number of bytes the box will store|65535|1073741824 (1 GiB) |max-zettel|Maximum number of zettel|127|65535 -The default values are somehow arbitrarily, but applicable for many use cases. - -While the number of zettel should be easily calculable by a user, the number of bytes might be a little more difficult. - -Metadata consumes 6 bytes for the zettel identifier and for each metadata value one byte for the separator, plus the length of key and data. -Then size of the content is its size in bytes. -For text content, its the number of bytes for its UTF-8 encoding. - -If one of the limits are exceeded, Zettelstore will give an error indication, based on the HTTP status code 507. +The default values are somewhat arbitrary but applicable to many use cases. + +While the number of zettel should be easily calculable by a user, the number of bytes might be a bit more difficult to determine. + +Metadata consumes 6 bytes for the zettel identifier, plus one byte for the separator for each metadata value, in addition to the length of the key and data. +The size of the content is its size in bytes. For text content, this corresponds to the number of bytes in its UTF-8 encoding. + +If one of the limits is exceeded, Zettelstore will return an error indicated by the HTTP status code 507. Index: docs/manual/00001004020000.zettel ================================================================== --- docs/manual/00001004020000.zettel +++ docs/manual/00001004020000.zettel @@ -2,17 +2,17 @@ title: Configure a running Zettelstore role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250131151530 +modified: 20250701130707 show-back-links: false You can configure a running Zettelstore by modifying the special zettel with the ID [[00000000000100]]. This zettel is called __configuration zettel__. The following metadata keys change the appearance / behavior of Zettelstore. -Some of them can be overwritten in an [[user zettel|00001010040200]], a subset of those may be overwritten in zettel that is currently used. +Some of them can be overwritten in a [[user zettel|00001010040200]], a subset of those may be overwritten in the zettel that is currently used. See the full list of [[metadata that may be overwritten|00001004020200]]. ; [!default-copyright|''default-copyright''] : Copyright value to be used when rendering content. Can be overwritten in a zettel with [[meta key|00001006020000]] ''copyright''. @@ -51,11 +51,11 @@ Default: ""en"". This value is used as a default value, if it is not set in a user's zettel or in a zettel. It is also used to specify the language for all non-zettel content, e.g. lists or search results. - Use values according to the language definition of [[RFC-5646|https://tools.ietf.org/html/rfc5646]]. + Use values according to the language definition of [[RFC-5646|https://datatracker.ietf.org/doc/html/rfc5646]]. ; [!lists-menu-zettel|''lists-menu-zettel''] : Identifier of the zettel that specifies entries of the ""Lists"" menu (in the [[Web user interface|00001014000000]]). Every list item with a [[link|00001007040310]] is translated into a menu entry. If not given or if the identifier does not identify a zettel, or the zettel is not accessible for the current user, the zettel with the identifier ''00000000080001'' is used. @@ -66,22 +66,22 @@ ; [!max-transclusions|''max-transclusions''] : Maximum number of indirect transclusion. This is used to avoid an exploding ""transclusion bomb"", a form of a [[billion laughs attack|https://en.wikipedia.org/wiki/Billion_laughs_attack]]. Default: ""1024"". -; [!show-back-links|''show-back-links''], [!show-folge-links|''show-folge-links''], [!show-sequel-links|''show-sequel-links''], [!show-subordinate-links|''show-subordinate-links''], [!show-successor-links|''show-successor-links''] +; [!show-back-links|''show-back-links''], [!show-folge-links|''show-folge-links''], [!show-sequel-links|''show-sequel-links''], [!show-subordinate-links|''show-subordinate-links''] : When displaying a zettel in the web user interface, references to other zettel are normally shown below the content of the zettel. - This affects the metadata keys [[''back''|00001006020000#back]], [[''folge''|00001006020000#folge]], [[''sequel''|00001006020000#sequel]], [[''subordinates''|00001006020000#subordinates]], and [[''successors''|00001006020000#successors]]. + This affects the metadata keys [[''back''|00001006020000#back]], [[''folge''|00001006020000#folge]], [[''sequel''|00001006020000#sequel]], and [[''subordinates''|00001006020000#subordinates]]. These configuration keys may be used to show, not to show, or to close the list of referenced zettel. Allowed values are: ""false"" (will not show the list), ""close"" (will show the list closed), and ""open"" / """" (will show the list). Default: """". May be [[overwritten|00001004020200]] in a user zettel, so that setting will only affect the given user. - Alternatively, it may be overwritten in a zettel, so that that the setting will affect only the given zettel. + Alternatively, it may be overwritten in a zettel, so that the setting will affect only the given zettel. This zettel is an example of a zettel that sets ''show-back-links'' to ""false"". ; [!site-name|''site-name''] : Name of the Zettelstore instance. Will be used when displaying some lists. Index: docs/manual/00001004020200.zettel ================================================================== --- docs/manual/00001004020200.zettel +++ docs/manual/00001004020200.zettel @@ -2,11 +2,11 @@ title: Runtime configuration data that may be user specific or zettel specific role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20221205155521 -modified: 20250131151259 +modified: 20250626114354 Some metadata of the [[runtime configuration|00001004020000]] may be overwritten in an [[user zettel|00001010040200]]. A subset of those may be overwritten in the zettel that is currently used. This allows to specify user specific or zettel specific behavior. @@ -19,6 +19,5 @@ |[[''lists-menu-zettel''|00001004020000#lists-menu-zettel]]|Y|N| |[[''show-back-links''|00001004020000#show-back-links]]|Y|Y| |[[''show-folge-links''|00001004020000#show-folge-links]]|Y|Y| |[[''show-sequel-links''|00001004020000#show-sequel-links]]|Y|Y| |[[''show-subordinate-links''|00001004020000#show-subordinate-links]]|Y|Y| -|[[''show-successor-links''|00001004020000#show-successor-links]]|Y|Y| Index: docs/manual/00001004050000.zettel ================================================================== --- docs/manual/00001004050000.zettel +++ docs/manual/00001004050000.zettel @@ -2,21 +2,21 @@ title: Command line parameters role: manual tags: #command #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102174436 +modified: 20250627160307 Zettelstore is not just a service that provides services of a zettelkasten. It allows some tasks to be executed at the command line. Typically, the task (""sub-command"") will be given at the command line as the first parameter. If no parameter is given, the Zettelstore is called as ``` zettelstore ``` -This is equivalent to call it this way: +This is equivalent to calling it this way: ```sh mkdir -p ./zettel zettelstore run -d ./zettel -c ./.zscfg ``` Typically this is done by starting Zettelstore via a graphical user interface by double-clicking its file icon. Index: docs/manual/00001004050400.zettel ================================================================== --- docs/manual/00001004050400.zettel +++ docs/manual/00001004050400.zettel @@ -2,30 +2,30 @@ title: The ''version'' sub-command role: manual tags: #command #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20211124182041 +modified: 20250701125959 -Emits some information about the Zettelstore's version. -This allows you to check, whether your installed Zettelstore is +Emits some information about the Zettelstore version. +This allows you to check whether your installed Zettelstore is up to date. The name of the software (""Zettelstore"") and the build version information is given, as well as the compiler version, and an indication about the operating system and the processor architecture of that computer. The build version information is a string like ''1.0.2+351ae138b4''. The part ""1.0.2"" is the release version. ""+351ae138b4"" is a code uniquely identifying the version to the developer. -Everything after the release version is optional, eg. ""1.4.3"" is a valid build version information too. +Everything after the release version is optional, e.g. ""1.4.3"" is a valid build version information also. Example: ``` # zettelstore version Zettelstore 1.0.2+351ae138b4 (go1.16.5@linux/amd64) Licensed under the latest version of the EUPL (European Union Public License) ``` -In this example, Zettelstore is running in the released version ""1.0.2"" and was compiled using [[Go, version 1.16.5|https://golang.org/doc/go1.16]]. -The software was build for running under a Linux operating system with an ""amd64"" processor. +In this example, Zettelstore is running in the released version ""1.0.2"" and was compiled using [[Go, version 1.16.5|https://go.dev/doc/go1.16]]. +The software was built for running under a Linux operating system with an ""amd64"" processor. The build version is also stored in the public, [[predefined|00001005090000]] zettel titled ""[[Zettelstore Version|00000000000001]]"". However, to access this zettel, you need a [[running zettelstore|00001004051000]]. Index: docs/manual/00001004051000.zettel ================================================================== --- docs/manual/00001004051000.zettel +++ docs/manual/00001004051000.zettel @@ -2,11 +2,11 @@ title: The ''run'' sub-command role: manual tags: #command #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20220724162050 +modified: 20250627160733 === ``zettelstore run`` This starts the web service. ``` @@ -16,11 +16,11 @@ ; [!a|''-a PORT''] : Specifies the TCP port through which you can reach the [[administrator console|00001004100000]]. See the explanation of [[''admin-port''|00001004010000#admin-port]] for more details. ; [!c|''-c CONFIGFILE''] : Specifies ''CONFIGFILE'' as a file, where [[startup configuration data|00001004010000]] is read. - It is ignored, when the given file is not available, nor readable. + It is ignored if the given file is not available or not readable. Default: tries to read the following files in the ""current directory"": ''zettelstore.cfg'', ''zsconfig.txt'', ''zscfg.txt'', ''_zscfg'', and ''.zscfg''. ; [!d|''-d DIR''] : Specifies ''DIR'' as the directory that contains all zettel. Index: docs/manual/00001004051100.zettel ================================================================== --- docs/manual/00001004051100.zettel +++ docs/manual/00001004051100.zettel @@ -2,24 +2,23 @@ title: The ''run-simple'' sub-command role: manual tags: #command #configuration #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102221633 +modified: 20250627161010 === ``zettelstore run-simple`` -This sub-command is implicitly called, when a user starts Zettelstore by double-clicking on its GUI icon. +This sub-command is implicitly called when a user starts Zettelstore by double-clicking its GUI icon. It is a simplified variant of the [[''run'' sub-command|00001004051000]]. First, this sub-command checks if it can read a [[Zettelstore startup configuration|00001004010000]] file by trying the [[default values|00001004051000#c]]. If this is the case, ''run-simple'' just continues as the [[''run'' sub-command|00001004051000]], but ignores any command line options (including ''-d DIR'').[^This allows a [[curious user|00001003000000]] to become an intermediate user.] - -If no startup configuration was found, the sub-command allows only to specify a zettel directory. -The directory will be created automatically, if it does not exist. -This is a difference to the ''run'' sub-command, where the directory must exist. -In contrast to the ''run'' sub-command, other command line parameter are not allowed. +If no startup configuration is found, the sub-command only allows specifying a zettel directory. +The directory will be created automatically if it does not exist. +This differs from the ''run'' sub-command, where the directory must already exist. +Unlike the ''run'' sub-command, no other command-line parameters are allowed. ``` zettelstore run-simple [-d DIR] ``` Index: docs/manual/00001004059900.zettel ================================================================== --- docs/manual/00001004059900.zettel +++ docs/manual/00001004059900.zettel @@ -2,11 +2,11 @@ title: Command line flags for profiling the application role: manual tags: #command #configuration #manual #zettelstore syntax: zmk created: 20211122170506 -modified: 20211122174951 +modified: 20250627161347 If you want to measure potential bottlenecks within the software Zettelstore, there are two [[command line|00001004050000]] flags for enabling the measurement (also called __profiling__): ; ''-cpuprofile FILE'' @@ -20,6 +20,6 @@ The given ''FILE'' can be used to analyze the data via the tool ``go tool pprof FILE``. Please notice that ''-cpuprofile'' takes precedence over ''-memprofile''. You cannot measure both. -You also can use the [[administrator console|00001004100000]] to begin and end profiling manually for a already running Zettelstore. +You also can use the [[administrator console|00001004100000]] to start and stop profiling manually for an already running Zettelstore. Index: docs/manual/00001004101000.zettel ================================================================== --- docs/manual/00001004101000.zettel +++ docs/manual/00001004101000.zettel @@ -2,11 +2,11 @@ title: List of supported commands of the administrator console role: manual tags: #configuration #manual #zettelstore syntax: zmk created: 20210510141304 -modified: 20250102190201 +modified: 20250701130043 ; [!bye|''bye''] : Closes the connection to the administrator console. ; [!config|''config SERVICE''] : Displays all valid configuration keys for the given service. @@ -50,11 +50,11 @@ ``log-level NAME VALUE`` sets the log level for the given service or for the kernel. ''VALUE'' is either the name of the log level or its numerical value. ; [!metrics|''metrics''] : Displays some values that reflect the inner workings of Zettelstore. - See [[here|https://golang.org/pkg/runtime/metrics/]] for a technical description of these values. + See [[here|https://pkg.go.dev/runtime/metrics]] for a technical description of these values. ; [!next-config|''next-config''] : Displays next configuration data. It will be the current configuration, if the corresponding services is restarted. ``next-config`` shows all next configuration data. Index: docs/manual/00001005000000.zettel ================================================================== --- docs/manual/00001005000000.zettel +++ docs/manual/00001005000000.zettel @@ -2,16 +2,16 @@ title: Structure of Zettelstore role: manual tags: #design #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102191502 +modified: 20250702180913 -Zettelstore is a software that manages your zettel. -Since every zettel must be readable without any special tool, most zettel have to be stored as ordinary files within specific directories. -Typically, file names and file content must comply with specific rules so that Zettelstore can manage them. -If you add, delete, or change zettel files with other tools, e.g. a text editor, Zettelstore will monitor these actions. +Zettelstore is a software application that manages your zettel. +Since each zettel must be readable without any special tools, most of them are stored as ordinary files within specific directories. +Typically, both file names and file content must follow certain rules so that Zettelstore can manage them properly. +If you add, delete, or modify zettel files with other tools, e.g. a text editor, Zettelstore will monitor these changes. Zettelstore provides additional services to the user. Via the built-in [[web user interface|00001014000000]] you can work with zettel in various ways. For example, you are able to list zettel, to create new zettel, to edit them, or to delete them. You can view zettel details and relations between zettel. @@ -29,11 +29,11 @@ Every file in this directory that should be monitored by Zettelstore must have a file name that begins with 14 digits (0-9), the [[zettel identifier|00001006050000]]. If you create a new zettel via the [[web user interface|00001014000000]] or via the [[API|00001012053200]], the zettel identifier will be the timestamp of the current date and time (format is ''YYYYMMDDhhmmss''). This allows zettel to be sorted naturally by creation time. -Since the only restriction on zettel identifiers are the 14 digits, you are free to use other digit sequences. +Since the only restriction on zettel identifiers is that they consist of 14 digits, you are free to use other digit sequences. The [[configuration zettel|00001004020000]] is one prominent example, as well as these manual zettel. You can create these special zettel by manually renaming the underlying zettel files. It is allowed that the file name contains other characters after the 14 digits. These are ignored by Zettelstore. @@ -49,11 +49,11 @@ Since each zettel contains some metadata, e.g. the title of the figure, the question arises where these data should be stored. The solution is a meta-file with the same zettel identifier, but without a filename extension. Zettelstore recognizes this situation and reads in both files for the one zettel containing the figure. It maintains this relationship as long as these files exist. -In case of some textual zettel content you do not want to store the metadata and the zettel content in two different files. +In the case of some textual zettel content, you may not want to store the metadata and the zettel content in two separate files. Here the ''.zettel'' extension will signal that the metadata and the zettel content will be stored in the same file, separated by an empty line or a line with three dashes (""''-\-\-''"", also known as ""YAML separator""). === Predefined zettel Zettelstore contains some [[predefined zettel|00001005090000]] to work properly. @@ -81,12 +81,9 @@ === Boxes: alternative ways to store zettel As described above, a zettel may be stored either as a file inside a directory or within the Zettelstore software itself. Zettelstore allows other ways to store zettel by providing an abstraction called __box__.[^Formerly, zettel were stored physically in boxes, often made of wood.] -A file directory which stores zettel is called a ""directory box"". -But zettel may be also stored in a ZIP file, which is called ""file box"". -For testing purposes, zettel may be stored in volatile memory (called __RAM__). -This way is called ""memory box"". - -Other types of boxes could be added to Zettelstore. -What about a ""remote Zettelstore box""? +A file directory that stores zettel is called a ""directory box"". +Alternatively, zettel can also be stored in a ZIP file, known as a ""file box"". +For testing purposes, zettel can be stored in volatile memory (called __RAM__). +This method is referred to as a ""memory box"". Index: docs/manual/00001005090000.zettel ================================================================== --- docs/manual/00001005090000.zettel +++ docs/manual/00001005090000.zettel @@ -2,11 +2,11 @@ title: List of predefined zettel role: manual tags: #manual #reference #zettelstore syntax: zmk created: 20210126175322 -modified: 20250416180103 +modified: 20250627163000 The following table lists all predefined zettel with their purpose. The content of most[^To be more exact: zettel with an identifier greater or equal ''00000999999900'' will have their content indexed.] of these zettel will not be indexed by Zettelstore. You will not find zettel when searched for some content, e.g. ""[[query:european]]"" will not find the [[Zettelstore License|00000000000004]]. @@ -25,11 +25,11 @@ | [[00000000000011]] | Zettelstore Sx Engine | Statistics about the [[Sx|https://t73f.de/r/sx]] engine, which interprets symbolic expressions | [[00000000000020]] | Zettelstore Box Manager | Contains some statistics about zettel boxes and the index process | [[00000000000090]] | Zettelstore Supported Metadata Keys | Contains all supported metadata keys, their [[types|00001006030000]], and more | [[00000000000092]] | Zettelstore Supported Parser | Lists all supported values for metadata [[syntax|00001006020000#syntax]] that are recognized by Zettelstore | [[00000000000096]] | Zettelstore Startup Configuration | Contains the effective values of the [[startup configuration|00001004010000]] -| [[00000000000100]] | Zettelstore Runtime Configuration | Allows to [[configure Zettelstore at runtime|00001004020000]] +| [[00000000000100]] | Zettelstore Runtime Configuration | Allows you to [[configure Zettelstore at runtime|00001004020000]] | [[00000000010100]] | Zettelstore Base HTML Template | Contains the general layout of the HTML view | [[00000000010200]] | Zettelstore Login Form HTML Template | Layout of the login form, when authentication is [[enabled|00001010040100]] | [[00000000010300]] | Zettelstore List Zettel HTML Template | Used when displaying a list of zettel | [[00000000010401]] | Zettelstore Detail HTML Template | Layout for the HTML detail view of one zettel | [[00000000010402]] | Zettelstore Info HTML Template | Layout for the information view of a specific zettel @@ -40,11 +40,11 @@ | [[00000000019990]] | Zettelstore Sxn Base Code | Base sxn functions to build the templates | [[00000000020001]] | Zettelstore Base CSS | System-defined CSS file that is included by the [[Base HTML Template|00000000010100]] | [[00000000025001]] | Zettelstore User CSS | User-defined CSS file that is included by the [[Base HTML Template|00000000010100]] | [[00000000040001]] | Generic Emoji | Image that is shown if [[original image reference|00001007040322]] is invalid | [[00000000060010]] | zettel | [[Role zettel|00001012051800]] for the role ""[[zettel|00001006020100#zettel]]"" -| [[00000000060020]] | configuration | [[Role zettel|00001012051800]] for the role ""[[confguration|00001006020100#configuration]]"" +| [[00000000060020]] | configuration | [[Role zettel|00001012051800]] for the role ""[[configuration|00001006020100#configuration]]"" | [[00000000060030]] | role | [[Role zettel|00001012051800]] for the role ""[[role|00001006020100#role]]"" | [[00000000060040]] | tag | [[Role zettel|00001012051800]] for the role ""[[tag|00001006020100#tag]]"" | [[00000000080001]] | Lists Menu | Default items of the ""Lists"" menu; see [[lists-menu-zettel|00001004020000#lists-menu-zettel]] for customization options | [[00000000090000]] | New Menu | Contains items that should be in the zettel template menu | [[00000000090001]] | New Zettel | Template for a new zettel with role ""[[zettel|00001006020100#zettel]]"" Index: docs/manual/00001006010000.zettel ================================================================== --- docs/manual/00001006010000.zettel +++ docs/manual/00001006010000.zettel @@ -2,14 +2,14 @@ title: Syntax of Metadata role: manual tags: #manual #syntax #zettelstore syntax: zmk created: 20210126175322 -modified: 20240219193158 +modified: 20250701130629 The metadata of a zettel is a collection of key-value pairs. -The syntax roughly resembles the internal header of an email ([[RFC5322|https://tools.ietf.org/html/rfc5322]]). +The syntax roughly resembles the internal header of an email ([[RFC5322|https://datatracker.ietf.org/doc/html/rfc5322]]). The key is a sequence of alphanumeric characters, a hyphen-minus character (""''-''"", U+002D) is also allowed. It begins at the first position of a new line. Uppercase letters of a key are translated to their lowercase equivalence. Index: docs/manual/00001006020000.zettel ================================================================== --- docs/manual/00001006020000.zettel +++ docs/manual/00001006020000.zettel @@ -2,11 +2,11 @@ title: Supported Metadata Keys role: manual tags: #manual #meta #reference #zettel #zettelstore syntax: zmk created: 20210126175322 -modified: 20250115163835 +modified: 20250701130724 Although you are free to define your own metadata, by using any key (according to the [[syntax|00001006010000]]), some keys have a special meaning that is enforced by Zettelstore. See the [[computed list of supported metadata keys|00000000000090]] for details. Most keys conform to a [[type|00001006030000]]. @@ -50,11 +50,13 @@ It is up to you to define required actions. ''expire'' is just a documentation. You could define a query and execute it regularly, for example [[query:expire? ORDER expire]]. Alternatively, a Zettelstore client software could define some actions when it detects expired zettel. ; [!folge|''folge''] -: Is a property that contains identifier of all zettel that reference this zettel through the [[''precursor''|#precursor]] value. +: Is a property that contains identifiers of all zettel that reference this zettel via the [[''precursor''|#precursor]] value. + + It is used to reference __folge zettel__, those that develop the idea of the current zettel a bit further, following a ""train of thought."" ; [!folge-role|''folge-role''] : Specifies a suggested [[''role''|#role]] the zettel should use in the future, if zettel currently has a preliminary role. ; [!forward|''forward''] : Property that contains all references that identify another zettel within the content of the zettel. ; [!id|''id''] @@ -64,11 +66,11 @@ : Language for the zettel. Mostly used for HTML rendering of the zettel. If not given, the value ''lang'' from the zettel of the [[current user|00001010040200]] will be used. If that value is also not available, it is read from the [[configuration zettel|00001004020000#lang]] will be used. - Use values according to the language definition of [[RFC-5646|https://tools.ietf.org/html/rfc5646]]. + Use values according to the language definition of [[RFC-5646|https://datatracker.ietf.org/doc/html/rfc5646]]. ; [!license|''license''] : Defines a license string that will be rendered. If not given, the value ''default-license'' from the [[configuration zettel|00001004020000#default-license]] will be used. ; [!modified|''modified''] : Date and time when a zettel was modified through Zettelstore. @@ -77,17 +79,14 @@ This is a computed value. There is no need to set it via Zettelstore. ; [!precursor|''precursor''] : References zettel for which this zettel is a ""Folgezettel"" / follow-up zettel. Basically the inverse of key [[''folge''|#folge]]. -; [!predecessor|''predecessor''] -: References the zettel that contains a previous version of the content. - In contrast to [[''precursor''|#precurso]] / [[''folge''|#folge]], this is a reference because of technical reasons, not because of content-related reasons. - Basically the inverse of key [[''successors''|#successors]]. ; [!prequel|''prequel''] -: Specifies a zettel that is conceptually a prequel zettel. - This is a zettel that occurred somehow before the current zettel. +: Specifies one or more zettel that are conceptually a prequel zettel. + These are zettel that occurred somehow before the current zettel. + Basically the inverse of key [[''sequel''|#sequel]]. ; [!published|''published''] : This property contains the timestamp of the last modification / creation of the zettel. If [[''modified''|#modified]] is set with a valid timestamp, it contains the its value. Otherwise, if [[''created''|#created]] is set with a valid timestamp, it contains the its value. Otherwise, if the zettel identifier contains a valid timestamp, the identifier is used. @@ -108,18 +107,14 @@ Can be used for selecting zettel. See [[supported zettel roles|00001006020100]]. If not given, it is ignored. ; [!sequel|''sequel''] : Is a property that contains identifier of all zettel that reference this zettel through the [[''prequel''|#prequel]] value. + + A __sequel zettel__ acts as a branching thought of the current zettel. ; [!subordinates|''subordinates''] : Is a property that contains identifier of all zettel that reference this zettel through the [[''superior''|#superior]] value. -; [!successors|''successors''] -: Is a property that contains identifier of all zettel that reference this zettel through the [[''predecessor''|#predecessor]] value. - Therefore, it references all zettel that contain a new version of the content and/or metadata. - In contrast to [[''folge''|#folge]], these are references because of technical reasons, not because of content-related reasons. - In most cases, zettel referencing the current zettel should be updated to reference a successor zettel. - The [[query reference|00001007040310]] [[query:backward? successors?]] lists all such zettel. ; [!summary|''summary''] : Summarizes the content of the zettel using plain text. ; [!superior|''superior''] : Specifies a zettel that is conceptually a superior zettel. This might be a more abstract zettel, or a zettel that should be higher in a hierarchy. Index: docs/manual/00001006020400.zettel ================================================================== --- docs/manual/00001006020400.zettel +++ docs/manual/00001006020400.zettel @@ -2,11 +2,11 @@ title: Supported values for metadata key ''read-only'' role: manual tags: #manual #meta #reference #zettel #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102205707 +modified: 20250602181627 A zettel can be marked as read-only, if it contains a metadata value for key [[''read-only''|00001006020000#read-only]]. If user authentication is [[enabled|00001010040100]], it is possible to allow some users to change the zettel, depending on their [[user role|00001010070300]]. Otherwise, the read-only mark is just a binary value. @@ -24,11 +24,11 @@ ; ""reader"" : Neither an unauthenticated user nor a user with role ""reader"" is allowed to modify the zettel. Users with role ""writer"" or the owner itself still can modify the zettel. ; ""writer"" -: Neither an unauthenticated user, nor users with roles ""reader"" or ""writer"" are allowed to modify the zettel. +: Neither an unauthenticated user nor users with roles ""reader"" or ""writer"" are allowed to modify the zettel. Only the owner of the Zettelstore can modify the zettel. If the metadata value is something else (one of the values ""true"" or ""owner"" is recommended), no user is allowed to modify the zettel through the [[web user interface|00001014000000]]. However, if the zettel is accessible as a file in a [[directory box|00001004011400]], the zettel could be modified using an external editor. Typically the owner of a Zettelstore has such access. Index: docs/manual/00001006050000.zettel ================================================================== --- docs/manual/00001006050000.zettel +++ docs/manual/00001006050000.zettel @@ -2,26 +2,26 @@ title: Zettel identifier role: manual tags: #design #manual #zettelstore syntax: zmk created: 20210126175322 -modified: 20250102165749 +modified: 20250627130018 Each zettel is given a unique identifier. To some degree, the zettel identifier is part of the metadata. Basically, the identifier is given by the [[Zettelstore|00001005000000]] software. Every zettel identifier consists of 14 digits. They resemble a timestamp: the first four digits could represent the year, the next two represent the month, followed by day, hour, minute, and second. -This allows to order zettel chronologically in a canonical way. +This allows zettel to be ordered chronologically in a canonical way. In most cases the zettel identifier is the timestamp when the zettel was created. However, the Zettelstore software just checks for exactly 14 digits. Anybody is free to assign a ""non-timestamp"" identifier to a zettel, e.g. with a month part of ""35"" or with ""99"" as the last two digits. -Some zettel identifier are [[reserved|00001006055000]] and should not be used otherwise. +Some zettel identifiers are [[reserved|00001006055000]] and should not be used otherwise. All identifiers of zettel initially provided by an empty Zettelstore begin with ""000000"", except the home zettel ''00010000000000''. -Zettel identifier of this manual have been chosen to begin with ""000010"". +Zettel identifiers of this manual have been chosen to begin with ""000010"". A zettel can have any identifier that contains 14 digits and that is not in use by another zettel managed by the same Zettelstore. Index: docs/manual/00001006055000.zettel ================================================================== --- docs/manual/00001006055000.zettel +++ docs/manual/00001006055000.zettel @@ -2,26 +2,27 @@ title: Reserved zettel identifier role: manual tags: #design #manual #zettelstore syntax: zmk created: 20210721105704 -modified: 20250102222416 +modified: 20250627152022 -[[Zettel identifier|00001006050000]] are typically created by examining the current date and time. -By renaming the name of the underlying zettel file, you are able to provide any sequence of 14 digits. +[[Zettel identifiers|00001006050000]] are typically created based on the current date and time. +By renaming the underlying zettel files, you can provide any sequence of 14 digits. To make things easier, you must not use zettel identifier that begin with four zeroes (''0000''). -All zettel provided by an empty zettelstore begin with six zeroes[^Exception: the predefined home zettel is ''00010000000000''. But you can [[configure|00001004020000#home-zettel]] another zettel with another identifier as the new home zettel.]. -Zettel identifier of this manual have be chosen to begin with ''000010''. +All zettel provided by an empty zettelstore begin with six zeroes[^Exception: the predefined home zettel is ''00010000000000''. +But you can [[configure|00001004020000#home-zettel]] another zettel with another identifier as the new home zettel.]. +Zettel identifiers of this manual have been chosen to begin with ''000010''. However, some external applications may need at least one defined zettel identifier to work properly. Zettel [[Zettelstore Application Directory|00000999999999]] (''00000999999999'') can be used to associate a name to a zettel identifier. For example, if your application is named ""app"", you create a metadata key ''app-zid''. Its value is the zettel identifier of the zettel that configures your application. -=== Reserved Zettel Identifier +=== Reserved Zettel Identifiers |= From | To | Description | 00000000000000 | 00000000000000 | This is an invalid zettel identifier | 00000000000001 | 00000999999999 | [[Predefined zettel|00001005090000]] | 00001000000000 | 00001099999999 | This [[Zettelstore manual|00001000000000]] Index: docs/manual/00001007000000.zettel ================================================================== --- docs/manual/00001007000000.zettel +++ docs/manual/00001007000000.zettel @@ -2,20 +2,20 @@ title: Zettelmarkup role: manual tags: #manual #zettelmarkup #zettelstore syntax: zmk created: 20210126175322 -modified: 20241212152823 +modified: 20250627161609 Zettelmarkup is a rich plain-text based markup language for writing zettel content. Besides the zettel content, Zettelmarkup is also used for specifying the title of a zettel, regardless of the syntax of a zettel. Zettelmarkup supports the longevity of stored notes by providing a syntax that any person can easily read, as well as a computer. Zettelmarkup can be much easier parsed / consumed by a software compared to other markup languages. Writing a parser for [[Markdown|https://daringfireball.net/projects/markdown/syntax]] is quite challenging. [[CommonMark|00001008010500]] is an attempt to make it simpler by providing a comprehensive specification, combined with an extra chapter to give hints for the implementation. -Zettelmarkup follows some simple principles that anybody who knows how ho write software should be able understand to create an implementation. +Zettelmarkup follows a few simple principles that anyone familiar with software development should be able to understand and implement. Zettelmarkup is a markup language on its own. This is in contrast to Markdown, which is basically a super-set of HTML: every HTML document is a valid Markdown document.[^To be precise: the content of the ``
`` of each HTML document is a valid Markdown document.] While HTML is a markup language that will probably last for a long time, it cannot be easily translated to other formats, such as PDF, JSON, or LaTeX. Additionally, it is allowed to embed other languages into HTML, such as CSS or even JavaScript. @@ -23,11 +23,11 @@ Zettelmarkup is a rich markup language, but it focuses on relatively short zettel content. It allows embedding other content, simple tables, quotations, description lists, and images. It provides a broad range of inline formatting, including __emphasized__, **strong**, ~~deleted~~{-} and >>inserted>> text. Footnotes[^like this] are supported, links to other zettel and to external material, as well as citation keys. -Zettelmarkup allows to include content from other zettel and to embed the result of a search query. +Zettelmarkup allows you to include content from other zettel and to embed the results of a search query. Zettelmarkup might be seen as a proprietary markup language. But if you want to use [[Markdown/CommonMark|00001008010000]] and you need support for footnotes or tables, you'll end up with proprietary extensions. However, the Zettelstore supports CommonMark as a zettel syntax, so you can mix both Zettelmarkup zettel and CommonMark zettel in one store to get the best of both worlds. Index: docs/manual/00001007030000.zettel ================================================================== --- docs/manual/00001007030000.zettel +++ docs/manual/00001007030000.zettel @@ -2,11 +2,11 @@ title: Zettelmarkup: Block-Structured Elements role: manual tags: #manual #zettelmarkup #zettelstore syntax: zmk created: 20210126175322 -modified: 20241212153023 +modified: 20250627132222 Every markup for blocks-structured elements (""blocks"") begins at the very first position of a line. There are five kinds of blocks: lists, one-line blocks, line-range blocks, tables, and paragraphs. @@ -20,35 +20,35 @@ Ordered lists, unordered lists, and quotation lists can be combined into [[nested lists|00001007030200]]. === One-line blocks -* [[Headings|00001007030300]] allow to structure the content of a zettel. +* [[Headings|00001007030300]] allow you to structure the content of a zettel. * The [[horizontal rule|00001007030400]] signals a thematic break * A [[transclusion|00001007031100]] embeds the content of one zettel into another. === Line-range blocks -This kind of blocks encompass at least two lines. -To be useful, they encompass more lines. -They begin with at least three identical characters at the first position of the beginning line. -They end at the line, that contains at least the same number of these identical characters, beginning at the first position of that line. +This kind of block encompasses at least two lines. +To be useful, it encompasses more lines. +It begins with at least three identical characters at the start of the first line. +It ends at the line that contains at least the same number of these identical characters, starting at the first position of that line. This allows line-range blocks to be nested. -Additionally, all other blocks elements are allowed in line-range blocks. +Additionally, all other block elements are allowed within line-range blocks. * [[Verbatim blocks|00001007030500]] do not interpret their content, * [[Quotation blocks|00001007030600]] specify a block-length quotations, * [[Verse blocks|00001007030700]] allow to enter poetry, lyrics and similar text, where line endings are important, * [[Region blocks|00001007030800]] just mark regions, e.g. for common formatting, -* [[Comment blocks|00001007030900]] allow to enter text that will be ignored when rendered. +* [[Comment blocks|00001007030900]] allow you to enter text that will be ignored when rendered. * [[Evaluation blocks|00001007031300]] specify some content to be evaluated by either Zettelstore or external software. * [[Math-mode blocks|00001007031400]] can be used to enter mathematical formulas / equations. * [[Inline-Zettel blocks|00001007031200]] provide a mechanism to specify zettel content with a new syntax without creating a new zettel. === Tables -Similar to lists are tables not specified explicitly. +Tables, similar to lists, are not specified explicitly. A sequence of table rows is considered a [[table|00001007031000]]. A table row itself is a sequence of table cells. === Paragraphs @@ -61,15 +61,15 @@ will be rendered in HTML as :::example = Heading Some text follows. ::: -This is because headings need at least three equal sign character. +This is because headings require at least three equal sign characters. A paragraph is essentially a sequence of [[inline-structured elements|00001007040000]]. Inline-structured elements can span more than one line. Paragraphs are separated by empty lines. If you want to specify a second paragraph inside a list item, or if you want to continue a paragraph on a second and more line within a list item, you must begin the paragraph with a certain number of space characters. The number of space characters depends on the kind of a list and the relevant nesting level. A line that begins with a space character and which is outside of a list or does not contain the right number of space characters is considered to be part of a paragraph. Index: docs/manual/00001007031200.zettel ================================================================== --- docs/manual/00001007031200.zettel +++ docs/manual/00001007031200.zettel @@ -2,11 +2,11 @@ title: Zettelmarkup: Inline-Zettel Block role: manual tags: #manual #zettelmarkup #zettelstore syntax: zmk created: 20220201142439 -modified: 20250102183744 +modified: 20250627131204 An inline-zettel block allows to specify some content with another syntax without creating a new zettel. This is useful, for example, if you want to embed some [[Markdown|00001008010500]] content, because you are too lazy to translate Markdown into Zettelmarkup. Another example is to specify HTML code to use it for some kind of web front-end framework. @@ -18,12 +18,12 @@ Alternatively, you can use the generic attribute to specify the syntax value. If no value is provided, ""[[text|00001008000000#text]]"" is assumed. Any other character in this first line will be ignored. -Text following the beginning line will not be interpreted, until a line begins with at least the same number of the same at-sign characters given at the beginning line. -This allows to enter some at-sign characters in the text that should not be interpreted at this level. +Text following the beginning line will not be interpreted until a line starts with at least the same number of identical at-sign characters as those in the beginning line. +This allows entering at-sign characters in the text that should not be interpreted at this level. Some examples: ```zmk @@@markdown A link to [this](00001007031200) zettel. @@ -50,12 +50,12 @@