@nextcloud/vue
Version:
Nextcloud vue components
420 lines (419 loc) • 13.1 kB
JavaScript
import '../assets/NcRichText-DqDAPQPD.css';
import { N as NcReferenceWidget } from "./referencePickerModal-ByI9zX0a.mjs";
import { U as URL_PATTERN, p as parseUrl, r as remarkAutolink, g as getRoute } from "./autolink-cbuFALXr.mjs";
import axios from "@nextcloud/axios";
import { getSharingToken } from "@nextcloud/sharing/public";
import { getCurrentUser } from "@nextcloud/auth";
import { generateOcsUrl } from "@nextcloud/router";
/* empty css */
import { n as normalizeComponent } from "./_plugin-vue2_normalizer-DU4iP6Vu.mjs";
import { N as NcCheckboxRadioSwitch } from "./NcCheckboxRadioSwitch-CvMEEI9x.mjs";
import { visit } from "unist-util-visit";
import { u } from "unist-builder";
import { G as GenRandomId } from "./GenRandomId-CMooMQt0.mjs";
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import breaks from "remark-breaks";
import remark2rehype from "remark-rehype";
import rehype2react from "rehype-react";
import rehypeExternalLinks from "rehype-external-links";
import { RouterLink } from "vue-router";
const _sfc_main$1 = {
name: "NcReferenceList",
components: {
NcReferenceWidget
},
props: {
text: {
type: String,
default: ""
},
referenceData: {
type: Object,
default: null
},
limit: {
type: Number,
default: 1
},
displayFallback: {
type: Boolean,
default: false
},
interactive: {
type: Boolean,
default: true
},
interactiveOptIn: {
type: Boolean,
default: false
}
},
data() {
return {
references: null,
loading: true
};
},
computed: {
isVisible() {
return this.loading || this.displayedReferences.length !== 0;
},
values() {
if (this.referenceData) {
return this.referenceData;
}
if (this.displayFallback && !this.loading && !this.references) {
return [this.fallbackReference];
}
return this.references ? Object.values(this.references) : [];
},
firstReference() {
var _a;
return (_a = this.values[0]) != null ? _a : null;
},
displayedReferences() {
return this.values.slice(0, this.limit);
},
fallbackReference() {
return {
accessible: true,
openGraphObject: {
id: this.text,
link: this.text,
name: this.text
},
richObjectType: "open-graph"
};
}
},
watch: {
text: "fetch"
},
mounted() {
this.fetch();
},
methods: {
fetch() {
this.loading = true;
if (this.referenceData) {
this.references = null;
this.loading = false;
return;
}
if (!new RegExp(URL_PATTERN).exec(this.text)) {
this.references = null;
this.loading = false;
return;
}
this.resolve().then((response) => {
this.references = response.data.ocs.data.references;
this.loading = false;
this.$emit("loaded");
}).catch((error) => {
console.error("Failed to extract references", error);
this.loading = false;
this.$emit("loaded");
});
},
resolve() {
const match = new RegExp(URL_PATTERN).exec(this.text.trim());
const isPublic = getCurrentUser() === null;
if (this.limit === 1 && match) {
return isPublic ? axios.get(generateOcsUrl("references/resolvePublic") + "?reference=".concat(encodeURIComponent(match[0]), "&sharingToken=").concat(getSharingToken())) : axios.get(generateOcsUrl("references/resolve") + "?reference=".concat(encodeURIComponent(match[0])));
}
return isPublic ? axios.post(generateOcsUrl("references/extractPublic"), {
text: this.text,
resolve: true,
limit: this.limit,
sharingToken: getSharingToken()
}) : axios.post(generateOcsUrl("references/extract"), {
text: this.text,
resolve: true,
limit: this.limit
});
}
}
};
var _sfc_render$1 = function render() {
var _vm = this, _c = _vm._self._c;
return _vm.isVisible ? _c("div", { staticClass: "widgets--list", class: { "icon-loading": _vm.loading } }, _vm._l(_vm.displayedReferences, function(reference) {
var _a;
return _c("div", { key: (_a = reference == null ? void 0 : reference.openGraphObject) == null ? void 0 : _a.id }, [_c("NcReferenceWidget", { attrs: { "reference": reference, "interactive": _vm.interactive, "interactive-opt-in": _vm.interactiveOptIn } })], 1);
}), 0) : _vm._e();
};
var _sfc_staticRenderFns$1 = [];
var __component__$1 = /* @__PURE__ */ normalizeComponent(
_sfc_main$1,
_sfc_render$1,
_sfc_staticRenderFns$1,
false,
null,
"4d1ff3f6"
);
const NcReferenceList = __component__$1.exports;
const remarkPlaceholder = function() {
return function(ast) {
visit(ast, (node) => node.type === "text", visitor);
function visitor(node, index, parent) {
const placeholders = node.value.split(/(\{[a-z\-_.0-9]+\})/ig).map((entry, index2, list) => {
const matches = entry.match(/^\{([a-z\-_.0-9]+)\}$/i);
if (!matches) {
return u("text", entry);
}
const [, component] = matches;
return u("element", {
tagName: "#".concat(component)
});
});
parent.children.splice(index, 1, ...placeholders);
}
};
};
const prepareTextNode = ({ h, context }, text) => {
if (context.autolink) {
text = parseUrl(text);
}
if (Array.isArray(text)) {
return text.map((entry) => {
if (typeof entry === "string") {
return entry;
}
const { component, props } = entry;
const componentClass = component.name === "NcLink" ? void 0 : "rich-text--component";
return h(component, {
props,
class: componentClass
});
});
}
return text;
};
const _sfc_main = {
name: "NcRichText",
components: {
NcReferenceList
},
props: {
text: {
type: String,
default: ""
},
arguments: {
type: Object,
default: () => {
return {};
}
},
referenceLimit: {
type: Number,
default: 0
},
referenceInteractive: {
type: Boolean,
default: true
},
/** Provide data upfront to avoid extra http request */
references: {
type: Object,
default: null
},
markdownCssClasses: {
type: Object,
default: () => {
return {
a: "rich-text--external-link",
ol: "rich-text--ordered-list",
ul: "rich-text--un-ordered-list",
li: "rich-text--list-item",
strong: "rich-text--strong",
em: "rich-text--italic",
h1: "rich-text--heading rich-text--heading-1",
h2: "rich-text--heading rich-text--heading-2",
h3: "rich-text--heading rich-text--heading-3",
h4: "rich-text--heading rich-text--heading-4",
h5: "rich-text--heading rich-text--heading-5",
h6: "rich-text--heading rich-text--heading-6",
hr: "rich-text--hr",
table: "rich-text--table",
pre: "rich-text--pre",
code: "rich-text--code",
blockquote: "rich-text--blockquote"
};
}
},
useMarkdown: {
type: Boolean,
default: false
},
/** Provide GitHub Flavored Markdown syntax */
useExtendedMarkdown: {
type: Boolean,
default: false
},
/** Provide event from rendered markdown inputs */
interactive: {
type: Boolean,
default: false
},
autolink: {
type: Boolean,
default: true
}
},
emits: ["interact:todo"],
data() {
return {
parentId: GenRandomId(5)
};
},
methods: {
renderPlaintext(h) {
const context = this;
const placeholders = this.text.split(/(\{[a-z\-_.0-9]+\})/ig).map(function(entry, index, list) {
const matches = entry.match(/^\{([a-z\-_.0-9]+)\}$/i);
if (!matches) {
return prepareTextNode({ h, context }, entry);
}
const argumentId = matches[1];
const argument = context.arguments[argumentId];
if (typeof argument === "object") {
const { component, props } = argument;
return h(component, {
props,
class: "rich-text--component"
});
}
if (argument) {
return h("span", { class: "rich-text--fallback" }, argument);
}
return entry;
});
return h("div", { class: "rich-text--wrapper" }, [
h("div", {}, placeholders.flat()),
this.referenceLimit > 0 ? h("div", { class: "rich-text--reference-widget" }, [
h(NcReferenceList, {
props: {
text: this.text,
referenceData: this.references,
interactive: this.referenceInteractive
}
})
]) : null
]);
},
renderMarkdown(h) {
const renderedMarkdown = unified().use(remarkParse).use(remarkAutolink, {
autolink: this.autolink,
useMarkdown: this.useMarkdown,
useExtendedMarkdown: this.useExtendedMarkdown
}).use(this.useExtendedMarkdown ? remarkGfm : void 0).use(breaks).use(remark2rehype, {
handlers: {
component(toHast, node) {
return toHast(node, node.component, { value: node.value });
}
}
}).use(remarkPlaceholder).use(rehypeExternalLinks, {
target: "_blank",
rel: ["noopener noreferrer"]
}).use(rehype2react, {
createElement: (tag, attrs, children) => {
children = children == null ? void 0 : children.map(
(child) => typeof child === "string" ? child.replace(/</gmi, "<") : child
);
if (!tag.startsWith("#")) {
if (this.useExtendedMarkdown) {
let nestedNode = null;
if (tag === "li" && Array.isArray(children) && children[0].tag === "input" && children[0].data.attrs.type === "checkbox") {
const [inputNode, ...labelParts] = children;
const nestedNodeIndex = labelParts.findIndex((child) => ["ul", "ol", "li", "blockquote", "pre"].includes(child.tag));
if (nestedNodeIndex !== -1) {
nestedNode = labelParts[nestedNodeIndex];
labelParts.splice(nestedNodeIndex);
}
const id = this.parentId + "-markdown-input-" + GenRandomId(5);
const inputComponent = h(NcCheckboxRadioSwitch, {
attrs: {
...inputNode.data.attrs,
id,
disabled: !this.interactive
},
on: {
"update:checked": () => {
this.$emit("interact:todo", id);
}
}
}, labelParts);
return h(tag, attrs, [inputComponent, nestedNode]);
}
}
if (tag === "a") {
const route = getRoute(this.$router, attrs.attrs.href);
if (route) {
delete attrs.attrs.href;
delete attrs.attrs.target;
return h(RouterLink, {
...attrs,
props: {
to: route
}
}, children);
}
}
return h(tag, attrs, children);
}
const placeholder = this.arguments[tag.slice(1)];
if (!placeholder) {
return h("span", { ...{ attrs }, ...{ class: "rich-text--fallback" } }, ["{".concat(tag.slice(1), "}")]);
}
if (!placeholder.component) {
return h("span", attrs, [placeholder]);
}
return h(
placeholder.component,
{
attrs,
props: placeholder.props,
class: "rich-text--component"
},
children
);
},
prefix: false
}).processSync(
this.text.replace(/</gmi, "<").replace(/>/gmi, ">")
).result;
return h("div", { class: "rich-text--wrapper rich-text--wrapper-markdown" }, [
renderedMarkdown,
this.referenceLimit > 0 ? h("div", { class: "rich-text--reference-widget" }, [
h(NcReferenceList, {
props: {
text: this.text,
referenceData: this.references,
interactive: this.referenceInteractive
}
})
]) : null
]);
}
},
render(h) {
return this.useMarkdown || this.useExtendedMarkdown ? this.renderMarkdown(h) : this.renderPlaintext(h);
}
};
const _sfc_render = null;
const _sfc_staticRenderFns = null;
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns,
false,
null,
"3b61be27"
);
const NcRichText = __component__.exports;
export {
NcRichText as N,
NcReferenceList as a
};