├── .gitignore ├── nbb.edn ├── deps.edn ├── .github └── workflows │ ├── test.yml │ └── ci.yml ├── rdf_export.mjs ├── bb.edn ├── package.json ├── CHANGELOG.md ├── LICENSE.md ├── action.yml ├── src └── logseq │ ├── rdf_export │ └── config.cljs │ └── rdf_export.cljs ├── README.md ├── yarn.lock └── test └── fixtures ├── docs.ttl └── docs-with-labels.ttl /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.nbb 3 | /.cpcache 4 | -------------------------------------------------------------------------------- /nbb.edn: -------------------------------------------------------------------------------- 1 | {:deps 2 | {logseq/graph-parser 3 | {:git/url "https://github.com/logseq/logseq" 4 | :git/sha "65640ed8857199d89268295863cd556f5d90ea0b" 5 | :deps/root "deps/graph-parser"} 6 | #_{:local/root "../logseq/deps/graph-parser"}}} 7 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:aliases 2 | {:clj-kondo 3 | {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2025.06.05"}} 4 | :main-opts ["-m" "clj-kondo.main"]} 5 | :outdated 6 | {:replace-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}} 7 | :main-opts ["-m" "antq.core" "--exclude" "com.github.liquidz/antq"]}}} 8 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | name: Test the action 7 | steps: 8 | - name: Checkout 9 | uses: actions/checkout@v4 10 | 11 | # TODO: Test a real graph 12 | - name: Run github action 13 | uses: logseq/rdf-export@main 14 | -------------------------------------------------------------------------------- /rdf_export.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { loadFile, addClassPath } from '@logseq/nbb-logseq' 4 | import { fileURLToPath } from 'url'; 5 | import { dirname, resolve } from 'path'; 6 | 7 | const __dirname = fileURLToPath(dirname(import.meta.url)); 8 | addClassPath(resolve(__dirname, 'src')); 9 | const { main } = await loadFile(resolve(__dirname, 'src/logseq/rdf_export.cljs')); 10 | 11 | // Expects to be called as node X.js ... 12 | const args = process.argv.slice(2) 13 | main.apply(null, args); 14 | -------------------------------------------------------------------------------- /bb.edn: -------------------------------------------------------------------------------- 1 | {:tasks 2 | {test 3 | {:doc "Regression tests done against local docs repo" 4 | :task 5 | (do 6 | (shell "node rdf_export.mjs docs.ttl -d ../docs") 7 | ;; Fixtures are from docs version https://github.com/logseq/docs/commit/e591e1cfabab4fbb666600b751b3b014d9bd8367 8 | (shell "diff test/fixtures/docs.ttl docs.ttl") 9 | (shell "ttl docs.ttl") 10 | (shell "node rdf_export.mjs docs-with-labels.ttl -d ../docs --add-labels -c '{:exclude-properties [:initial-version :description]}'") 11 | (shell "diff test/fixtures/docs-with-labels.ttl docs-with-labels.ttl") 12 | (shell "ttl docs-with-labels.ttl") 13 | (println "Success!"))}}} 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@logseq/rdf-export", 3 | "version": "1.0.0", 4 | "description": "Exports a configurable subset of a logseq graph to RDF", 5 | "bin": { 6 | "logseq-rdf-export": "rdf_export.mjs" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/logseq/rdf-export.git" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/logseq/rdf-export/issues" 17 | }, 18 | "homepage": "https://github.com/logseq/rdf-export#readme", 19 | "dependencies": { 20 | "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v24", 21 | "mldoc": "^1.5.9", 22 | "n3": "^1.16.3", 23 | "turtle-validator": "^1.1.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | 8 | lint: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | 15 | - name: Set up Java 16 | uses: actions/setup-java@v4 17 | with: 18 | distribution: 'zulu' 19 | java-version: 17 20 | 21 | - name: Set up Clojure 22 | uses: DeLaGuardo/setup-clojure@master 23 | with: 24 | cli: 1.11.1.1237 25 | 26 | - name: Run clj-kondo lint 27 | run: clojure -M:clj-kondo --lint src 28 | 29 | - name: Check outdated dependencies 30 | uses: liquidz/antq-action@main 31 | with: 32 | excludes: 'clojure/brew-install' 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Unreleased 2 | 3 | * Use nbb-logseq and latest logseq deps that supports db-version 4 | 5 | ## 0.2.1 6 | * Remove unused :class-query and :additional-pages config options 7 | * Sort triples for easier diffing 8 | 9 | ## 0.2.0 10 | 11 | * Add support for block level exports 12 | * Use a block's page name as an identity when no name is found 13 | * Add :unique-id-properties config to uniquely identify a block when no 14 | :block/name exists 15 | * Add warnings when a block can't be exported and a :classes-without-ids to 16 | silence them for certain classes 17 | * Add :expand-macros config to expand macros in export 18 | * Add --add-labels CLI option to add labels to all entities and use more 19 | standard vocabs like rdfs and owl. This option allows feeding an export 20 | to a LLM e.g. https://github.com/emptycrown/llama-hub/tree/main/loader_hub/file/rdf 21 | * Add :exclude-properties config to exclude certain properties from export 22 | * Add :type-property config to look up an entity's class 23 | 24 | ## 0.1.0 25 | 26 | * Initial release with rdf being exported to a file and validated 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Logseq 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Logseq RDF Export' 2 | description: 'Exports a subset of a Logseq graph to RDF' 3 | inputs: 4 | rdfFile: 5 | description: "Name of RDF file to save export" 6 | required: true 7 | default: "test.ttl" 8 | directory: 9 | description: "Graph's root directory" 10 | required: false 11 | default: '.' 12 | 13 | runs: 14 | using: "composite" 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | with: 19 | repository: logseq/rdf-export 20 | path: .logseq-rdf-export 21 | 22 | - name: Set up Clojure 23 | uses: DeLaGuardo/setup-clojure@master 24 | with: 25 | cli: 1.11.1.1182 26 | bb: 1.0.164 27 | 28 | - name: Set up Node 29 | uses: actions/setup-node@v3 30 | with: 31 | node-version: '18' 32 | cache: 'yarn' 33 | cache-dependency-path: .logseq-rdf-export/yarn.lock 34 | 35 | - name: Fetch yarn deps 36 | run: cd .logseq-rdf-export && yarn install --immutable 37 | shell: bash 38 | 39 | - name: Nbb cache 40 | uses: actions/cache@v3 41 | id: nbb-deps 42 | with: 43 | path: | 44 | ~/.m2/repository 45 | ~/.gitlibs 46 | .logseq-rdf-export/.nbb/.cache 47 | key: ${{ runner.os }}-nbb-deps-${{ hashFiles('.logseq-rdf-export/nbb.edn') }} 48 | restore-keys: ${{ runner.os }}-nbb-deps- 49 | 50 | - name: Fetch nbb deps 51 | if: steps.nbb-deps.outputs.cache-hit != 'true' 52 | run: cd .logseq-rdf-export && yarn nbb-logseq -e ':fetching-deps' 53 | shell: bash 54 | 55 | - name: Export graph to RDF 56 | run: cd .logseq-rdf-export && node rdf_export.mjs ../${{ inputs.rdfFile }} --directory ${{ inputs.directory }} 57 | shell: bash 58 | 59 | - name: Validate RDF file 60 | run: cd .logseq-rdf-export && yarn ttl ../${{ inputs.rdfFile}} 61 | shell: bash 62 | -------------------------------------------------------------------------------- /src/logseq/rdf_export/config.cljs: -------------------------------------------------------------------------------- 1 | (ns logseq.rdf-export.config) 2 | 3 | (def default-config 4 | "Graph-specific config to define behaviors for this export" 5 | {;; Recommended: Base url for all pages in the graph 6 | :base-url 7 | "https://example.com/#/page/" 8 | 9 | ;; The rest of these config keys are optional: 10 | 11 | ;; Rdf format to write to. Defaults to turtle. 12 | ;; Other possible values - n-triples, n-quads, trig 13 | :format "turtle" 14 | ;; Shortens urls in turtle output 15 | :prefixes 16 | {:s "https://schema.org/"} 17 | ;; Property used to look up urls of property pages. Defaults 18 | ;; to :url. For example, in order to resolve the description property, 19 | ;; the description page has a url property with its full url. 20 | :url-property :url 21 | ;; Property used to look up a Class of an entity. Default to :type 22 | :type-property :type 23 | ;; When an entity doesn't have a unique string to identify it, usually through 24 | ;; :block/title, look up these properties in order 25 | :unique-id-properties [] 26 | ;; Properties that are excluded in export for all entities. 27 | ;; Useful if some properties cause issues with a rdf consumer 28 | :exclude-properties [] 29 | ;; When enabled expands macros in entities if they exist 30 | :expand-macros false 31 | ;; Silences warning messages for classes of entities that don't have a unique id 32 | :classes-without-ids #{} 33 | 34 | ;; The rest of the config determines what pages in your graph are included in 35 | ;; the output. All triples/properties of a page are included. 36 | ;; These config keys are all optional as they have useful defaults. 37 | ;; 38 | ;; Query to fetch all pages that are properties. 39 | ;; Defaults to pages with "type:: [[Property]]" 40 | :property-query 41 | '[:find (pull ?b [*]) 42 | :in $ % 43 | :where 44 | (page-property ?b :type "Property")] 45 | ;; Query to fetch all entities that are instances of classes. 46 | ;; Defaults to pages with "type:: [[X]]" where X are pages with 47 | ;; "type:: [[Class]]" 48 | :class-instances-query 49 | '[:find (pull ?b2 [*]) 50 | :in $ % 51 | :where 52 | (page-property ?b :type "Class") 53 | [?b :block/title ?n] 54 | (page-property ?b2 :type ?n)] 55 | ;; Query to fetch additional instances. 56 | ;; Useful for instances that aren't fetched by :class-instances-query 57 | ;; e.g. block-level instances. 58 | ;; Defaults to nil 59 | :additional-instances-query nil}) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | This is a [github action](https://github.com/features/actions) to export a 4 | configurable portion of a Logseq graph to [RDF](https://www.w3.org/RDF/). Some 5 | basic validation is also done on the exported rdf file. This action can also be 6 | run as a [CLI](#cli). 7 | 8 | ## Usage 9 | 10 | ### Setup 11 | 12 | By default, this action is configured to export the portion of your Logseq graph that: 13 | 14 | * has class pages with properties `type:: [[Class]]` 15 | * has property pages with properties `type:: [[Property]]` 16 | * has pages with properties `type:: [[X]]` where X are pages with `type:: [[Class]]` 17 | 18 | For an example of such a graph, see https://github.com/logseq/docs. If you would like 19 | to organize your graph differently, you can [configure it](#configuration). 20 | 21 | ### Github Action 22 | 23 | To setup this action, add the file `.github/workflows/ci.yml` to your graph's 24 | github repository with the following content: 25 | 26 | ``` yaml 27 | on: [push] 28 | 29 | jobs: 30 | rdf-export: 31 | runs-on: ubuntu-latest 32 | name: Test rdf export 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | 37 | - name: Export graph as RDF 38 | uses: logseq/rdf-export@main 39 | ``` 40 | 41 | That's it! This job will then run on future git pushes and build RDF files from your graph. 42 | 43 | NOTE: The above example defaults to picking up new changes. If you'd prefer to stay on a stable version use the format `logseq/rdf-export@VERSION` e.g. `logseq/rdf-export@v0.1.0`. See CHANGELOG.md for released versions. 44 | 45 | #### Action Inputs 46 | 47 | This action can take inputs e.g.: 48 | 49 | ```yaml 50 | - name: Export graph as RDF 51 | uses: logseq/rdf-export@main 52 | with: 53 | rdfFile: my-graph-name.ttl 54 | directory: logseq-graph-directory 55 | ``` 56 | 57 | This action has the following inputs: 58 | 59 | ##### `rdfFile` 60 | 61 | **Required:** Name of the exported rdf file. Defaults to `test.ttl`. 62 | 63 | ##### `directory` 64 | 65 | Optional: The directory of the graph to rdf. Defaults to `.`. 66 | 67 | #### Use with other actions 68 | 69 | Since this action produces a valid RDF file, it is easy to save this file for 70 | later usage using [upload-artifact](https://github.com/actions/upload-artifact): 71 | 72 | ```yaml 73 | ... 74 | - name: Export graph as RDF 75 | uses: logseq/rdf-export@main 76 | with: 77 | rdfFile: my-graph.ttl 78 | 79 | - uses: actions/upload-artifact@v4 80 | with: 81 | name: Exported RDF 82 | path: my-graph.ttl 83 | ``` 84 | 85 | ### CLI 86 | 87 | To use this as a CLI locally, first install 88 | [babashka](https://github.com/babashka/babashka#installation) and 89 | [clojure](https://clojure.org/guides/install_clojure). Then: 90 | 91 | ```sh 92 | $ git clone https://github.com/logseq/rdf-export 93 | $ cd rdf-export && yarn install 94 | $ yarn global add $PWD 95 | ``` 96 | 97 | Then use it from any logseq graph directory! 98 | ```sh 99 | $ logseq-rdf-export docs.ttl 100 | Parsing 301 files... 101 | ... 102 | Writing 295 triples to file docs.ttl 103 | ``` 104 | 105 | ## Configuration 106 | 107 | To configure how and what is exported to RDF, create a `.rdf-export/config.edn` 108 | file in your graph's directory. It's recommended to configure the `:base-url` 109 | key so that urls point to your Logseq graph. To configure what is exported, 110 | knowledge of [advanced 111 | queries](https://docs.logseq.com/#/page/advanced%20queries) is required. See 112 | [the config 113 | file](https://github.com/logseq/rdf-export/blob/main/src/logseq/rdf_export/config.cljs) 114 | for the full list of configuration keys. 115 | 116 | ## Development 117 | 118 | This github action use [nbb-logseq](https://github.com/logseq/nbb-logseq) and the [graph-parser 119 | library](https://github.com/logseq/logseq/tree/master/deps/graph-parser) to export a Logseq graph 120 | from its database. 121 | 122 | ## LICENSE 123 | See LICENSE.md 124 | 125 | ## Additional Links 126 | * https://github.com/logseq/graph-validator - Github action that this one is modeled after 127 | * https://github.com/Matdata-eu/logseq-rdf-export-docker - Docker image of this repository which 128 | also supports GitLab use 129 | * https://github.com/rdfjs/N3.js - Library that handles the rdf exporting 130 | * https://github.com/logseq/docs - Logseq graph that uses this action 131 | -------------------------------------------------------------------------------- /src/logseq/rdf_export.cljs: -------------------------------------------------------------------------------- 1 | (ns logseq.rdf-export 2 | "This ns converts a subset of a Logseq graph to an rdf file using 3 | https://github.com/rdfjs/N3.js' 4 | 5 | All of the above pages can be customized with query config options." 6 | (:require ["n3" :refer [DataFactory Writer]] 7 | ["fs" :as fs] 8 | ["path" :as path] 9 | [clojure.string :as string] 10 | [clojure.edn :as edn] 11 | [clojure.set :as set] 12 | [datascript.core :as d] 13 | [logseq.db.file-based.rules :as file-rules] 14 | [babashka.cli :as cli] 15 | [logseq.graph-parser.cli :as gp-cli] 16 | [logseq.rdf-export.config :as config] 17 | [datascript.transit :as dt])) 18 | 19 | (defn- create-entities 20 | "Given a seq of block maps and config options, create entities which consist 21 | of the block's properties and a few built in block attributes" 22 | [{:keys [exclude-properties expand-entity-fn]} result] 23 | (map 24 | (fn [block] 25 | (let [block-name (or (get-in block [:block/properties :title]) 26 | (:block/title block) 27 | ;; Use page name for non-journal pre-blocks 28 | (when-not (get-in block [:block/page :block/journal?]) 29 | (get-in block [:block/page :block/title])))] 30 | (cond-> 31 | (-> (:block/properties block) 32 | ;; TODO: Add proper tags support 33 | (dissoc :title :tags) 34 | ((fn [x] (apply dissoc x exclude-properties))) 35 | expand-entity-fn) 36 | (some? block-name) 37 | (assoc :block/title block-name)))) 38 | result)) 39 | 40 | (defn- page-url [page-name config] 41 | (str (:base-url config) (js/encodeURIComponent page-name))) 42 | 43 | ;; overly permissive but nothing harmful yet 44 | (defn- url? [s] 45 | (re-matches #"\S+://\S+" s)) 46 | 47 | (defn- triplify 48 | "Turns an entity map into a coll of triples" 49 | [m 50 | {:keys [url-property type-property classes-without-ids unique-id-properties] :as config} 51 | property-map] 52 | (if-let [subject (if (:block/title m) 53 | (page-url (:block/title m) config) 54 | (some #(when-let [v (m %)] 55 | (if (url? v) v (page-url v config))) 56 | unique-id-properties))] 57 | (mapcat 58 | (fn [prop] 59 | (map #(vector 60 | subject 61 | ;; predicate 62 | (or (url-property (get property-map prop)) 63 | (page-url (name prop) config)) 64 | ;; object 65 | %) 66 | (let [v (m prop)] 67 | ;; If a collection, they are refs/pages 68 | (if (coll? v) (map #(page-url % config) v) [v])))) 69 | (keys m)) 70 | (do 71 | (when (empty? (set/intersection classes-without-ids (m type-property))) 72 | (println "Skip entity b/c no name or url for entity - " (pr-str m))) 73 | []))) 74 | 75 | (defn- block->label-triple [block] 76 | [(:url block) 77 | "http://www.w3.org/2000/01/rdf-schema#label" 78 | (:block/title block)]) 79 | 80 | (defn- build-alias-triples 81 | [ents config] 82 | (->> ents 83 | (filter :alias) 84 | (mapcat #(map (fn [alias] 85 | (block->label-triple 86 | {:url (page-url alias config) 87 | :block/title (:block/title %)})) 88 | (:alias %))))) 89 | 90 | (defn- add-class-instances [db config property-map {:keys [add-labels]}] 91 | (let [ents (->> (d/q (:class-instances-query config) 92 | db 93 | [(:page-property file-rules/query-dsl-rules)]) 94 | (map first) 95 | (create-entities config))] 96 | (concat 97 | (mapcat #(triplify % config property-map) ents) 98 | (when add-labels 99 | (build-alias-triples ents config))))) 100 | 101 | (defn- add-additional-instances [db config property-map {:keys [add-labels]}] 102 | (let [ents (->> (d/q (:additional-instances-query config) 103 | db 104 | []) 105 | (map first) 106 | (create-entities config))] 107 | (concat 108 | (mapcat #(triplify % config property-map) ents) 109 | (when add-labels 110 | (build-alias-triples ents config))))) 111 | 112 | (defn- create-quads [_writer db config {:keys [add-labels] :as options}] 113 | (let [properties (->> (d/q (:property-query config) 114 | db 115 | [(:page-property file-rules/query-dsl-rules)]) 116 | (map first) 117 | (create-entities config)) 118 | built-in-properties {:block/title 119 | {:url (if add-labels 120 | "http://www.w3.org/2000/01/rdf-schema#label" 121 | "https://schema.org/name")} 122 | :alias 123 | {:url (if add-labels 124 | "http://www.w3.org/2002/07/owl#sameAs" 125 | "https://schema.org/sameAs")}} 126 | property-map (into built-in-properties 127 | (map (juxt (comp keyword :block/title) identity) 128 | properties))] 129 | (set 130 | (concat 131 | (add-class-instances db config property-map options) 132 | (when (seq (:additional-instances-query config)) 133 | (add-additional-instances db config property-map options)) 134 | (when add-labels 135 | (map (fn [[k v]] 136 | (block->label-triple 137 | {:url (:url v) :block/title (name k)})) 138 | (dissoc built-in-properties :block/title))))))) 139 | 140 | (defn- add-quads [writer quads] 141 | (doseq [[q1 q2 q3] 142 | (map (fn [q] 143 | (map #(if (and (string? %) (url? %)) 144 | (.namedNode DataFactory %) 145 | (.literal DataFactory %)) 146 | q)) 147 | (sort quads))] 148 | (.addQuad writer (.quad DataFactory q1 q2 q3)))) 149 | 150 | (defn- read-config [config] 151 | (try 152 | (edn/read-string config) 153 | (catch :default _ 154 | (println "Error: Failed to parse config. Make sure it is valid EDN") 155 | (js/process.exit 1)))) 156 | 157 | (defn get-graph-config [dir user-config] 158 | (merge-with (fn [v1 v2] 159 | (if (and (map? v1) (map? v2)) 160 | (merge v1 v2) v2)) 161 | config/default-config 162 | (when (fs/existsSync (path/join dir ".rdf-export" "config.edn")) 163 | (read-config 164 | (str (fs/readFileSync (path/join dir ".rdf-export" "config.edn"))))) 165 | (when (seq user-config) 166 | (read-config user-config)))) 167 | 168 | (def spec 169 | "Options spec" 170 | ;; Adds labels for all entities that are missing them e.g. properties and 171 | ;; aliased entities 172 | {:add-labels {:coerce :boolean 173 | :alias :a 174 | :desc "Add rdfs:labels for all entities"} 175 | :cache-dir {:alias :C 176 | :desc "Cache directory for db"} 177 | :config {:alias :c 178 | :desc "Edn config map"} 179 | :directory {:desc "Graph directory to export" 180 | :alias :d 181 | :default "."} 182 | :help {:alias :h 183 | :coerce :boolean 184 | :desc "Print help"}}) 185 | 186 | (defn- get-db 187 | "If cached db exists get it, otherwise parse for a fresh db" 188 | [graph-dir cache-dir] 189 | ;; cache-db from https://github.com/logseq/bb-tasks 190 | (let [cache-file (path/join (or cache-dir ".") ".cached-db-transit.json")] 191 | (if (fs/existsSync cache-file) 192 | (do 193 | (println "Reading from cached db") 194 | (dt/read-transit-str (fs/readFileSync cache-file))) 195 | (let [{:keys [conn]} (gp-cli/parse-graph graph-dir {:verbose false})] @conn)))) 196 | 197 | (defn- macro-subs 198 | [macro-content arguments] 199 | (loop [s macro-content 200 | args arguments 201 | n 1] 202 | (if (seq args) 203 | (recur 204 | (string/replace s (str "$" n) (first args)) 205 | (rest args) 206 | (inc n)) 207 | s))) 208 | 209 | (defn- macro-expand-entity 210 | "Checks each ent value for a macro and expands it if there's a logseq config for it" 211 | [m logseq-config] 212 | (update-vals m 213 | #(if-let [[_ macro args] (and (string? %) 214 | (seq (re-matches #"\{\{(\S+)\s+(.*)\}\}" %)))] 215 | (if-let [content (get-in logseq-config [:macros macro])] 216 | (macro-subs content (string/split args #"\s+")) 217 | %) 218 | %))) 219 | 220 | (defn write-rdf-file 221 | "Given a graph's dir, covert to rdf and write to given file." 222 | [dir file & [options]] 223 | (let [graph-config (get-graph-config dir (:config options)) 224 | db (get-db dir (:cache-dir options)) 225 | logseq-config (if (fs/existsSync (path/join dir "logseq" "config.edn")) 226 | (-> (path/join dir "logseq" "config.edn") fs/readFileSync str edn/read-string) 227 | {}) 228 | writer (Writer. (clj->js {:prefixes (:prefixes graph-config) 229 | :format (:format graph-config)})) 230 | graph-config' (if (:expand-macros graph-config) 231 | (assoc graph-config :expand-entity-fn #(macro-expand-entity % logseq-config)) 232 | (assoc graph-config :expand-entity-fn identity)) 233 | quads (create-quads writer db graph-config' options)] 234 | (add-quads writer quads) 235 | (.end writer (fn [_err result] 236 | (println "Writing" (count quads) "triples to file" file) 237 | (fs/writeFileSync file result))))) 238 | 239 | (defn -main [& args] 240 | (let [{:keys [directory help] :as options} (cli/parse-opts args {:spec spec}) 241 | _ (when (or help (zero? (count args))) 242 | (println (str "Usage: logseq-rdf-export FILE [OPTIONS]\nOptions:\n" 243 | (cli/format-opts {:spec spec}))) 244 | (js/process.exit 1)) 245 | ;; In CI, move up a directory since the script is run in subdirectory of 246 | ;; a project 247 | directory' (if js/process.env.CI (path/join ".." directory) directory)] 248 | (write-rdf-file directory' (first args) (select-keys options [:cache-dir :config :add-labels])))) 249 | 250 | #js {:main -main} 251 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v24": 6 | version "1.2.173-feat-db-v24" 7 | resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/3d5b78b0382c7253bf9874c1f38586dd338434f4" 8 | dependencies: 9 | import-meta-resolve "^4.1.0" 10 | 11 | abort-controller@^3.0.0: 12 | version "3.0.0" 13 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" 14 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== 15 | dependencies: 16 | event-target-shim "^5.0.0" 17 | 18 | ansi-regex@^2.0.0: 19 | version "2.1.1" 20 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 21 | integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== 22 | 23 | ansi-regex@^3.0.0: 24 | version "3.0.1" 25 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" 26 | integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== 27 | 28 | base64-js@^1.3.1: 29 | version "1.5.1" 30 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 31 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 32 | 33 | buffer@^6.0.3: 34 | version "6.0.3" 35 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" 36 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 37 | dependencies: 38 | base64-js "^1.3.1" 39 | ieee754 "^1.2.1" 40 | 41 | camelcase@^5.0.0: 42 | version "5.3.1" 43 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 44 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 45 | 46 | cliui@^4.0.0: 47 | version "4.1.0" 48 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" 49 | integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== 50 | dependencies: 51 | string-width "^2.1.1" 52 | strip-ansi "^4.0.0" 53 | wrap-ansi "^2.0.0" 54 | 55 | code-point-at@^1.0.0: 56 | version "1.1.0" 57 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 58 | integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== 59 | 60 | cross-spawn@^6.0.0: 61 | version "6.0.5" 62 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 63 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 64 | dependencies: 65 | nice-try "^1.0.4" 66 | path-key "^2.0.1" 67 | semver "^5.5.0" 68 | shebang-command "^1.2.0" 69 | which "^1.2.9" 70 | 71 | decamelize@^1.2.0: 72 | version "1.2.0" 73 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 74 | integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== 75 | 76 | end-of-stream@^1.1.0: 77 | version "1.4.4" 78 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 79 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 80 | dependencies: 81 | once "^1.4.0" 82 | 83 | event-target-shim@^5.0.0: 84 | version "5.0.1" 85 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" 86 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== 87 | 88 | events@^3.3.0: 89 | version "3.3.0" 90 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 91 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 92 | 93 | execa@^1.0.0: 94 | version "1.0.0" 95 | resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" 96 | integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== 97 | dependencies: 98 | cross-spawn "^6.0.0" 99 | get-stream "^4.0.0" 100 | is-stream "^1.1.0" 101 | npm-run-path "^2.0.0" 102 | p-finally "^1.0.0" 103 | signal-exit "^3.0.0" 104 | strip-eof "^1.0.0" 105 | 106 | find-up@^3.0.0: 107 | version "3.0.0" 108 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 109 | integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== 110 | dependencies: 111 | locate-path "^3.0.0" 112 | 113 | get-caller-file@^1.0.1: 114 | version "1.0.3" 115 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 116 | integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== 117 | 118 | get-stream@^4.0.0: 119 | version "4.1.0" 120 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" 121 | integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== 122 | dependencies: 123 | pump "^3.0.0" 124 | 125 | ieee754@^1.2.1: 126 | version "1.2.1" 127 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 128 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 129 | 130 | import-meta-resolve@^4.1.0: 131 | version "4.1.0" 132 | resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706" 133 | integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw== 134 | 135 | invert-kv@^2.0.0: 136 | version "2.0.0" 137 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" 138 | integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== 139 | 140 | is-fullwidth-code-point@^1.0.0: 141 | version "1.0.0" 142 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 143 | integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== 144 | dependencies: 145 | number-is-nan "^1.0.0" 146 | 147 | is-fullwidth-code-point@^2.0.0: 148 | version "2.0.0" 149 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 150 | integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== 151 | 152 | is-stream@^1.1.0: 153 | version "1.1.0" 154 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 155 | integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== 156 | 157 | isexe@^2.0.0: 158 | version "2.0.0" 159 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 160 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 161 | 162 | lcid@^2.0.0: 163 | version "2.0.0" 164 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" 165 | integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== 166 | dependencies: 167 | invert-kv "^2.0.0" 168 | 169 | locate-path@^3.0.0: 170 | version "3.0.0" 171 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 172 | integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== 173 | dependencies: 174 | p-locate "^3.0.0" 175 | path-exists "^3.0.0" 176 | 177 | map-age-cleaner@^0.1.1: 178 | version "0.1.3" 179 | resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" 180 | integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== 181 | dependencies: 182 | p-defer "^1.0.0" 183 | 184 | mem@^4.0.0: 185 | version "4.3.0" 186 | resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" 187 | integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== 188 | dependencies: 189 | map-age-cleaner "^0.1.1" 190 | mimic-fn "^2.0.0" 191 | p-is-promise "^2.0.0" 192 | 193 | mimic-fn@^2.0.0: 194 | version "2.1.0" 195 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 196 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 197 | 198 | mldoc@^1.5.9: 199 | version "1.5.9" 200 | resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc" 201 | integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ== 202 | dependencies: 203 | yargs "^12.0.2" 204 | 205 | n3@^1.16.3, n3@^1.4.0: 206 | version "1.16.3" 207 | resolved "https://registry.yarnpkg.com/n3/-/n3-1.16.3.tgz#d339dca14c79648b1595a3252c5410b800b896f8" 208 | integrity sha512-9caLSZuMW1kdlPxEN4ka6E4E8a5QKoZ2emxpW+zHMofI+Bo92nJhN//wNub15S5T9I4c6saEqdGEu+YXJqMZVA== 209 | dependencies: 210 | queue-microtask "^1.1.2" 211 | readable-stream "^4.0.0" 212 | 213 | nice-try@^1.0.4: 214 | version "1.0.5" 215 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 216 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 217 | 218 | npm-run-path@^2.0.0: 219 | version "2.0.2" 220 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 221 | integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== 222 | dependencies: 223 | path-key "^2.0.0" 224 | 225 | number-is-nan@^1.0.0: 226 | version "1.0.1" 227 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 228 | integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== 229 | 230 | once@^1.3.1, once@^1.4.0: 231 | version "1.4.0" 232 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 233 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 234 | dependencies: 235 | wrappy "1" 236 | 237 | os-locale@^3.0.0: 238 | version "3.1.0" 239 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" 240 | integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== 241 | dependencies: 242 | execa "^1.0.0" 243 | lcid "^2.0.0" 244 | mem "^4.0.0" 245 | 246 | p-defer@^1.0.0: 247 | version "1.0.0" 248 | resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" 249 | integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== 250 | 251 | p-finally@^1.0.0: 252 | version "1.0.0" 253 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 254 | integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== 255 | 256 | p-is-promise@^2.0.0: 257 | version "2.1.0" 258 | resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" 259 | integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== 260 | 261 | p-limit@^2.0.0: 262 | version "2.3.0" 263 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 264 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 265 | dependencies: 266 | p-try "^2.0.0" 267 | 268 | p-locate@^3.0.0: 269 | version "3.0.0" 270 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 271 | integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== 272 | dependencies: 273 | p-limit "^2.0.0" 274 | 275 | p-try@^2.0.0: 276 | version "2.2.0" 277 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 278 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 279 | 280 | path-exists@^3.0.0: 281 | version "3.0.0" 282 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 283 | integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== 284 | 285 | path-key@^2.0.0, path-key@^2.0.1: 286 | version "2.0.1" 287 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 288 | integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== 289 | 290 | process@^0.11.10: 291 | version "0.11.10" 292 | resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" 293 | integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== 294 | 295 | pump@^3.0.0: 296 | version "3.0.0" 297 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 298 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 299 | dependencies: 300 | end-of-stream "^1.1.0" 301 | once "^1.3.1" 302 | 303 | queue-microtask@^1.1.2: 304 | version "1.2.3" 305 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 306 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 307 | 308 | readable-stream@^4.0.0: 309 | version "4.3.0" 310 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba" 311 | integrity sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ== 312 | dependencies: 313 | abort-controller "^3.0.0" 314 | buffer "^6.0.3" 315 | events "^3.3.0" 316 | process "^0.11.10" 317 | 318 | require-directory@^2.1.1: 319 | version "2.1.1" 320 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 321 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 322 | 323 | require-main-filename@^1.0.1: 324 | version "1.0.1" 325 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" 326 | integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== 327 | 328 | semver@^5.5.0: 329 | version "5.7.1" 330 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 331 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 332 | 333 | set-blocking@^2.0.0: 334 | version "2.0.0" 335 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 336 | integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== 337 | 338 | shebang-command@^1.2.0: 339 | version "1.2.0" 340 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 341 | integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== 342 | dependencies: 343 | shebang-regex "^1.0.0" 344 | 345 | shebang-regex@^1.0.0: 346 | version "1.0.0" 347 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 348 | integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== 349 | 350 | signal-exit@^3.0.0: 351 | version "3.0.7" 352 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 353 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 354 | 355 | string-width@^1.0.1: 356 | version "1.0.2" 357 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 358 | integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== 359 | dependencies: 360 | code-point-at "^1.0.0" 361 | is-fullwidth-code-point "^1.0.0" 362 | strip-ansi "^3.0.0" 363 | 364 | string-width@^2.0.0, string-width@^2.1.1: 365 | version "2.1.1" 366 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 367 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 368 | dependencies: 369 | is-fullwidth-code-point "^2.0.0" 370 | strip-ansi "^4.0.0" 371 | 372 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 373 | version "3.0.1" 374 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 375 | integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== 376 | dependencies: 377 | ansi-regex "^2.0.0" 378 | 379 | strip-ansi@^4.0.0: 380 | version "4.0.0" 381 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 382 | integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== 383 | dependencies: 384 | ansi-regex "^3.0.0" 385 | 386 | strip-eof@^1.0.0: 387 | version "1.0.0" 388 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 389 | integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== 390 | 391 | turtle-validator@^1.1.1: 392 | version "1.1.1" 393 | resolved "https://registry.yarnpkg.com/turtle-validator/-/turtle-validator-1.1.1.tgz#7077544a85ed330231fa1cab15bac18cf17c0f39" 394 | integrity sha512-k7HgLYUATigmdMvU7cdzvW6hOORwX7tBLBoFzXC0wIlN1hrvmJcJouElc+qVvIiJlBkiDY8jkxMenQ+HrVyS9w== 395 | dependencies: 396 | n3 "^1.4.0" 397 | 398 | which-module@^2.0.0: 399 | version "2.0.0" 400 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 401 | integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== 402 | 403 | which@^1.2.9: 404 | version "1.3.1" 405 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 406 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 407 | dependencies: 408 | isexe "^2.0.0" 409 | 410 | wrap-ansi@^2.0.0: 411 | version "2.1.0" 412 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 413 | integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== 414 | dependencies: 415 | string-width "^1.0.1" 416 | strip-ansi "^3.0.1" 417 | 418 | wrappy@1: 419 | version "1.0.2" 420 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 421 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 422 | 423 | "y18n@^3.2.1 || ^4.0.0": 424 | version "4.0.3" 425 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" 426 | integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== 427 | 428 | yargs-parser@^11.1.1: 429 | version "11.1.1" 430 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" 431 | integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== 432 | dependencies: 433 | camelcase "^5.0.0" 434 | decamelize "^1.2.0" 435 | 436 | yargs@^12.0.2: 437 | version "12.0.5" 438 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" 439 | integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== 440 | dependencies: 441 | cliui "^4.0.0" 442 | decamelize "^1.2.0" 443 | find-up "^3.0.0" 444 | get-caller-file "^1.0.1" 445 | os-locale "^3.0.0" 446 | require-directory "^2.1.1" 447 | require-main-filename "^1.0.1" 448 | set-blocking "^2.0.0" 449 | string-width "^2.0.0" 450 | which-module "^2.0.0" 451 | y18n "^3.2.1 || ^4.0.0" 452 | yargs-parser "^11.1.1" 453 | -------------------------------------------------------------------------------- /test/fixtures/docs.ttl: -------------------------------------------------------------------------------- 1 | @prefix s: . 2 | @prefix d: . 3 | 4 | d:Academic a d:FeatureTag; 5 | s:name "Academic". 6 | a d:Feature; 7 | d:platforms ; 8 | s:description "Advanced queries are written with [Datalog](https://en.wikipedia.org/wiki/Datalog) and query the [Datascript](https://github.com/tonsky/datascript) database."; 9 | s:name "Advanced Queries". 10 | a d:Feature; 11 | d:platforms , ; 12 | s:description "Advanced functionality that can be invoked from any block"; 13 | s:name "Advanced commands". 14 | a d:Platform; 15 | s:name "All Platforms". 16 | a d:Feature; 17 | d:platforms ; 18 | s:description "Page dedicated to page management - search, delete and sort pages."; 19 | s:name "All pages". 20 | d:Android a d:Platform; 21 | s:name "Android". 22 | a d:Feature; 23 | d:initial-version "unreleased"; 24 | d:platforms d:Desktop; 25 | s:name "Assets alias". 26 | a d:Feature; 27 | d:platforms ; 28 | s:description "Clickable link to a particular Logseq block e.g. `((123e4567-e89b-12d3-a456-426614174000))`. Produced by putting a unique [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) inside parenthesis `(())`"; 29 | s:name "Block Reference"; 30 | s:sameAs . 31 | a d:Feature; 32 | d:platforms ; 33 | s:description "Also known as block embedding, this allows a portion of a page to be displayed within another. Edits made to the embedded content are also made in the referenced content."; 34 | s:name "Block embed"; 35 | s:sameAs . 36 | d:Boolean a d:Class; 37 | s:name "Boolean"; 38 | s:url s:Boolean; 39 | d:DataType. 40 | d:Calculator a d:Command; 41 | s:description "The calculator supports basic operations like `+ - / * ^` and advanced operations (factorial, modular division, and scientific functions)."; 42 | s:name "Calculator". 43 | d:Class a d:Class; 44 | d:sameas ; 45 | s:description "Defines user defined classes/types in this graph"; 46 | s:name "Class"; 47 | s:url d:Class; 48 | d:Thing. 49 | a d:Feature; 50 | d:platforms , ; 51 | s:description "Run ClojureScript in a block using [sci](https://github.com/babashka/sci)"; 52 | s:name "ClojureScript Eval in a Block". 53 | d:Cloze a d:Command; 54 | s:description d:Flashcards; 55 | s:name "Cloze". 56 | a d:Feature; 57 | d:platforms ; 58 | s:description d:Codemirror; 59 | s:name "Code block". 60 | d:Command a d:Class; 61 | s:description , ; 62 | s:name "Command"; 63 | s:url d:Command; 64 | d:Feature. 65 | d:Commands a d:Feature; 66 | d:platforms , ; 67 | s:description "Functionality that can be invoked from any block"; 68 | s:name "Commands". 69 | a d:Feature; 70 | d:platforms , ; 71 | s:description "Describes copy and the difference between formatted and raw paste"; 72 | s:name "Copy and Paste". 73 | a d:Feature; 74 | d:platforms , ; 75 | s:name "Custom theme". 76 | d:DataType a d:Class; 77 | s:description "Provides basic data types such as integers, strings, etc. See https://www.w3.org/TR/rdf12-concepts/#section-Datatypes for additional datatypes that could be possible"; 78 | s:name "DataType"; 79 | s:url s:DataType; 80 | d:Class. 81 | d:Desktop a d:Platform; 82 | s:description "Desktop environments we support are osx, linux and windows. We use [Electron](https://www.electronjs.org/) for desktop."; 83 | s:name "Desktop". 84 | d:Draw a d:Command; 85 | s:description "Draw in blocks using an embedded Excalidraw canvas"; 86 | s:name "Draw". 87 | d:Export a d:Feature; 88 | d:platforms ; 89 | s:description "The Logseq Export feature allows users to export their data in various formats, including text, HTML, OPML, PNG, EDN, JSON, and standard Markdown. It supports exporting text selections, blocks, individual pages, or the entire graph with customizable options."; 90 | s:name "Export". 91 | d:Feature a d:Class; 92 | s:description "A user-facing piece of functionality. This can be a small piece or it can be a big one that consists of subfeatures"; 93 | s:name "Feature"; 94 | s:url d:Feature; 95 | d:Thing. 96 | d:FeatureTag a d:Class; 97 | s:description "Tags to categorize features"; 98 | s:name "FeatureTag"; 99 | s:url d:FeatureTag; 100 | d:Thing. 101 | a d:Feature; 102 | d:initial-version "0.8.9"; 103 | d:platforms d:Desktop; 104 | s:description "Allow users to migrate the filenames to the latest format"; 105 | s:name "Filename format". 106 | a d:Feature; 107 | d:initial-version "0.8.3"; 108 | d:platforms d:Desktop; 109 | s:description "Finds any text that is visible or loaded into the current page"; 110 | s:name "Find in page". 111 | d:Flashcards a d:Feature; 112 | d:platforms ; 113 | s:description "Cards are blocks that are intended to be used as an aid in memorization"; 114 | s:name "Flashcards". 115 | a d:Feature; 116 | d:platforms d:Desktop; 117 | s:description "Automatically save commit changes to a git repository."; 118 | s:name "Git Auto-Commit". 119 | a d:Feature; 120 | d:initial-version "0.8.6"; 121 | d:platforms d:Desktop; 122 | s:description ; 123 | s:name "Global config.edn". 124 | a d:Feature; 125 | d:initial-version "0.8.6"; 126 | d:platforms d:Desktop; 127 | s:description , ; 128 | s:name "Global configuration". 129 | d:Handbook a d:Feature; 130 | d:initial-version "0.9.20"; 131 | d:platforms , ; 132 | s:description "Provides in app documentation in the form of short tutorials"; 133 | s:name "Handbook". 134 | d:Headings a d:Feature; 135 | d:platforms ; 136 | s:description "Creating headings on a page"; 137 | s:name "Headings". 138 | d:Import a d:Feature; 139 | d:platforms , ; 140 | s:name "Import". 141 | a d:Feature; 142 | d:platforms ; 143 | s:name "Journals page". 144 | a d:Feature; 145 | d:platforms ; 146 | s:description "Provides keyboards shortcuts for running core commands and actions. Shortcuts can be customized through user configuration."; 147 | s:name "Keyboard shortcuts". 148 | a d:Feature; 149 | d:platforms ; 150 | s:description "Graph view of your whole graph"; 151 | s:name "Knowledge Graph"; 152 | s:sameAs . 153 | a ; 154 | s:name "Left sidebar". 155 | a d:Feature; 156 | d:platforms ; 157 | s:name "Linked References". 158 | a d:Feature; 159 | d:initial-version "0.8.15"; 160 | d:platforms d:Desktop; 161 | s:description "local HTTP server to access logseq's graph"; 162 | s:name "Local Http server". 163 | a d:Feature; 164 | d:platforms , , d:Web; 165 | s:description "Paid feature that provides encrypted synchronization of graphs between devices."; 166 | s:name "Logseq Sync". 167 | a d:Feature; 168 | d:platforms ; 169 | s:name "Logseq Sync Encryption". 170 | d:Macros a d:Feature; 171 | d:platforms ; 172 | s:description "Provides a way to write and maintain reusable text. This text can render as html and can invoke some other features"; 173 | s:name "Macros". 174 | a d:Feature; 175 | d:platforms ; 176 | s:description "Write and render math using https://katex.org/ syntax"; 177 | s:name "Math Block". 178 | d:Namespaces a d:Feature; 179 | d:platforms ; 180 | s:description "Used to group a set of related pages"; 181 | s:name "Namespaces". 182 | a d:Feature; 183 | d:initial-version "0.9.5"; 184 | d:platforms ; 185 | s:description "Provides numbered (ordered) lists with each list item being a block."; 186 | s:name "Numbered List". 187 | a d:Feature; 188 | d:platforms d:Desktop; 189 | s:name "PDF highlights". 190 | a d:Feature; 191 | d:platforms ; 192 | s:name "Page and block references". 193 | a d:Feature; 194 | d:platforms ; 195 | s:description ; 196 | s:name "Page embed"; 197 | s:sameAs . 198 | a d:Feature; 199 | d:platforms ; 200 | s:description ; 201 | s:name "Page graph". 202 | d:Platform a d:Class; 203 | s:description "One or more platforms, usually for a feature"; 204 | s:name "Platform"; 205 | s:url d:Platform; 206 | d:Thing. 207 | d:Plugins a d:Feature; 208 | d:platforms d:Desktop; 209 | s:description "Extends the functionality of logseq with third party tools"; 210 | s:name "Plugins". 211 | d:Properties a d:Feature; 212 | d:platforms ; 213 | s:description "Annotates any block or page with multiple pairs of values e.g. `rating:: 8` or `name:: foo`. Building block for organizing graphs"; 214 | s:name "Properties". 215 | d:Property a d:Class; 216 | d:sameas ; 217 | s:description "Defines user defined properties in this graph"; 218 | s:name "Property"; 219 | s:url d:Property; 220 | d:Thing. 221 | a d:Platform; 222 | s:description d:Web; 223 | s:name "Publish Web". 224 | d:Publishing a d:Feature; 225 | d:platforms d:Desktop; 226 | s:description ; 227 | s:name "Publishing". 228 | d:Queries a d:Feature; 229 | d:platforms ; 230 | s:description "Also known as simple queries"; 231 | s:name "Queries". 232 | d:Query a d:Command; 233 | s:description d:Queries; 234 | s:name "Query". 235 | a d:Feature; 236 | d:platforms ; 237 | s:description d:Queries; 238 | s:name "Query Builder". 239 | a d:Feature; 240 | d:initial-version "0.2.6"; 241 | d:platforms ; 242 | s:description "This runs custom transformations on a query's results, usually to calculate aggregations"; 243 | s:name "Query function". 244 | a ; 245 | s:description , d:Queries; 246 | s:name "Query table". 247 | a ; 248 | s:name "Right sidebar". 249 | d:Search a d:Feature; 250 | d:platforms ; 251 | s:name "Search". 252 | d:Settings a ; 253 | s:name "Settings". 254 | a d:Feature; 255 | d:initial-version "0.9.10"; 256 | d:platforms ; 257 | s:description "Snap shapes to canvas grid"; 258 | s:name "Snap to grid". 259 | d:String a d:Class; 260 | d:meta "Prefer the name string over text as it maps with xsd:string"; 261 | s:name "String"; 262 | s:url s:Text; 263 | d:DataType. 264 | d:StringWithRefs a d:Class; 265 | s:description "String that can have page references"; 266 | s:name "StringWithRefs"; 267 | s:url d:StringWithRefs; 268 | d:DataType. 269 | d:Tables a ; 270 | s:description "Tables are our first versioned component, accepting props to control the output."; 271 | s:name "Tables". 272 | d:Tags a d:Feature; 273 | d:platforms ; 274 | s:description "Annotates pages or blocks with a single value"; 275 | s:name "Tags". 276 | d:Tasks a d:Feature; 277 | d:platforms ; 278 | s:name "Tasks"; 279 | s:sameAs d:Todos. 280 | d:Thing a d:Class; 281 | s:description "The simplest concept which all classes inherit from."; 282 | s:name "Thing"; 283 | s:url s:Thing. 284 | a d:Class; 285 | s:description "A well-defined piece of the UI that usually has a name"; 286 | s:name "UI Element"; 287 | s:url ; 288 | d:Thing. 289 | a d:Feature; 290 | d:platforms , ; 291 | s:description "Allows users to revert or reapply changes made during their editing sessions. It also enhances the user experience by providing a convenient way to correct mistakes and explore alternative edits."; 292 | s:name "Undo and Redo". 293 | a d:Feature; 294 | d:platforms ; 295 | s:name "Unlinked References". 296 | d:Uri a d:Class; 297 | d:meta "Couldn't use URL since we're case insensitive and url is already taken"; 298 | s:name "Uri"; 299 | s:url s:URL; 300 | d:DataType. 301 | a d:Feature; 302 | d:platforms ; 303 | s:description "Users can configure logseq with a number of files."; 304 | s:name "User configuration". 305 | d:Web a d:Platform; 306 | s:name "Web". 307 | d:Whiteboard a d:Feature; 308 | d:platforms ; 309 | s:description "Put thoughts from your knowledge base as well as new ones next to each other on a spatial canvas together with shapes, drawings, website embeds and connectors. Built on a fork of [tldraw](https://github.com/tldraw/tldraw)."; 310 | s:name "Whiteboard"; 311 | s:sameAs d:Whiteboards. 312 | a ; 313 | s:description "Selected objects (eg. drawing, shapes, blocks, pages) all have an Object Action Bar that allows the user to change it's appearance (eg. color, text size and style) or interact with it (link, open in right sidebar)."; 314 | s:name "Whiteboard/Action Bar"; 315 | s:sameAs . 316 | a ; 317 | s:description ; 318 | s:name "Whiteboard/Canvas"; 319 | s:sameAs d:Canvas. 320 | a ; 321 | s:description ; 322 | s:name "Whiteboard/Context Menu"; 323 | s:sameAs . 324 | a ; 325 | s:description "A page where you can manage your Whiteboards."; 326 | s:name "Whiteboard/Dashboard"; 327 | s:sameAs . 328 | a d:Feature; 329 | d:initial-version "0.9.4"; 330 | d:platforms , ; 331 | s:description "Allows locking whiteboard elements, rendering them unmodifiable"; 332 | s:name "Whiteboard/Element locking"; 333 | s:sameAs . 334 | a ; 335 | s:name "Whiteboard/Embed"; 336 | s:sameAs . 337 | a d:Class; 338 | s:description d:Blocks, d:Graph, d:Pages, ; 339 | s:name "Whiteboard/Object"; 340 | s:sameAs , ; 341 | s:url ; 342 | . 343 | a ; 344 | d:supports "Link to page/block, Mobile context menu"; 345 | s:name "Whiteboard/Object/Image"; 346 | s:sameAs d:Image. 347 | a ; 348 | d:supports "Edit PDF, Link to page/block"; 349 | s:description "Embedded PDF"; 350 | s:name "Whiteboard/Object/PDF"; 351 | s:sameAs d:PDF. 352 | a ; 353 | d:supports "Url, Link to page/block, Mobile context menu"; 354 | s:description "Embedded tweets"; 355 | s:name "Whiteboard/Object/Tweet"; 356 | s:sameAs d:Tweet, d:Tweets. 357 | a ; 358 | d:supports "Url, Link to page/block, Mobile context menu"; 359 | s:description "Embedded Youtube videos"; 360 | s:name "Whiteboard/Object/Youtube"; 361 | s:sameAs d:Youtube, , . 362 | a ; 363 | d:supports "Reload, Url, Open, Link to page/block, Mobile context menu"; 364 | s:name "Whiteboard/Object/iFrame"; 365 | s:sameAs d:iFrame. 366 | a ; 367 | s:description d:Block, d:Canvas, , d:Page, d:Whiteboard; 368 | s:name "Whiteboard/Quick Add"; 369 | s:sameAs . 370 | a d:Class; 371 | s:description ; 372 | s:name "Whiteboard/Tool"; 373 | s:sameAs d:Tool, d:Tools, ; 374 | s:url ; 375 | d:Feature. 376 | a d:Tool, ; 377 | s:description "Connect any element on the canvas with a line. Add arrows to signal a direction. Add text on the connector. Can also be used to draw lines that are not connected to anything."; 378 | s:name "Whiteboard/Tool/Connector"; 379 | s:sameAs d:Connector. 380 | a d:Tool, ; 381 | d:initial-version "0.8.12"; 382 | d:platforms , ; 383 | s:description "Sets the global color"; 384 | s:name "Whiteboard/Tool/Global color swatch"; 385 | s:sameAs . 386 | a d:Tool, ; 387 | d:initial-version "0.9.3"; 388 | d:platforms , ; 389 | s:description "Sets the global scale level"; 390 | s:name "Whiteboard/Tool/Global scale select"; 391 | s:sameAs . 392 | a d:Tool, ; 393 | s:description "Freeform highlighting on the canvas"; 394 | s:name "Whiteboard/Tool/Highlight"; 395 | s:sameAs d:Highlight. 396 | a d:Tool, ; 397 | d:supports "Color Swatch, Link to page/block, Mobile context menu"; 398 | s:description "Freeform pencil drawings on the canvas"; 399 | s:name "Whiteboard/Tool/Pencil"; 400 | s:sameAs d:Pencil. 401 | a d:Tool, ; 402 | s:description "Create rectangle, circle and triangle shapes on the canvas"; 403 | s:name "Whiteboard/Tool/Shape"; 404 | s:sameAs d:Shape, d:Shapes. 405 | a d:Tool, ; 406 | s:description "Create circles"; 407 | s:name "Whiteboard/Tool/Shape/Circle"; 408 | s:sameAs d:Circle. 409 | a d:Tool, ; 410 | s:description "Create rectangles"; 411 | s:name "Whiteboard/Tool/Shape/Rectangle"; 412 | s:sameAs d:Rect, d:Rectangle. 413 | a d:Tool, ; 414 | s:description "Create triangles"; 415 | s:name "Whiteboard/Tool/Shape/Triangle"; 416 | s:sameAs d:Triangle. 417 | a d:Tool, ; 418 | s:description "Create text elements"; 419 | s:name "Whiteboard/Tool/Text"; 420 | s:sameAs d:Text. 421 | a ; 422 | s:name "Whiteboard/Toolbar"; 423 | s:sameAs d:Toolbar. 424 | a d:Feature; 425 | d:platforms d:Desktop; 426 | s:name "Youtube timestamp". 427 | d:Zotero a d:Feature; 428 | d:platforms , ; 429 | s:description "Built in integration that helps import your Zotero items as pages seamlessly. [Zotero](https://www.zotero.org/) is a free, easy-to-use tool to help you collect, organize, cite, and share research."; 430 | s:name "Zotero". 431 | a d:Feature; 432 | d:platforms ; 433 | s:description "Local config file, `logseq/config.edn`, is the main configuration file for a graph"; 434 | s:name "config.edn". 435 | a d:Feature; 436 | d:platforms ; 437 | s:description "Local config file, logseq/custom.css, loads custom css for a graph on startup"; 438 | s:name "custom.css". 439 | a d:Feature; 440 | d:platforms ; 441 | s:description "Local config file, logseq/custom.js, loads custom js for a graph on startup"; 442 | s:name "custom.js". 443 | d:description a d:Property; 444 | d:rangeIncludes d:StringWithRefs; 445 | s:name "description"; 446 | s:url s:description. 447 | d:domainincludes a d:Property; 448 | d:domainIncludes d:Property; 449 | d:rangeIncludes d:Class; 450 | d:sameas s:domainIncludes; 451 | s:description "A more useful version of rdfs:domain as it can be one of multiple values"; 452 | s:name "domainincludes"; 453 | s:url d:domainIncludes. 454 | a d:Feature; 455 | d:platforms ; 456 | s:description "Local config file, logseq/export.css, loads custom css for a published graph"; 457 | s:name "export.css". 458 | d:iOS a d:Platform; 459 | s:description "This refers to iOS on mobile. Only versions 14 and greater are supported."; 460 | s:name "iOS". 461 | d:initial-version a d:Property; 462 | d:domainIncludes d:Feature, d:Tool; 463 | d:rangeIncludes d:String; 464 | s:name "initial-version"; 465 | s:url d:initial-version. 466 | d:meta a d:Property; 467 | d:rangeIncludes d:String; 468 | s:description "Meta description field which usually discusses organizing thing instead of thing itself"; 469 | s:name "meta"; 470 | s:url d:meta. 471 | d:name a d:Property; 472 | d:rangeIncludes d:String; 473 | d:unique true; 474 | s:name "name"; 475 | s:url s:name. 476 | d:parent a d:Property; 477 | d:domainIncludes d:Class; 478 | d:rangeIncludes d:Class; 479 | s:description "Used to connect a class with its parent class"; 480 | s:name "parent"; 481 | s:url . 482 | d:platforms a d:Property; 483 | d:domainIncludes d:Feature, d:Tool; 484 | d:rangeIncludes d:Platform; 485 | s:name "platforms"; 486 | s:url d:platforms. 487 | a d:Feature; 488 | d:initial-version "0.8.9"; 489 | d:platforms d:Desktop; 490 | s:description d:Plugins; 491 | s:name "plugins.edn". 492 | d:rangeincludes a d:Property; 493 | d:domainIncludes d:Property; 494 | d:rangeIncludes d:Class; 495 | d:sameas s:rangeIncludes; 496 | s:description "List of values a property can have"; 497 | s:name "rangeincludes"; 498 | s:url d:rangeIncludes. 499 | d:sameAs a d:Property; 500 | d:rangeIncludes d:Uri; 501 | s:description "Indicates that two URIs are equivalent"; 502 | s:name "sameAs"; 503 | s:url . 504 | d:slide a d:Feature; 505 | d:platforms ; 506 | s:name "slide"; 507 | s:sameAs d:Presentation. 508 | d:supports a d:Property; 509 | d:domainIncludes d:Tool, ; 510 | d:rangeIncludes d:String; 511 | s:name "supports"; 512 | s:url d:supports. 513 | d:templates a d:Feature; 514 | d:platforms , ; 515 | s:name "templates". 516 | a d:Feature; 517 | d:platforms ; 518 | s:description "Provides a readable alias for a page. A page can have multiple aliases. Page references with the alias will automatically redirect to the original page"; 519 | s:name "term/alias"; 520 | s:sameAs . 521 | d:type a d:Property; 522 | d:rangeIncludes d:Class; 523 | s:name "type"; 524 | s:url . 525 | d:unique a d:Property; 526 | d:domainIncludes d:Property; 527 | d:rangeIncludes d:Boolean; 528 | s:name "unique"; 529 | s:url d:unique. 530 | d:url a d:Property; 531 | d:rangeIncludes d:Uri; 532 | d:unique true; 533 | s:name "url"; 534 | s:url s:url. 535 | -------------------------------------------------------------------------------- /test/fixtures/docs-with-labels.ttl: -------------------------------------------------------------------------------- 1 | @prefix s: . 2 | @prefix d: . 3 | 4 | "alias". 5 | d:Academic a d:FeatureTag; 6 | "Academic". 7 | a d:Feature; 8 | "Advanced Queries"; 9 | d:platforms . 10 | a d:Feature; 11 | "Advanced commands"; 12 | d:platforms , . 13 | a d:Platform; 14 | "All Platforms". 15 | a d:Feature; 16 | "All pages"; 17 | d:platforms . 18 | d:Android a d:Platform; 19 | "Android". 20 | a d:Feature; 21 | "Assets alias"; 22 | d:platforms d:Desktop. 23 | a d:Feature; 24 | "Block Reference"; 25 | ; 26 | d:platforms . 27 | a d:Feature; 28 | "Block embed"; 29 | ; 30 | d:platforms . 31 | d:Boolean a d:Class; 32 | "Boolean"; 33 | s:url s:Boolean; 34 | d:DataType. 35 | d:Calculator a d:Command; 36 | "Calculator". 37 | d:Canvas "Whiteboard/Canvas". 38 | d:Circle "Whiteboard/Tool/Shape/Circle". 39 | d:Class a d:Class; 40 | "Class"; 41 | d:sameas ; 42 | s:url d:Class; 43 | d:Thing. 44 | a d:Feature; 45 | "ClojureScript Eval in a Block"; 46 | d:platforms , . 47 | d:Cloze a d:Command; 48 | "Cloze". 49 | a d:Feature; 50 | "Code block"; 51 | d:platforms . 52 | d:Command a d:Class; 53 | "Command"; 54 | s:url d:Command; 55 | d:Feature. 56 | d:Commands a d:Feature; 57 | "Commands"; 58 | d:platforms , . 59 | d:Connector "Whiteboard/Tool/Connector". 60 | "Whiteboard/Context Menu". 61 | a d:Feature; 62 | "Copy and Paste"; 63 | d:platforms , . 64 | a d:Feature; 65 | "Custom theme"; 66 | d:platforms , . 67 | d:DataType a d:Class; 68 | "DataType"; 69 | s:url s:DataType; 70 | d:Class. 71 | d:Desktop a d:Platform; 72 | "Desktop". 73 | d:Draw a d:Command; 74 | "Draw". 75 | "Whiteboard/Element locking". 76 | d:Export a d:Feature; 77 | "Export"; 78 | d:platforms . 79 | d:Feature a d:Class; 80 | "Feature"; 81 | s:url d:Feature; 82 | d:Thing. 83 | d:FeatureTag a d:Class; 84 | "FeatureTag"; 85 | s:url d:FeatureTag; 86 | d:Thing. 87 | a d:Feature; 88 | "Filename format"; 89 | d:platforms d:Desktop. 90 | a d:Feature; 91 | "Find in page"; 92 | d:platforms d:Desktop. 93 | d:Flashcards a d:Feature; 94 | "Flashcards"; 95 | d:platforms . 96 | a d:Feature; 97 | "Git Auto-Commit"; 98 | d:platforms d:Desktop. 99 | "Whiteboard/Tool/Global color swatch". 100 | a d:Feature; 101 | "Global config.edn"; 102 | d:platforms d:Desktop. 103 | a d:Feature; 104 | "Global configuration"; 105 | d:platforms d:Desktop. 106 | "Whiteboard/Tool/Global scale select". 107 | "Knowledge Graph". 108 | d:Handbook a d:Feature; 109 | "Handbook"; 110 | d:platforms , . 111 | d:Headings a d:Feature; 112 | "Headings"; 113 | d:platforms . 114 | d:Highlight "Whiteboard/Tool/Highlight". 115 | d:Image "Whiteboard/Object/Image". 116 | d:Import a d:Feature; 117 | "Import"; 118 | d:platforms , . 119 | a d:Feature; 120 | "Journals page"; 121 | d:platforms . 122 | a d:Feature; 123 | "Keyboard shortcuts"; 124 | d:platforms . 125 | a d:Feature; 126 | "Knowledge Graph"; 127 | ; 128 | d:platforms . 129 | a ; 130 | "Left sidebar". 131 | a d:Feature; 132 | "Linked References"; 133 | d:platforms . 134 | a d:Feature; 135 | "Local Http server"; 136 | d:platforms d:Desktop. 137 | a d:Feature; 138 | "Logseq Sync"; 139 | d:platforms , , d:Web. 140 | a d:Feature; 141 | "Logseq Sync Encryption"; 142 | d:platforms . 143 | d:Macros a d:Feature; 144 | "Macros"; 145 | d:platforms . 146 | a d:Feature; 147 | "Math Block"; 148 | d:platforms . 149 | d:Namespaces a d:Feature; 150 | "Namespaces"; 151 | d:platforms . 152 | a d:Feature; 153 | "Numbered List"; 154 | d:platforms . 155 | "Whiteboard/Action Bar". 156 | d:PDF "Whiteboard/Object/PDF". 157 | a d:Feature; 158 | "PDF highlights"; 159 | d:platforms d:Desktop. 160 | a d:Feature; 161 | "Page and block references"; 162 | d:platforms . 163 | a d:Feature; 164 | "Page embed"; 165 | ; 166 | d:platforms . 167 | a d:Feature; 168 | "Page graph"; 169 | d:platforms . 170 | d:Pencil "Whiteboard/Tool/Pencil". 171 | d:Platform a d:Class; 172 | "Platform"; 173 | s:url d:Platform; 174 | d:Thing. 175 | d:Plugins a d:Feature; 176 | "Plugins"; 177 | d:platforms d:Desktop. 178 | d:Presentation "slide". 179 | d:Properties a d:Feature; 180 | "Properties"; 181 | d:platforms . 182 | d:Property a d:Class; 183 | "Property"; 184 | d:sameas ; 185 | s:url d:Property; 186 | d:Thing. 187 | a d:Platform; 188 | "Publish Web". 189 | d:Publishing a d:Feature; 190 | "Publishing"; 191 | d:platforms d:Desktop. 192 | d:Queries a d:Feature; 193 | "Queries"; 194 | d:platforms . 195 | d:Query a d:Command; 196 | "Query". 197 | a d:Feature; 198 | "Query Builder"; 199 | d:platforms . 200 | a d:Feature; 201 | "Query function"; 202 | d:platforms . 203 | a ; 204 | "Query table". 205 | "Whiteboard/Quick Add". 206 | d:Rect "Whiteboard/Tool/Shape/Rectangle". 207 | d:Rectangle "Whiteboard/Tool/Shape/Rectangle". 208 | a ; 209 | "Right sidebar". 210 | d:Search a d:Feature; 211 | "Search"; 212 | d:platforms . 213 | d:Settings a ; 214 | "Settings". 215 | d:Shape "Whiteboard/Tool/Shape". 216 | d:Shapes "Whiteboard/Tool/Shape". 217 | a d:Feature; 218 | "Snap to grid"; 219 | d:platforms . 220 | d:String a d:Class; 221 | "String"; 222 | d:meta "Prefer the name string over text as it maps with xsd:string"; 223 | s:url s:Text; 224 | d:DataType. 225 | d:StringWithRefs a d:Class; 226 | "StringWithRefs"; 227 | s:url d:StringWithRefs; 228 | d:DataType. 229 | d:Tables a ; 230 | "Tables". 231 | d:Tags a d:Feature; 232 | "Tags"; 233 | d:platforms . 234 | d:Tasks a d:Feature; 235 | "Tasks"; 236 | d:Todos; 237 | d:platforms . 238 | d:Text "Whiteboard/Tool/Text". 239 | d:Thing a d:Class; 240 | "Thing"; 241 | s:url s:Thing. 242 | d:Todos "Tasks". 243 | d:Tool "Whiteboard/Tool". 244 | d:Toolbar "Whiteboard/Toolbar". 245 | d:Tools "Whiteboard/Tool". 246 | d:Triangle "Whiteboard/Tool/Shape/Triangle". 247 | d:Tweet "Whiteboard/Object/Tweet". 248 | d:Tweets "Whiteboard/Object/Tweet". 249 | a d:Class; 250 | "UI Element"; 251 | s:url ; 252 | d:Thing. 253 | a d:Feature; 254 | "Undo and Redo"; 255 | d:platforms , . 256 | a d:Feature; 257 | "Unlinked References"; 258 | d:platforms . 259 | d:Uri a d:Class; 260 | "Uri"; 261 | d:meta "Couldn't use URL since we're case insensitive and url is already taken"; 262 | s:url s:URL; 263 | d:DataType. 264 | a d:Feature; 265 | "User configuration"; 266 | d:platforms . 267 | d:Web a d:Platform; 268 | "Web". 269 | d:Whiteboard a d:Feature; 270 | "Whiteboard"; 271 | d:Whiteboards; 272 | d:platforms . 273 | "Whiteboard/Dashboard". 274 | "Whiteboard/Embed". 275 | "Whiteboard/Object". 276 | "Whiteboard/Object". 277 | "Whiteboard/Tool". 278 | a ; 279 | "Whiteboard/Action Bar"; 280 | . 281 | a ; 282 | "Whiteboard/Canvas"; 283 | d:Canvas. 284 | a ; 285 | "Whiteboard/Context Menu"; 286 | . 287 | a ; 288 | "Whiteboard/Dashboard"; 289 | . 290 | a d:Feature; 291 | "Whiteboard/Element locking"; 292 | ; 293 | d:platforms , . 294 | a ; 295 | "Whiteboard/Embed"; 296 | . 297 | a d:Class; 298 | "Whiteboard/Object"; 299 | , ; 300 | s:url ; 301 | . 302 | a ; 303 | "Whiteboard/Object/Image"; 304 | d:Image; 305 | d:supports "Link to page/block, Mobile context menu". 306 | a ; 307 | "Whiteboard/Object/PDF"; 308 | d:PDF; 309 | d:supports "Edit PDF, Link to page/block". 310 | a ; 311 | "Whiteboard/Object/Tweet"; 312 | d:Tweet, d:Tweets; 313 | d:supports "Url, Link to page/block, Mobile context menu". 314 | a ; 315 | "Whiteboard/Object/Youtube"; 316 | d:Youtube, , ; 317 | d:supports "Url, Link to page/block, Mobile context menu". 318 | a ; 319 | "Whiteboard/Object/iFrame"; 320 | d:iFrame; 321 | d:supports "Reload, Url, Open, Link to page/block, Mobile context menu". 322 | a ; 323 | "Whiteboard/Quick Add"; 324 | . 325 | a d:Class; 326 | "Whiteboard/Tool"; 327 | d:Tool, d:Tools, ; 328 | s:url ; 329 | d:Feature. 330 | a d:Tool, ; 331 | "Whiteboard/Tool/Connector"; 332 | d:Connector. 333 | a d:Tool, ; 334 | "Whiteboard/Tool/Global color swatch"; 335 | ; 336 | d:platforms , . 337 | a d:Tool, ; 338 | "Whiteboard/Tool/Global scale select"; 339 | ; 340 | d:platforms , . 341 | a d:Tool, ; 342 | "Whiteboard/Tool/Highlight"; 343 | d:Highlight. 344 | a d:Tool, ; 345 | "Whiteboard/Tool/Pencil"; 346 | d:Pencil; 347 | d:supports "Color Swatch, Link to page/block, Mobile context menu". 348 | a d:Tool, ; 349 | "Whiteboard/Tool/Shape"; 350 | d:Shape, d:Shapes. 351 | a d:Tool, ; 352 | "Whiteboard/Tool/Shape/Circle"; 353 | d:Circle. 354 | a d:Tool, ; 355 | "Whiteboard/Tool/Shape/Rectangle"; 356 | d:Rect, d:Rectangle. 357 | a d:Tool, ; 358 | "Whiteboard/Tool/Shape/Triangle"; 359 | d:Triangle. 360 | a d:Tool, ; 361 | "Whiteboard/Tool/Text"; 362 | d:Text. 363 | a ; 364 | "Whiteboard/Toolbar"; 365 | d:Toolbar. 366 | d:Whiteboards "Whiteboard". 367 | d:Youtube "Whiteboard/Object/Youtube". 368 | a d:Feature; 369 | "Youtube timestamp"; 370 | d:platforms d:Desktop. 371 | "Whiteboard/Object/Youtube". 372 | "Whiteboard/Object/Youtube". 373 | d:Zotero a d:Feature; 374 | "Zotero"; 375 | d:platforms , . 376 | a d:Feature; 377 | "config.edn"; 378 | d:platforms . 379 | a d:Feature; 380 | "custom.css"; 381 | d:platforms . 382 | a d:Feature; 383 | "custom.js"; 384 | d:platforms . 385 | d:description a d:Property; 386 | "description"; 387 | d:rangeIncludes d:StringWithRefs; 388 | s:url s:description. 389 | d:domainincludes a d:Property; 390 | "domainincludes"; 391 | d:domainIncludes d:Property; 392 | d:rangeIncludes d:Class; 393 | d:sameas s:domainIncludes; 394 | s:url d:domainIncludes. 395 | a d:Feature; 396 | "export.css"; 397 | d:platforms . 398 | d:iFrame "Whiteboard/Object/iFrame". 399 | d:iOS a d:Platform; 400 | "iOS". 401 | d:initial-version a d:Property; 402 | "initial-version"; 403 | d:domainIncludes d:Feature, d:Tool; 404 | d:rangeIncludes d:String; 405 | s:url d:initial-version. 406 | d:meta a d:Property; 407 | "meta"; 408 | d:rangeIncludes d:String; 409 | s:url d:meta. 410 | d:name a d:Property; 411 | "name"; 412 | d:rangeIncludes d:String; 413 | d:unique true; 414 | s:url s:name. 415 | "term/alias". 416 | d:parent a d:Property; 417 | "parent"; 418 | d:domainIncludes d:Class; 419 | d:rangeIncludes d:Class; 420 | s:url . 421 | d:platforms a d:Property; 422 | "platforms"; 423 | d:domainIncludes d:Feature, d:Tool; 424 | d:rangeIncludes d:Platform; 425 | s:url d:platforms. 426 | a d:Feature; 427 | "plugins.edn"; 428 | d:platforms d:Desktop. 429 | d:rangeincludes a d:Property; 430 | "rangeincludes"; 431 | d:domainIncludes d:Property; 432 | d:rangeIncludes d:Class; 433 | d:sameas s:rangeIncludes; 434 | s:url d:rangeIncludes. 435 | d:sameAs a d:Property; 436 | "sameAs"; 437 | d:rangeIncludes d:Uri; 438 | s:url . 439 | d:slide a d:Feature; 440 | "slide"; 441 | d:Presentation; 442 | d:platforms . 443 | d:supports a d:Property; 444 | "supports"; 445 | d:domainIncludes d:Tool, ; 446 | d:rangeIncludes d:String; 447 | s:url d:supports. 448 | d:templates a d:Feature; 449 | "templates"; 450 | d:platforms , . 451 | a d:Feature; 452 | "term/alias"; 453 | ; 454 | d:platforms . 455 | "Block Reference". 456 | "Block embed". 457 | "Page embed". 458 | d:type a d:Property; 459 | "type"; 460 | d:rangeIncludes d:Class; 461 | s:url . 462 | d:unique a d:Property; 463 | "unique"; 464 | d:domainIncludes d:Property; 465 | d:rangeIncludes d:Boolean; 466 | s:url d:unique. 467 | d:url a d:Property; 468 | "url"; 469 | d:rangeIncludes d:Uri; 470 | d:unique true; 471 | s:url s:url. 472 | --------------------------------------------------------------------------------