UNPKG

@nextcloud/vue

Version:
420 lines (419 loc) 13.1 kB
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(/&lt;/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, "&lt;").replace(/&gt;/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 };