mirror of
https://github.com/logseq/logseq.git
synced 2026-02-01 22:47:36 +00:00
Necessary parts of mldoc are nbb compatible
Also merged in parser tests which were not running
This commit is contained in:
@@ -29,7 +29,7 @@ frontend.extensions.zotero.api/item
|
||||
;; For repl
|
||||
frontend.external.roam/reset-state!
|
||||
;; For repl
|
||||
frontend.format.mldoc/ast-export-markdown
|
||||
logseq.graph-parser.mldoc/ast-export-markdown
|
||||
;; Protocol fn wrapper that could be used
|
||||
frontend.fs/readdir
|
||||
;; Referenced in TODO
|
||||
|
||||
@@ -720,13 +720,13 @@
|
||||
(inline-text {} format v))
|
||||
([config format v]
|
||||
(when (string? v)
|
||||
(let [inline-list (mldoc/inline->edn v (gp-mldoc/default-config format))]
|
||||
(let [inline-list (gp-mldoc/inline->edn v (gp-mldoc/default-config format))]
|
||||
[:div.inline.mr-1 (map-inline config inline-list)]))))
|
||||
|
||||
(defn- render-macro
|
||||
[config name arguments macro-content format]
|
||||
(if macro-content
|
||||
(let [ast (->> (mldoc/->edn macro-content (gp-mldoc/default-config format))
|
||||
(let [ast (->> (gp-mldoc/->edn macro-content (gp-mldoc/default-config format))
|
||||
(map first))
|
||||
paragraph? (and (= 1 (count ast))
|
||||
(= "Paragraph" (ffirst ast)))]
|
||||
@@ -2708,11 +2708,11 @@
|
||||
;; (cond
|
||||
;; (= lang "quote")
|
||||
;; (let [content (string/trim (string/join "\n" lines))]
|
||||
;; ["Quote" (first (mldoc/->edn content (gp-mldoc/default-config :markdown)))])
|
||||
;; ["Quote" (first (gp-mldoc/->edn content (gp-mldoc/default-config :markdown)))])
|
||||
|
||||
;; (contains? #{"query" "note" "tip" "important" "caution" "warning" "pinned"} lang)
|
||||
;; (let [content (string/trim (string/join "\n" lines))]
|
||||
;; ["Custom" lang nil (first (mldoc/->edn content (gp-mldoc/default-config :markdown))) content])
|
||||
;; ["Custom" lang nil (first (gp-mldoc/->edn content (gp-mldoc/default-config :markdown))) content])
|
||||
|
||||
;; :else
|
||||
;; ["Src" options])))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(set! mldoc/parse-property text/parse-property)
|
||||
(set! gp-mldoc/parse-property text/parse-property)
|
||||
|
||||
(defonce mldoc-record (->MldocMode))
|
||||
(defonce adoc-record (->AdocMode))
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
[logseq.graph-parser.config :as gp-config]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[lambdaisland.glogi :as log]
|
||||
[medley.core :as medley]
|
||||
[frontend.format.mldoc :as mldoc]))
|
||||
[medley.core :as medley]))
|
||||
|
||||
(defn heading-block?
|
||||
[block]
|
||||
@@ -166,7 +165,7 @@
|
||||
(map last)
|
||||
(map (fn [v]
|
||||
(when (and (string? v)
|
||||
(not (mldoc/link? format v)))
|
||||
(not (gp-mldoc/link? format v)))
|
||||
(let [v (string/trim v)
|
||||
result (text/split-page-refs-without-brackets v {:un-brackets? false})]
|
||||
(if (coll? result)
|
||||
@@ -430,7 +429,7 @@
|
||||
(if (or (:pre-block? block)
|
||||
(= (:format block) :org))
|
||||
content
|
||||
(mldoc/remove-indentation-spaces content (inc (:level block)) false))))]
|
||||
(gp-mldoc/remove-indentation-spaces content (inc (:level block)) false))))]
|
||||
(if (= format :org)
|
||||
content
|
||||
(property/->new-properties content))))
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
(ns frontend.format.mldoc
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.format.protocol :as protocol]
|
||||
[frontend.utf8 :as utf8]
|
||||
[goog.object :as gobj]
|
||||
[lambdaisland.glogi :as log]
|
||||
[medley.core :as medley]
|
||||
["mldoc" :as mldoc :refer [Mldoc]]
|
||||
[linked.core :as linked]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[logseq.graph-parser.util :as gp-util]
|
||||
[logseq.graph-parser.config :as gp-config]))
|
||||
[logseq.graph-parser.util :as gp-util]))
|
||||
|
||||
(defonce anchorLink (gobj/get Mldoc "anchorLink"))
|
||||
(defonce parseOPML (gobj/get Mldoc "parseOPML"))
|
||||
@@ -34,104 +30,6 @@
|
||||
title
|
||||
(or references gp-mldoc/default-references)))
|
||||
|
||||
(defn remove-indentation-spaces
|
||||
[s level remove-first-line?]
|
||||
(let [lines (string/split-lines s)
|
||||
[f & r] lines
|
||||
body (map (fn [line]
|
||||
(if (string/blank? (gp-util/safe-subs line 0 level))
|
||||
(gp-util/safe-subs line level)
|
||||
line))
|
||||
(if remove-first-line? lines r))
|
||||
content (if remove-first-line? body (cons f body))]
|
||||
(string/join "\n" content)))
|
||||
|
||||
(defn- ->vec
|
||||
[s]
|
||||
(if (string? s) [s] s))
|
||||
|
||||
(defn- ->vec-concat
|
||||
[& coll]
|
||||
(->> (map ->vec coll)
|
||||
(remove nil?)
|
||||
(apply concat)
|
||||
(distinct)))
|
||||
|
||||
(defn collect-page-properties
|
||||
[ast parse-property]
|
||||
(if (seq ast)
|
||||
(let [original-ast ast
|
||||
ast (map first ast) ; without position meta
|
||||
directive? (fn [[item _]] (= "directive" (string/lower-case (first item))))
|
||||
grouped-ast (group-by directive? original-ast)
|
||||
directive-ast (take-while directive? original-ast)
|
||||
[properties-ast other-ast] (if (= "Property_Drawer" (ffirst ast))
|
||||
[(last (first ast))
|
||||
(rest original-ast)]
|
||||
[(->> (map first directive-ast)
|
||||
(map rest))
|
||||
(get grouped-ast false)])
|
||||
properties (->>
|
||||
properties-ast
|
||||
(map (fn [[k v]]
|
||||
(let [k (keyword (string/lower-case k))
|
||||
v (if (contains? #{:title :description :filters :macro} k)
|
||||
v
|
||||
(parse-property k v))]
|
||||
[k v]))))
|
||||
properties (into (linked/map) properties)
|
||||
macro-properties (filter (fn [x] (= :macro (first x))) properties)
|
||||
macros (if (seq macro-properties)
|
||||
(->>
|
||||
(map
|
||||
(fn [[_ v]]
|
||||
(let [[k v] (gp-util/split-first " " v)]
|
||||
(mapv
|
||||
string/trim
|
||||
[k v])))
|
||||
macro-properties)
|
||||
(into {}))
|
||||
{})
|
||||
properties (->> (remove (fn [x] (= :macro (first x))) properties)
|
||||
(into (linked/map)))
|
||||
properties (cond-> properties
|
||||
(seq macros)
|
||||
(assoc :macros macros))
|
||||
alias (:alias properties)
|
||||
alias (when alias
|
||||
(if (coll? alias)
|
||||
(remove string/blank? alias)
|
||||
[alias]))
|
||||
filetags (when-let [org-file-tags (:filetags properties)]
|
||||
(->> (string/split org-file-tags ":")
|
||||
(remove string/blank?)))
|
||||
tags (:tags properties)
|
||||
tags (->> (->vec-concat tags filetags)
|
||||
(remove string/blank?))
|
||||
properties (assoc properties :tags tags :alias alias)
|
||||
properties (-> properties
|
||||
(update :filetags (constantly filetags)))
|
||||
properties (medley/remove-kv (fn [_k v] (or (nil? v) (and (coll? v) (empty? v)))) properties)]
|
||||
(if (seq properties)
|
||||
(cons [["Properties" properties] nil] other-ast)
|
||||
original-ast))
|
||||
ast))
|
||||
|
||||
(defn update-src-full-content
|
||||
[ast content]
|
||||
(let [content (utf8/encode content)]
|
||||
(map (fn [[block pos-meta]]
|
||||
(if (and (vector? block)
|
||||
(= "Src" (first block)))
|
||||
(let [{:keys [start_pos end_pos]} pos-meta
|
||||
content (utf8/substring content start_pos end_pos)
|
||||
spaces (re-find #"^[\t ]+" (first (string/split-lines content)))
|
||||
content (if spaces (remove-indentation-spaces content (count spaces) true)
|
||||
content)
|
||||
block ["Src" (assoc (second block) :full_content content)]]
|
||||
[block pos-meta])
|
||||
[block pos-meta])) ast)))
|
||||
|
||||
(defn block-with-title?
|
||||
[type]
|
||||
(contains? #{"Paragraph"
|
||||
@@ -139,50 +37,21 @@
|
||||
"Hiccup"
|
||||
"Heading"} type))
|
||||
|
||||
(def parse-property nil)
|
||||
|
||||
(defn ->edn
|
||||
[content config]
|
||||
(if (string? content)
|
||||
(try
|
||||
(if (string/blank? content)
|
||||
[]
|
||||
(-> content
|
||||
(gp-mldoc/parse-json config)
|
||||
(gp-util/json->clj)
|
||||
(update-src-full-content content)
|
||||
(collect-page-properties parse-property)))
|
||||
(catch js/Error e
|
||||
(js/console.error e)
|
||||
[]))
|
||||
(log/error :edn/wrong-content-type content)))
|
||||
|
||||
(defn opml->edn
|
||||
[content]
|
||||
(try
|
||||
(if (string/blank? content)
|
||||
{}
|
||||
(let [[headers blocks] (-> content (parse-opml) (gp-util/json->clj))]
|
||||
[headers (collect-page-properties blocks parse-property)]))
|
||||
[headers (gp-mldoc/collect-page-properties blocks gp-mldoc/parse-property)]))
|
||||
(catch js/Error e
|
||||
(log/error :edn/convert-failed e)
|
||||
[])))
|
||||
|
||||
(defn inline->edn
|
||||
[text config]
|
||||
(try
|
||||
(if (string/blank? text)
|
||||
{}
|
||||
(-> text
|
||||
(gp-mldoc/inline-parse-json config)
|
||||
(gp-util/json->clj)))
|
||||
(catch js/Error _e
|
||||
[])))
|
||||
|
||||
(defrecord MldocMode []
|
||||
protocol/Format
|
||||
(toEdn [_this content config]
|
||||
(->edn content config))
|
||||
(gp-mldoc/->edn content config))
|
||||
(toHtml [_this content config references]
|
||||
(export "html" content config references))
|
||||
(loaded? [_this]
|
||||
@@ -206,21 +75,3 @@
|
||||
[ast typ]
|
||||
(and (contains? #{"Drawer"} (ffirst ast))
|
||||
(= typ (second (first ast)))))
|
||||
|
||||
(defn link?
|
||||
[format link]
|
||||
(when (string? link)
|
||||
(let [[type link] (first (inline->edn link (gp-mldoc/default-config format)))
|
||||
[ref-type ref-value] (:url link)]
|
||||
(and (= "Link" type)
|
||||
(or
|
||||
;; 1. url
|
||||
(not (contains? #{"Page_ref" "Block_ref"} ref-type))
|
||||
|
||||
(and (contains? #{"Page_ref"} ref-type)
|
||||
(or
|
||||
;; 2. excalidraw link
|
||||
(gp-config/draw? ref-value)
|
||||
|
||||
;; 3. local asset link
|
||||
(boolean (gp-config/local-asset? ref-value)))))))))
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
content (drawer/with-logbook block content)
|
||||
content (with-timetracking block content)
|
||||
first-block? (= left page)
|
||||
ast (mldoc/->edn (string/trim content) (gp-mldoc/default-config format))
|
||||
ast (gp-mldoc/->edn (string/trim content) (gp-mldoc/default-config format))
|
||||
first-elem-type (first (ffirst ast))
|
||||
first-elem-meta (second (ffirst ast))
|
||||
properties? (contains? #{"Property_Drawer" "Properties"} first-elem-type)
|
||||
@@ -1942,7 +1942,7 @@
|
||||
props (into [] (:properties block))
|
||||
content* (str (if (= :markdown format) "- " "* ")
|
||||
(property/insert-properties format content props))
|
||||
ast (mldoc/->edn content* (gp-mldoc/default-config format))
|
||||
ast (gp-mldoc/->edn content* (gp-mldoc/default-config format))
|
||||
blocks (block/extract-blocks ast content* true format)
|
||||
fst-block (first blocks)]
|
||||
(assert fst-block "fst-block shouldn't be nil")
|
||||
@@ -2851,7 +2851,7 @@
|
||||
(when-let [editing-block (state/get-edit-block)]
|
||||
(let [page-id (:db/id (:block/page editing-block))
|
||||
blocks (block/extract-blocks
|
||||
(mldoc/->edn text (gp-mldoc/default-config format)) text true format)
|
||||
(gp-mldoc/->edn text (gp-mldoc/default-config format)) text true format)
|
||||
blocks' (block/with-parent-and-left page-id blocks)]
|
||||
(paste-blocks blocks' {}))))
|
||||
|
||||
@@ -3169,7 +3169,7 @@
|
||||
[format content semantic?]
|
||||
(and (string/includes? content "\n")
|
||||
(if semantic?
|
||||
(let [ast (mldoc/->edn content (gp-mldoc/default-config format))
|
||||
(let [ast (gp-mldoc/->edn content (gp-mldoc/default-config format))
|
||||
first-elem-type (first (ffirst ast))]
|
||||
(mldoc/block-with-title? first-elem-type))
|
||||
true)))
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
[frontend.publishing.html :as html]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[goog.dom :as gdom]
|
||||
[promesa.core :as p])
|
||||
@@ -215,7 +214,7 @@
|
||||
(let [block (db/entity [:block/uuid (uuid block-uuid)])
|
||||
block-content (get-blocks-contents repo (:block/uuid block))
|
||||
format (:block/format block)
|
||||
ast (mldoc/->edn block-content (gp-mldoc/default-config format))
|
||||
ast (gp-mldoc/->edn block-content (gp-mldoc/default-config format))
|
||||
embed-pages-new (get-embed-pages-from-ast ast)
|
||||
embed-blocks-new (get-embed-blocks-from-ast ast)
|
||||
block-refs-new (get-block-refs-from-ast ast)
|
||||
@@ -259,7 +258,7 @@
|
||||
(let [page-name* (util/page-name-sanity-lc page-name)
|
||||
page-content (get-page-content repo page-name*)
|
||||
format (:block/format (db/entity [:block/name page-name*]))
|
||||
ast (mldoc/->edn page-content (gp-mldoc/default-config format))
|
||||
ast (gp-mldoc/->edn page-content (gp-mldoc/default-config format))
|
||||
embed-pages-new (get-embed-pages-from-ast ast)
|
||||
embed-blocks-new (get-embed-blocks-from-ast ast)
|
||||
block-refs-new (get-block-refs-from-ast ast)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[frontend.db :as db]
|
||||
[frontend.format :as format]
|
||||
[frontend.format.block :as block]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
[frontend.state :as state]
|
||||
[frontend.text :as text]
|
||||
[frontend.util :as util]
|
||||
@@ -143,7 +142,7 @@
|
||||
[]
|
||||
(let [format (format/get-format file)
|
||||
_ (println "Parsing start: " file)
|
||||
ast (mldoc/->edn content (gp-mldoc/default-config format
|
||||
ast (gp-mldoc/->edn content (gp-mldoc/default-config format
|
||||
;; {:parse_outline_only? true}
|
||||
))]
|
||||
(println "Parsing finished : " file)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
[frontend.date :as date]
|
||||
[frontend.util :as util]
|
||||
[frontend.config :as config]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
["path" :as path]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.handler.notification :as notification]
|
||||
@@ -23,11 +23,11 @@
|
||||
(string/lower-case (date/journal-name)))
|
||||
format (db/get-page-format page)
|
||||
time (date/get-current-time)
|
||||
url (if (and (mldoc/link? format title) (not url))
|
||||
url (if (and (gp-mldoc/link? format title) (not url))
|
||||
title
|
||||
url)
|
||||
text (if (= url title) nil title)
|
||||
[text url] (if (or (mldoc/link? format url) (not url))
|
||||
[text url] (if (or (gp-mldoc/link? format url) (not url))
|
||||
[text url]
|
||||
(string/split url "\"\n"))
|
||||
text (some-> text (string/replace #"^\"" ""))
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
(:require [frontend.config :as config]
|
||||
[frontend.util :as util]
|
||||
[clojure.string :as string]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
[clojure.set :as set]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[logseq.graph-parser.util :as gp-util]
|
||||
[frontend.state :as state]))
|
||||
|
||||
@@ -366,7 +366,7 @@
|
||||
(contains? @non-parsing-properties (string/lower-case k))
|
||||
v
|
||||
|
||||
(mldoc/link? format v)
|
||||
(gp-mldoc/link? format v)
|
||||
v
|
||||
|
||||
:else
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
(defn get-drawer-ast
|
||||
[format content typ]
|
||||
(let [ast (mldoc/->edn content (gp-mldoc/default-config format))
|
||||
(let [ast (gp-mldoc/->edn content (gp-mldoc/default-config format))
|
||||
typ-drawer (ffirst (filter (fn [x]
|
||||
(mldoc/typ-drawer? x typ)) ast))]
|
||||
typ-drawer))
|
||||
@@ -33,7 +33,7 @@
|
||||
[format content typ value]
|
||||
(when (string? content)
|
||||
(try
|
||||
(let [ast (mldoc/->edn content (gp-mldoc/default-config format))
|
||||
(let [ast (gp-mldoc/->edn content (gp-mldoc/default-config format))
|
||||
has-properties? (some (fn [x] (mldoc/properties? x)) ast)
|
||||
has-typ-drawer? (some (fn [x] (mldoc/typ-drawer? x typ)) ast)
|
||||
lines (string/split-lines content)
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
properties (filter (fn [[k _v]] ((built-in-properties) k)) properties)]
|
||||
(if (seq properties)
|
||||
(let [lines (string/split-lines content)
|
||||
ast (mldoc/->edn content (gp-mldoc/default-config format))
|
||||
ast (gp-mldoc/->edn content (gp-mldoc/default-config format))
|
||||
[title body] (if (mldoc/block-with-title? (first (ffirst ast)))
|
||||
[(first lines) (rest lines)]
|
||||
[nil lines])
|
||||
@@ -234,7 +234,7 @@
|
||||
(insert-property format content key value false))
|
||||
([format content key value front-matter?]
|
||||
(when (string? content)
|
||||
(let [ast (mldoc/->edn content (gp-mldoc/default-config format))
|
||||
(let [ast (gp-mldoc/->edn content (gp-mldoc/default-config format))
|
||||
title? (mldoc/block-with-title? (ffirst (map first ast)))
|
||||
has-properties? (or (and title?
|
||||
(mldoc/properties? (second ast)))
|
||||
|
||||
6
src/main/logseq/graph_parser/log.cljs
Normal file
6
src/main/logseq/graph_parser/log.cljs
Normal file
@@ -0,0 +1,6 @@
|
||||
(ns logseq.graph-parser.log
|
||||
"Minimal logging ns that implements basic lambdaisland.glogi fns. May use
|
||||
glogi later if this ns is used more")
|
||||
|
||||
(defn error [& msgs]
|
||||
(apply js/console.error (map clj->js msgs)))
|
||||
@@ -1,21 +1,27 @@
|
||||
(ns ^:nbb-compatible logseq.graph-parser.mldoc
|
||||
;; Disable clj linters since we don't support clj
|
||||
#?(:clj {:clj-kondo/config {:linters {:unresolved-namespace {:level :off}
|
||||
:unresolved-symbol {:level :off}}}})
|
||||
(:require #?(:org.babashka/nbb ["mldoc$default" :refer [Mldoc]]
|
||||
:default ["mldoc" :refer [Mldoc]])
|
||||
:default ["mldoc" :refer [Mldoc]])
|
||||
#?(:org.babashka/nbb [logseq.graph-parser.log :as log]
|
||||
:default [lambdaisland.glogi :as log])
|
||||
[goog.object :as gobj]
|
||||
[cljs-bean.core :as bean]
|
||||
[clojure.string :as string]))
|
||||
[frontend.utf8 :as utf8]
|
||||
[clojure.string :as string]
|
||||
[linked.core :as linked]
|
||||
[logseq.graph-parser.util :as gp-util]
|
||||
[logseq.graph-parser.config :as gp-config]))
|
||||
|
||||
(defonce parseJson (gobj/get Mldoc "parseJson"))
|
||||
(defonce parseInlineJson (gobj/get Mldoc "parseInlineJson"))
|
||||
(defonce astExportMarkdown (gobj/get Mldoc "astExportMarkdown"))
|
||||
|
||||
;; NOTE: All references to js/ have to have a :default conditional because of clojure
|
||||
(def default-references
|
||||
#?(:cljs
|
||||
(js/JSON.stringify
|
||||
(clj->js {:embed_blocks []
|
||||
:embed_pages []}))
|
||||
:default {}))
|
||||
(js/JSON.stringify
|
||||
(clj->js {:embed_blocks []
|
||||
:embed_pages []})))
|
||||
|
||||
(defn- convert-export-md-remove-options [opts]
|
||||
(->> opts
|
||||
@@ -58,4 +64,152 @@
|
||||
(filter #(not (nil? (second %))))
|
||||
(into {})
|
||||
(bean/->js)
|
||||
#?(:cljs js/JSON.stringify :default identity)))))
|
||||
js/JSON.stringify))))
|
||||
|
||||
(defn remove-indentation-spaces
|
||||
[s level remove-first-line?]
|
||||
(let [lines (string/split-lines s)
|
||||
[f & r] lines
|
||||
body (map (fn [line]
|
||||
(if (string/blank? (gp-util/safe-subs line 0 level))
|
||||
(gp-util/safe-subs line level)
|
||||
line))
|
||||
(if remove-first-line? lines r))
|
||||
content (if remove-first-line? body (cons f body))]
|
||||
(string/join "\n" content)))
|
||||
|
||||
(defn- update-src-full-content
|
||||
[ast content]
|
||||
(let [content (utf8/encode content)]
|
||||
(map (fn [[block pos-meta]]
|
||||
(if (and (vector? block)
|
||||
(= "Src" (first block)))
|
||||
(let [{:keys [start_pos end_pos]} pos-meta
|
||||
content (utf8/substring content start_pos end_pos)
|
||||
spaces (re-find #"^[\t ]+" (first (string/split-lines content)))
|
||||
content (if spaces (remove-indentation-spaces content (count spaces) true)
|
||||
content)
|
||||
block ["Src" (assoc (second block) :full_content content)]]
|
||||
[block pos-meta])
|
||||
[block pos-meta])) ast)))
|
||||
|
||||
(defn- ->vec
|
||||
[s]
|
||||
(if (string? s) [s] s))
|
||||
|
||||
(defn- ->vec-concat
|
||||
[& coll]
|
||||
(->> (map ->vec coll)
|
||||
(remove nil?)
|
||||
(apply concat)
|
||||
(distinct)))
|
||||
|
||||
(defn collect-page-properties
|
||||
[ast parse-property]
|
||||
(if (seq ast)
|
||||
(let [original-ast ast
|
||||
ast (map first ast) ; without position meta
|
||||
directive? (fn [[item _]] (= "directive" (string/lower-case (first item))))
|
||||
grouped-ast (group-by directive? original-ast)
|
||||
directive-ast (take-while directive? original-ast)
|
||||
[properties-ast other-ast] (if (= "Property_Drawer" (ffirst ast))
|
||||
[(last (first ast))
|
||||
(rest original-ast)]
|
||||
[(->> (map first directive-ast)
|
||||
(map rest))
|
||||
(get grouped-ast false)])
|
||||
properties (->>
|
||||
properties-ast
|
||||
(map (fn [[k v]]
|
||||
(let [k (keyword (string/lower-case k))
|
||||
v (if (contains? #{:title :description :filters :macro} k)
|
||||
v
|
||||
(parse-property k v))]
|
||||
[k v]))))
|
||||
properties (into (linked/map) properties)
|
||||
macro-properties (filter (fn [x] (= :macro (first x))) properties)
|
||||
macros (if (seq macro-properties)
|
||||
(->>
|
||||
(map
|
||||
(fn [[_ v]]
|
||||
(let [[k v] (gp-util/split-first " " v)]
|
||||
(mapv
|
||||
string/trim
|
||||
[k v])))
|
||||
macro-properties)
|
||||
(into {}))
|
||||
{})
|
||||
properties (->> (remove (fn [x] (= :macro (first x))) properties)
|
||||
(into (linked/map)))
|
||||
properties (cond-> properties
|
||||
(seq macros)
|
||||
(assoc :macros macros))
|
||||
alias (:alias properties)
|
||||
alias (when alias
|
||||
(if (coll? alias)
|
||||
(remove string/blank? alias)
|
||||
[alias]))
|
||||
filetags (when-let [org-file-tags (:filetags properties)]
|
||||
(->> (string/split org-file-tags ":")
|
||||
(remove string/blank?)))
|
||||
tags (:tags properties)
|
||||
tags (->> (->vec-concat tags filetags)
|
||||
(remove string/blank?))
|
||||
properties (assoc properties :tags tags :alias alias)
|
||||
properties (-> properties
|
||||
(update :filetags (constantly filetags)))
|
||||
properties (into (linked/map)
|
||||
(remove (fn [[_k v]]
|
||||
(or (nil? v) (and (coll? v) (empty? v))))
|
||||
properties))]
|
||||
(if (seq properties)
|
||||
(cons [["Properties" properties] nil] other-ast)
|
||||
original-ast))
|
||||
ast))
|
||||
|
||||
(def parse-property nil)
|
||||
|
||||
(defn ->edn
|
||||
[content config]
|
||||
(if (string? content)
|
||||
(try
|
||||
(if (string/blank? content)
|
||||
[]
|
||||
(-> content
|
||||
(parse-json config)
|
||||
(gp-util/json->clj)
|
||||
(update-src-full-content content)
|
||||
(collect-page-properties parse-property)))
|
||||
(catch js/Error e
|
||||
(js/console.error e)
|
||||
[]))
|
||||
(log/error :edn/wrong-content-type content)))
|
||||
|
||||
(defn inline->edn
|
||||
[text config]
|
||||
(try
|
||||
(if (string/blank? text)
|
||||
{}
|
||||
(-> text
|
||||
(inline-parse-json config)
|
||||
(gp-util/json->clj)))
|
||||
(catch js/Error _e
|
||||
[])))
|
||||
|
||||
(defn link?
|
||||
[format link]
|
||||
(when (string? link)
|
||||
(let [[type link] (first (inline->edn link (default-config format)))
|
||||
[ref-type ref-value] (:url link)]
|
||||
(and (= "Link" type)
|
||||
(or
|
||||
;; 1. url
|
||||
(not (contains? #{"Page_ref" "Block_ref"} ref-type))
|
||||
|
||||
(and (contains? #{"Page_ref"} ref-type)
|
||||
(or
|
||||
;; 2. excalidraw link
|
||||
(gp-config/draw? ref-value)
|
||||
|
||||
;; 3. local asset link
|
||||
(boolean (gp-config/local-asset? ref-value)))))))))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
(ns frontend.parser
|
||||
(:require [cljs.test :refer [is deftest]]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[frontend.format.mldoc :as mldoc :refer [->edn]]))
|
||||
|
||||
(def md-config (gp-mldoc/default-config :markdown))
|
||||
|
||||
(deftest src-test
|
||||
(is (=
|
||||
(first (->edn "```
|
||||
: hello
|
||||
```" md-config))
|
||||
[["Src"
|
||||
{:lines [": hello" "\n"],
|
||||
:pos_meta {:start_pos 4, :end_pos 12},
|
||||
:full_content "```\n: hello\n```"}]
|
||||
{:start_pos 0, :end_pos 15}])))
|
||||
|
||||
(deftest name-definition-test
|
||||
(is (=
|
||||
(first (->edn "term
|
||||
: definition" md-config))
|
||||
[["List"
|
||||
[{:content [["Paragraph" [["Plain" "definition"]]]],
|
||||
:items [],
|
||||
:name [["Plain" "term"]],
|
||||
:indent 0,
|
||||
:ordered false}]]
|
||||
{:start_pos 0, :end_pos 17}])))
|
||||
@@ -1,38 +1,38 @@
|
||||
(ns frontend.format.mldoc-test
|
||||
(:require [frontend.format.mldoc :as mldoc]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
(ns logseq.graph-parser.mldoc-test
|
||||
(:require [logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
["fs" :as fs]
|
||||
["child_process" :as child-process]
|
||||
[clojure.string :as string]
|
||||
[clojure.edn :as edn]
|
||||
[frontend.format]
|
||||
[cljs.test :refer [testing deftest are is]]))
|
||||
|
||||
(deftest test-link
|
||||
(testing "non-link"
|
||||
(are [x y] (= (mldoc/link? :markdown x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :markdown x) y)
|
||||
"google.com" false))
|
||||
|
||||
(testing "plain links"
|
||||
(are [x y] (= (mldoc/link? :markdown x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :markdown x) y)
|
||||
"http://www.google.com" true
|
||||
"http://google.com" true))
|
||||
|
||||
(testing "org links with labels"
|
||||
(are [x y] (= (mldoc/link? :org x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :org x) y)
|
||||
"[[http://www.google.com][google]]" true
|
||||
"[[http://google.com][google]]" true
|
||||
"[[https://www.google.com][google]]" true
|
||||
"[[https://google.com][google]]" true))
|
||||
|
||||
(testing "org links without labels"
|
||||
(are [x y] (= (mldoc/link? :org x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :org x) y)
|
||||
"[[http://www.google.com]]" true
|
||||
"[[https://www.google.com]]" true
|
||||
"[[draws/2022-03-06-15-00-28.excalidraw]]" true
|
||||
"[[assets/2022-03-06-15-00-28.pdf]]" true))
|
||||
|
||||
(testing "markdown links"
|
||||
(are [x y] (= (mldoc/link? :markdown x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :markdown x) y)
|
||||
"[google](http://www.google.com)" true
|
||||
"[google](https://www.google.com)" true
|
||||
"[[draws/2022-03-06-15-00-28.excalidraw]]" true
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
;; https://github.com/logseq/logseq/issues/4308
|
||||
(testing "parsing links should be finished"
|
||||
(are [x y] (= (mldoc/link? :markdown x) y)
|
||||
(are [x y] (= (gp-mldoc/link? :markdown x) y)
|
||||
"[YouTube](https://www.youtube.com/watch?v=-8ym7pyUs9gL) - [Vimeo](https://vimeo.com/677920303) {{youtube https://www.youtube.com/watch?v=-8ym7pyUs9g}}" true)))
|
||||
|
||||
;; TODO: Reuse with repo-test fns
|
||||
@@ -75,8 +75,8 @@
|
||||
(let [format (if (string/ends-with? path ".org")
|
||||
:org :markdown)]
|
||||
[path
|
||||
(mldoc/->edn content
|
||||
(gp-mldoc/default-config format))])))
|
||||
(gp-mldoc/->edn content
|
||||
(gp-mldoc/default-config format))])))
|
||||
(into {}))]
|
||||
(is (= {"CommentBlock" 1,
|
||||
"Custom" 41,
|
||||
@@ -97,9 +97,35 @@
|
||||
(->> asts-by-file (mapcat val) (map ffirst) frequencies))
|
||||
"AST node type counts")
|
||||
|
||||
; (println :DIFF)
|
||||
; (prn (butlast (clojure.data/diff (edn/read-string (slurp "mldoc-asts.edn"))
|
||||
; asts-by-file)))
|
||||
;; This is just temporary
|
||||
(is (= (edn/read-string (slurp "mldoc-asts.edn"))
|
||||
asts-by-file)
|
||||
"Matches initial AST")
|
||||
#_(println "Wrote asts for" (count asts-by-file) "files")
|
||||
#_(fs/writeFileSync "mldoc-asts.edn" (pr-str asts-by-file))))
|
||||
|
||||
(def md-config (gp-mldoc/default-config :markdown))
|
||||
|
||||
(deftest src-test
|
||||
(is (= [["Src"
|
||||
{:lines [": hello" "\n"],
|
||||
:pos_meta {:start_pos 4, :end_pos 12},
|
||||
:full_content "```\n: hello\n```"}]
|
||||
{:start_pos 0, :end_pos 15}]
|
||||
(first (gp-mldoc/->edn "```
|
||||
: hello
|
||||
```" md-config)))))
|
||||
|
||||
(deftest name-definition-test
|
||||
(is (= [["List"
|
||||
[{:content [["Paragraph" [["Plain" "definition"]]]],
|
||||
:items [],
|
||||
:name [["Plain" "term"]],
|
||||
:indent 0,
|
||||
:ordered false}]]
|
||||
{:start_pos 0, :end_pos 17}]
|
||||
(first (gp-mldoc/->edn "term
|
||||
: definition" md-config)))))
|
||||
Reference in New Issue
Block a user