mirror of
https://github.com/logseq/logseq.git
synced 2026-04-24 22:25:01 +00:00
fix: positioned properties rendering
This commit is contained in:
3
deps/publish/deps.edn
vendored
3
deps/publish/deps.edn
vendored
@@ -1,4 +1,5 @@
|
||||
{:deps
|
||||
{:paths ["src" "../../resources"]
|
||||
:deps
|
||||
{org.clojure/clojure {:mvn/version "1.11.1"}
|
||||
rum/rum {:git/url "https://github.com/logseq/rum" ;; fork
|
||||
:sha "5d672bf84ed944414b9f61eeb83808ead7be9127"}
|
||||
|
||||
64
deps/publish/src/logseq/publish/publish.css
vendored
64
deps/publish/src/logseq/publish/publish.css
vendored
@@ -215,10 +215,72 @@ a:hover {
|
||||
.block-content {
|
||||
white-space: pre-wrap;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
gap: 4px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.positioned-properties {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.positioned-properties.block-left, .positioned-properties.block-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.positioned-properties.block-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.positioned-properties.block-below {
|
||||
margin: 6px 0 0 22px;
|
||||
gap: 8px 12px;
|
||||
}
|
||||
|
||||
.positioned-property {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.positioned-property .property-name {
|
||||
color: var(--muted);
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.positioned-property .property-value {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.property-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
line-height: 1;
|
||||
font-size: 1rem;
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
.property-icon svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.property-value-with-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.block-text {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
|
||||
177
deps/publish/src/logseq/publish/publish.js
vendored
177
deps/publish/src/logseq/publish/publish.js
vendored
@@ -22,6 +22,7 @@ import { markdown } from "https://esm.sh/@codemirror/lang-markdown@6";
|
||||
import { sql } from "https://esm.sh/@codemirror/lang-sql@6";
|
||||
import { css } from "https://esm.sh/@codemirror/lang-css@6";
|
||||
import { clojure } from "https://esm.sh/@nextjournal/lang-clojure";
|
||||
import emojiData from "https://esm.sh/@emoji-mart/data@1?bundle";
|
||||
|
||||
const katex = katexPkg.default || katexPkg;
|
||||
const THEME_KEY = "publish-theme";
|
||||
@@ -35,6 +36,178 @@ document.addEventListener("click", (event) => {
|
||||
btn.setAttribute("aria-expanded", String(!collapsed));
|
||||
});
|
||||
|
||||
const getEmojiNative = (id) => {
|
||||
const emoji = emojiData?.emojis?.[id];
|
||||
if (!emoji) return null;
|
||||
return emoji?.skins?.[0]?.native || null;
|
||||
};
|
||||
|
||||
const toKebabCase = (value) =>
|
||||
(value || "")
|
||||
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
||||
.replace(/([a-zA-Z])([0-9])/g, "$1-$2")
|
||||
.replace(/([0-9])([a-zA-Z])/g, "$1-$2")
|
||||
.replace(/[_\s]+/g, "-")
|
||||
.replace(/-+/g, "-")
|
||||
.toLowerCase();
|
||||
|
||||
const toPascalCase = (value) =>
|
||||
(value || "")
|
||||
.split(/[^a-zA-Z0-9]+/)
|
||||
.filter(Boolean)
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||
.join("");
|
||||
|
||||
const toTablerIconName = (id) => {
|
||||
if (!id) return null;
|
||||
return id.startsWith("Icon") ? id : `Icon${toPascalCase(id)}`;
|
||||
};
|
||||
|
||||
const svgNamespace = "http://www.w3.org/2000/svg";
|
||||
|
||||
const isReactElement = (node) =>
|
||||
node &&
|
||||
typeof node === "object" &&
|
||||
node.$$typeof &&
|
||||
node.type &&
|
||||
node.props;
|
||||
|
||||
const setDomAttribute = (el, key, val, isSvg) => {
|
||||
if (key === "className") {
|
||||
el.setAttribute("class", val);
|
||||
return;
|
||||
}
|
||||
if (key === "style" && val && typeof val === "object") {
|
||||
Object.entries(val).forEach(([styleKey, styleVal]) => {
|
||||
el.style[styleKey] = styleVal;
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (key === "ref" || key === "key" || key === "children") return;
|
||||
if (val === true) {
|
||||
el.setAttribute(key, "");
|
||||
return;
|
||||
}
|
||||
if (val === false || val == null) return;
|
||||
|
||||
let attr = key;
|
||||
if (isSvg) {
|
||||
if (key === "strokeWidth") attr = "stroke-width";
|
||||
else if (key === "strokeLinecap") attr = "stroke-linecap";
|
||||
else if (key === "strokeLinejoin") attr = "stroke-linejoin";
|
||||
else if (key !== "viewBox" && /[A-Z]/.test(key)) {
|
||||
attr = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
||||
}
|
||||
}
|
||||
el.setAttribute(attr, val);
|
||||
};
|
||||
|
||||
const reactNodeToDom = (node, parentIsSvg = false) => {
|
||||
if (node == null || node === false) return null;
|
||||
if (Array.isArray(node)) {
|
||||
const frag = document.createDocumentFragment();
|
||||
node.forEach((child) => {
|
||||
const childNode = reactNodeToDom(child, parentIsSvg);
|
||||
if (childNode) frag.appendChild(childNode);
|
||||
});
|
||||
return frag;
|
||||
}
|
||||
if (typeof node === "string" || typeof node === "number") {
|
||||
return document.createTextNode(String(node));
|
||||
}
|
||||
if (node.nodeType) return node;
|
||||
if (isReactElement(node)) {
|
||||
if (node.type === Symbol.for("react.fragment")) {
|
||||
return reactNodeToDom(node.props?.children, parentIsSvg);
|
||||
}
|
||||
if (typeof node.type === "function") {
|
||||
return reactNodeToDom(node.type(node.props), parentIsSvg);
|
||||
}
|
||||
const tag = node.type;
|
||||
const isSvg = parentIsSvg || tag === "svg";
|
||||
const el = isSvg
|
||||
? document.createElementNS(svgNamespace, tag)
|
||||
: document.createElement(tag);
|
||||
const props = node.props || {};
|
||||
Object.entries(props).forEach(([key, val]) => {
|
||||
setDomAttribute(el, key, val, isSvg);
|
||||
});
|
||||
const children = props.children;
|
||||
if (children != null) {
|
||||
const childNode = reactNodeToDom(children, isSvg);
|
||||
if (childNode) el.appendChild(childNode);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const getTablerExtIcon = (id) => {
|
||||
const name = toTablerIconName(id);
|
||||
if (!name) return null;
|
||||
return window.tablerIcons?.[name] || null;
|
||||
};
|
||||
|
||||
const renderTablerExtIcon = (el, id) => {
|
||||
const iconFn = getTablerExtIcon(id);
|
||||
if (!iconFn) return false;
|
||||
const node = iconFn({ size: 14, stroke: 2 });
|
||||
if (!node) return false;
|
||||
el.textContent = "";
|
||||
const domNode = reactNodeToDom(node);
|
||||
if (!domNode) return false;
|
||||
if (domNode.nodeType === 11) {
|
||||
el.appendChild(domNode);
|
||||
return true;
|
||||
}
|
||||
if (domNode.nodeType) {
|
||||
if (domNode.tagName === "svg") {
|
||||
domNode.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
el.appendChild(domNode);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const renderPropertyIcons = () => {
|
||||
const icons = Array.from(
|
||||
document.querySelectorAll(".property-icon[data-icon-type][data-icon-id]")
|
||||
);
|
||||
if (!icons.length) return;
|
||||
|
||||
icons.forEach((el) => {
|
||||
const id = el.dataset.iconId;
|
||||
const type = el.dataset.iconType;
|
||||
if (!id) return;
|
||||
|
||||
if (type === "emoji") {
|
||||
const native = getEmojiNative(id);
|
||||
el.textContent = native || id;
|
||||
return;
|
||||
}
|
||||
|
||||
el.textContent = "";
|
||||
el.setAttribute("aria-hidden", "true");
|
||||
|
||||
if (type === "tabler-ext-icon") {
|
||||
if (renderTablerExtIcon(el, id)) return;
|
||||
const slug = toKebabCase(id);
|
||||
el.classList.add("tie", `tie-${slug}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "tabler-icon") {
|
||||
if (renderTablerExtIcon(el, id)) return;
|
||||
const slug = toKebabCase(id);
|
||||
el.classList.add("ti", `ti-${slug}`);
|
||||
return;
|
||||
}
|
||||
|
||||
el.textContent = id;
|
||||
});
|
||||
};
|
||||
|
||||
let sequenceKey = null;
|
||||
let sequenceTimer = null;
|
||||
const SEQUENCE_TIMEOUT_MS = 900;
|
||||
@@ -179,6 +352,10 @@ const initTwitterEmbeds = () => {
|
||||
|
||||
const initPublish = () => {
|
||||
applyTheme(preferredTheme());
|
||||
renderPropertyIcons();
|
||||
if (!window.tablerIcons) {
|
||||
window.addEventListener("load", renderPropertyIcons, { once: true });
|
||||
}
|
||||
|
||||
initTwitterEmbeds();
|
||||
|
||||
|
||||
194
deps/publish/src/logseq/publish/render.cljs
vendored
194
deps/publish/src/logseq/publish/render.cljs
vendored
@@ -80,6 +80,31 @@
|
||||
[]
|
||||
nodes-list))
|
||||
|
||||
(defn- normalize-nodes
|
||||
[nodes]
|
||||
(cond
|
||||
(nil? nodes) []
|
||||
(and (vector? nodes) (keyword? (first nodes))) [nodes]
|
||||
:else nodes))
|
||||
|
||||
(defn- icon-span
|
||||
[icon]
|
||||
(when (and (map? icon) (string? (:id icon)) (not (string/blank? (:id icon))))
|
||||
[:span
|
||||
(cond->
|
||||
{:class "property-icon"
|
||||
:data-icon-id (:id icon)
|
||||
:data-icon-type (name (:type icon))}
|
||||
(:color icon)
|
||||
(assoc :style (str "color: " (:color icon) ";")))]))
|
||||
|
||||
(defn- with-icon
|
||||
[icon nodes]
|
||||
(let [icon-node (icon-span icon)]
|
||||
(if icon-node
|
||||
(into [:span {:class "property-value-with-icon"} icon-node] nodes)
|
||||
nodes)))
|
||||
|
||||
(defn- theme-toggle-node
|
||||
[]
|
||||
[:button.theme-toggle
|
||||
@@ -103,6 +128,25 @@
|
||||
[]
|
||||
[:script {:type "module" :src "/static/publish.js"}])
|
||||
|
||||
(defn- icon-runtime-script
|
||||
[]
|
||||
[:script
|
||||
"(function(){if(window.React&&window.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED){return;}var s='http://www.w3.org/2000/svg';var k=function(n){return n.replace(/[A-Z]/g,function(m){return'-'+m.toLowerCase();});};var a=function(el,key,val){if(key==='className'){el.setAttribute('class',val);return;}if(key==='style'&&val&&typeof val==='object'){for(var sk in val){el.style[sk]=val[sk];}return;}if(key==='ref'||key==='key'||key==='children'){return;}if(val===true){el.setAttribute(key,'');return;}if(val===false||val==null){return;}var attr=key;if(key==='strokeWidth'){attr='stroke-width';}else if(key==='strokeLinecap'){attr='stroke-linecap';}else if(key==='strokeLinejoin'){attr='stroke-linejoin';}else if(key!=='viewBox'&&/[A-Z]/.test(key)){attr=k(key);}el.setAttribute(attr,val);};var c=function(el,child){if(child==null||child===false){return;}if(Array.isArray(child)){child.forEach(function(n){c(el,n);});return;}if(typeof child==='string'||typeof child==='number'){el.appendChild(document.createTextNode(child));return;}if(child.nodeType){el.appendChild(child);} };var e=function(type,props){var children=Array.prototype.slice.call(arguments,2);if(type===Symbol.for('react.fragment')){var frag=document.createDocumentFragment();children.forEach(function(n){c(frag,n);});return frag;}if(typeof type==='function'){return type(Object.assign({},props,{children:children}));}var isSvg=type==='svg'||(props&&props.xmlns===s);var el=isSvg?document.createElementNS(s,type):document.createElement(type);if(props){for(var p in props){a(el,p,props[p]);}}children.forEach(function(n){c(el,n);});return el;};window.React={createElement:e,forwardRef:function(fn){return fn;},Fragment:Symbol.for('react.fragment'),__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:{ReactCurrentOwner:{current:null}}};window.PropTypes=new Proxy({}, {get:function(){return function(){return null;};}});})();"])
|
||||
|
||||
(defn- head-node
|
||||
[title]
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title title]
|
||||
(theme-init-script)
|
||||
(icon-runtime-script)
|
||||
[:script {:defer true :src "/static/tabler.ext.js"}]
|
||||
[:link {:rel "stylesheet"
|
||||
:href "https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@3.0/dist/tabler-icons.min.css"}]
|
||||
[:link {:rel "stylesheet" :href "/static/tabler-extension.css"}]
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]])
|
||||
|
||||
(defn property-type
|
||||
[prop-key property-type-by-ident]
|
||||
(or (get property-type-by-ident prop-key)
|
||||
@@ -157,7 +201,9 @@
|
||||
[(str value)])
|
||||
|
||||
(and ref-type? (get entities value))
|
||||
(entity->link-node (get entities value) ctx)
|
||||
(let [entity (get entities value)]
|
||||
(with-icon (:logseq.property/icon entity)
|
||||
(entity->link-node entity ctx)))
|
||||
|
||||
:else
|
||||
[(str value)])
|
||||
@@ -216,7 +262,75 @@
|
||||
[:div.property
|
||||
[:dt.property-name (property-title k (:property-title-by-ident ctx))]
|
||||
[:dd.property-value
|
||||
(into [:span] (property-value->nodes v k ctx entities))]])]))
|
||||
(into [:span] (normalize-nodes (property-value->nodes v k ctx entities)))]])]))
|
||||
|
||||
(defn- property-ui-position
|
||||
[prop-key ctx]
|
||||
(when-let [property (get (:property-entity-by-ident ctx) prop-key)]
|
||||
(:logseq.property/ui-position property)))
|
||||
|
||||
(defn- split-properties-by-position
|
||||
[props ctx]
|
||||
(reduce (fn [acc [k v]]
|
||||
(let [position (property-ui-position k ctx)
|
||||
bucket (case position
|
||||
(:block-left :block-right :block-below) position
|
||||
:properties)]
|
||||
(update acc bucket assoc k v)))
|
||||
{:properties {}
|
||||
:block-left {}
|
||||
:block-right {}
|
||||
:block-below {}}
|
||||
props))
|
||||
|
||||
(defn- sorted-properties
|
||||
[props ctx]
|
||||
(sort-by (fn [[prop-key _]]
|
||||
(get-in ctx [:property-entity-by-ident prop-key :block/order]))
|
||||
props))
|
||||
|
||||
(defn- class-has?
|
||||
[class-name target]
|
||||
(some #{target} (string/split (or class-name "") #"\s+")))
|
||||
|
||||
(defn- node-has-class?
|
||||
[node target]
|
||||
(when (and (vector? node) (keyword? (first node)))
|
||||
(let [attrs (second node)]
|
||||
(and (map? attrs) (class-has? (:class attrs) target)))))
|
||||
|
||||
(defn- strip-positioned-value
|
||||
[node]
|
||||
(if (node-has-class? node "property-value-with-icon")
|
||||
(let [[tag attrs & children] node
|
||||
icon-children (filter #(node-has-class? % "property-icon") children)]
|
||||
(if (seq icon-children)
|
||||
(into [tag attrs] icon-children)
|
||||
node))
|
||||
node))
|
||||
|
||||
(defn- positioned-value-nodes
|
||||
[value prop-key ctx entities]
|
||||
(->> (property-value->nodes value prop-key ctx entities)
|
||||
normalize-nodes
|
||||
(map strip-positioned-value)))
|
||||
|
||||
(defn- render-positioned-properties
|
||||
[props ctx entities position]
|
||||
(when (seq props)
|
||||
(case position
|
||||
:block-below
|
||||
[:div.positioned-properties.block-below
|
||||
(for [[k v] (sorted-properties props ctx)]
|
||||
[:div.positioned-property
|
||||
[:span.property-name (property-title k (:property-title-by-ident ctx))]
|
||||
[:span.property-value
|
||||
(into [:span] (positioned-value-nodes v k ctx entities))]])]
|
||||
|
||||
[:div {:class (str "positioned-properties " (name position))}
|
||||
(for [[k v] (sorted-properties props ctx)]
|
||||
[:span.positioned-property
|
||||
(into [:span] (positioned-value-nodes v k ctx entities))])])))
|
||||
|
||||
(def ^:private youtube-regex #"^((?:https?:)?//)?((?:www|m).)?((?:youtube.com|youtu.be|y2u.be|youtube-nocookie.com))(/(?:[\w-]+\?v=|embed/|v/)?)([\w-]+)([\S^\?]+)?$")
|
||||
(def ^:private vimeo-regex #"^((?:https?:)?//)?((?:www).)?((?:player.vimeo.com|vimeo.com))(/(?:video/)?)([\w-]+)(\S+)?$")
|
||||
@@ -580,16 +694,23 @@
|
||||
(let [child-id (:db/id block)
|
||||
nested (render-block-tree children-by-parent child-id ctx)
|
||||
has-children? (boolean nested)
|
||||
properties (render-properties (entity-properties block ctx (:entities ctx))
|
||||
ctx
|
||||
(:entities ctx))]
|
||||
raw-props (entity-properties block ctx (:entities ctx))
|
||||
{:keys [properties block-left block-right block-below]}
|
||||
(split-properties-by-position raw-props ctx)
|
||||
positioned-left (render-positioned-properties block-left ctx (:entities ctx) :block-left)
|
||||
positioned-right (render-positioned-properties block-right ctx (:entities ctx) :block-right)
|
||||
positioned-below (render-positioned-properties block-below ctx (:entities ctx) :block-below)
|
||||
properties (render-properties properties ctx (:entities ctx))]
|
||||
[:li.block
|
||||
[:div.block-content
|
||||
(when positioned-left positioned-left)
|
||||
(block-display-node block ctx)
|
||||
(when positioned-right positioned-right)
|
||||
(when has-children?
|
||||
[:button.block-toggle
|
||||
{:type "button" :aria-expanded "true"}
|
||||
"▾"])]
|
||||
(when positioned-below positioned-below)
|
||||
(when properties
|
||||
[:div.block-properties properties])
|
||||
(when nested
|
||||
@@ -705,6 +826,12 @@
|
||||
acc))
|
||||
{}
|
||||
entities)
|
||||
property-entity-by-ident (reduce (fn [acc [_e entity]]
|
||||
(if-let [ident (:db/ident entity)]
|
||||
(assoc acc ident entity)
|
||||
acc))
|
||||
{}
|
||||
entities)
|
||||
children-by-parent (->> entities
|
||||
(reduce (fn [acc [e entity]]
|
||||
(if (and (= (:block/page entity) page-eid)
|
||||
@@ -723,6 +850,7 @@
|
||||
:property-title-by-ident property-title-by-ident
|
||||
:property-type-by-ident property-type-by-ident
|
||||
:property-hidden-by-ident property-hidden-by-ident
|
||||
:property-entity-by-ident property-entity-by-ident
|
||||
:entities entities}
|
||||
page-properties (render-properties (entity-properties page-entity ctx entities)
|
||||
ctx
|
||||
@@ -746,12 +874,7 @@
|
||||
(for [item tagged-nodes]
|
||||
(render-tagged-item graph-uuid item))]])
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title page-title]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node page-title)
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -788,12 +911,7 @@
|
||||
(or (:updated-at row) 0)))
|
||||
reverse)
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title (str "Published pages - " graph-uuid)]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node (str "Published pages - " graph-uuid))
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -818,12 +936,7 @@
|
||||
(let [rows tag-items
|
||||
title (or tag-title tag-uuid)
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title (str "Tag - " title)]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node (str "Tag - " title))
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -846,12 +959,7 @@
|
||||
(let [rows tag-items
|
||||
title (or tag-title tag-name)
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title (str "Tag - " title)]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node (str "Tag - " title))
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -885,12 +993,7 @@
|
||||
(let [rows ref-items
|
||||
title (or ref-title ref-name)
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title (str "Ref - " title)]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node (str "Ref - " title))
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -925,12 +1028,7 @@
|
||||
[graph-uuid]
|
||||
(let [title "Page not published"
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title title]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node title)
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -946,12 +1044,7 @@
|
||||
[graph-uuid page-uuid wrong?]
|
||||
(let [title "Protected page"
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title title]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node title)
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
@@ -980,12 +1073,7 @@
|
||||
[]
|
||||
(let [title "Page not found"
|
||||
doc [:html
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
[:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
|
||||
[:title title]
|
||||
(theme-init-script)
|
||||
[:link {:rel "stylesheet" :href "/static/publish.css"}]]
|
||||
(head-node title)
|
||||
[:body
|
||||
[:main.wrap
|
||||
(toolbar-node
|
||||
|
||||
10
deps/publish/src/logseq/publish/routes.cljs
vendored
10
deps/publish/src/logseq/publish/routes.cljs
vendored
@@ -10,6 +10,8 @@
|
||||
|
||||
(def publish-css (resource/inline "logseq/publish/publish.css"))
|
||||
(def publish-js (resource/inline "logseq/publish/publish.js"))
|
||||
(def tabler-ext-js (resource/inline "js/tabler.ext.js"))
|
||||
(def tabler-extension-css (resource/inline "css/tabler-extension.css"))
|
||||
|
||||
(defn- request-password
|
||||
[request]
|
||||
@@ -540,6 +542,14 @@
|
||||
"cache-control" "public, max-age=31536000, immutable"}
|
||||
(publish-common/cors-headers))})
|
||||
|
||||
(and (= path "/static/tabler.ext.js") (= method "GET"))
|
||||
(js/Response.
|
||||
tabler-ext-js
|
||||
#js {:headers (publish-common/merge-headers
|
||||
#js {"content-type" "text/javascript; charset=utf-8"
|
||||
"cache-control" "public, max-age=31536000, immutable"}
|
||||
(publish-common/cors-headers))})
|
||||
|
||||
(and (string/starts-with? path "/page/") (= method "GET"))
|
||||
(handle-page-html request env)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user