/+ - Name: SisuDoc Spine, Doc Reform [a part of] - Description: documents, structuring, processing, publishing, search - static content generator - Author: Ralph Amissah [ralph.amissah@gmail.com] - Copyright: (C) 2015 (continuously updated, current 2026) Ralph Amissah, All Rights Reserved. - License: AGPL 3 or later: Spine (SiSU), a framework for document structuring, publishing and search Copyright (C) Ralph Amissah This program is free software: you can redistribute it and/or modify it under the terms of the GNU AFERO General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see [https://www.gnu.org/licenses/]. If you have Internet connection, the latest version of the AGPL should be available at these locations: [https://www.fsf.org/licensing/licenses/agpl.html] [https://www.gnu.org/licenses/agpl.html] - Spine (by Doc Reform, related to SiSU) uses standard: - docReform markup syntax - standard SiSU markup syntax with modified headers and minor modifications - docReform object numbering - standard SiSU object citation numbering & system - Homepages: [https://www.sisudoc.org] [https://www.doc-reform.org] - Git [https://git.sisudoc.org/] +/ module ocda.load; /+ ↓ what a path is, and loading it. . One place that decides, so that every reader and every writer accepts the same inputs and a new input type is added once. This mirrors spine's own ocda/abstraction/load.d, which names the sources it can enter the pipeline from and tells them apart by suffix. . Deliberately *not* here: .sst and .ssm markup. Reading markup means implementing the parser, which is spine's work and a far larger thing than a reader or a sample writer needs. This library reads abstractions. +/ import std.algorithm : endsWith; import ocda.model; import ocda.load_ssp; import ocda.load_db; import ocda.load_pod; enum Source { ssp, // .ssp, the abstraction as text ocda_db, // .ocda.db, the abstraction as sqlite pod, // .sisupod or .zip, an archive carrying a .ssp unknown, } Source sourceOf(string path) { if (path.endsWith(".ocda.db")) { return Source.ocda_db; } if (path.endsWith(".ssp")) { return Source.ssp; } /+ ↓ .sisupod is the archive spine writes now; .zip is what it wrote before, and every pod already published carries that name, so both are read. What is inside decides how it is opened, not the name. +/ if (path.endsWith(".sisupod")) { return Source.pod; } if (path.endsWith(".zip")) { return Source.pod; } if (path.endsWith(".db")) { return Source.ocda_db; } return Source.unknown; } string sourceName(Source s) { final switch (s) { case Source.ssp: return ".ssp (the abstraction as text)"; case Source.ocda_db: return ".ocda.db (the abstraction as sqlite)"; case Source.pod: return "a pod archive carrying a .ssp"; case Source.unknown: return "not an abstraction this library reads"; } } class OcdaLoadError : Exception { this(string msg) { super(msg); } } /+ ↓ load whatever the path is into the model. lang names which language to take from a .ocda.db, which holds every language of its document, and from a pod, which may carry more than one .ssp. A .ssp is one language by construction and ignores it. +/ OcdaDocument load(string path, string lang = "", bool any_version = false) { final switch (sourceOf(path)) { case Source.ssp: return parseSspFile(path); case Source.ocda_db: return loadDbFile(path, lang, any_version); case Source.pod: return loadPodFile(path, lang); case Source.unknown: throw new OcdaLoadError(path ~ ": " ~ sourceName(Source.unknown) ~ " (expected .ssp, .ocda.db, .sisupod or .zip)"); } }