Skip to content

Commit

Permalink
fix: preserve reference links when copy-pasting from preview (#856)
Browse files Browse the repository at this point in the history
* fix: preserve reference links when copy-pasting from preview

* chore: abstract as util function
  • Loading branch information
dcshzj authored Nov 5, 2024
1 parent bb46aee commit fb6377e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type PreviewProps = IsomerSchema & {
// Add a fake link component to prevent the preview from navigating away
const FakeLink = forwardRef<HTMLAnchorElement, PropsWithChildren<unknown>>(
({ children, ...rest }, ref) => (
<a {...rest} ref={ref} href="#" onClick={(e) => e.preventDefault()}>
<a {...rest} ref={ref} onClick={(e) => e.preventDefault()}>
{children}
</a>
),
Expand Down
2 changes: 2 additions & 0 deletions apps/studio/src/features/editing-experience/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ export const TYPE_TO_ICON: Record<
// iframe-formsg
// iframe-youtube
}

export const REFERENCE_LINK_REGEX = /\[resource:(\d+):(\d+)\]/
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ import { TableHeader } from "@tiptap/extension-table-header"
import { TableRow } from "@tiptap/extension-table-row"
import { Text } from "@tiptap/extension-text"
import { Underline } from "@tiptap/extension-underline"
import { Plugin, PluginKey } from "@tiptap/pm/state"
import { textblockTypeInputRule, useEditor } from "@tiptap/react"

import { getHtmlWithRelativeReferenceLinks } from "../utils"

const HEADING_LEVELS: Level[] = [2, 3, 4, 5]

export interface BaseEditorProps {
Expand All @@ -34,7 +37,28 @@ export interface BaseEditorProps {
}

const BASE_EXTENSIONS: Extensions = [
Link.configure({
Link.extend({
addProseMirrorPlugins() {
return [
// NOTE: This plugin is used to transform links inside the HTML content
// copied by the user from the preview, as browsers will automatically
// transform relative links (in the form of [resource:siteId:resourceId])
// into absolute links:
// https://studio.isomer.gov.sg/sites/1/pages/[resource:siteId:resourceId]
// This plugin will transform the absolute links back into the relative
// links, so that the original link is preserved in the editor.
new Plugin({
key: new PluginKey("transformReferenceLinks"),
props: {
transformPastedHTML(html, _) {
return getHtmlWithRelativeReferenceLinks(html)
},
},
}),
...(this.parent?.() ?? []),
]
},
}).configure({
HTMLAttributes: {
rel: "",
target: "_self",
Expand Down
16 changes: 16 additions & 0 deletions apps/studio/src/features/editing-experience/utils.ts
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
import { REFERENCE_LINK_REGEX } from "./constants"

export const dataAttr = (value: unknown) => (!!value ? true : undefined)

// This function converts HTML with absolute reference links (something like
// https://studio.isomer.gov.sg/sites/1/pages/[resource:siteId:resourceId]) into
// relative reference links ([resource:siteId:resourceId])
export const getHtmlWithRelativeReferenceLinks = (html: string) =>
html.replaceAll(
new RegExp(
`href="(?:http|https):\/\/[^[]*\/${REFERENCE_LINK_REGEX.source}"`,
"g",
),
(_, siteId, resourceId) => {
return `href="[resource:${siteId}:${resourceId}]"`
},
)
4 changes: 3 additions & 1 deletion apps/studio/src/utils/link.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { REFERENCE_LINK_REGEX } from "~/features/editing-experience/constants"

interface GetReferenceLinkParams {
siteId: string
resourceId: string
Expand All @@ -19,7 +21,7 @@ export const getReferenceLink = ({
export const getResourceIdFromReferenceLink = (
referenceLink: string,
): string => {
const match = /\[resource:(\d+):(\d+)\]/.exec(referenceLink)
const match = REFERENCE_LINK_REGEX.exec(referenceLink)
if (!match) {
return ""
}
Expand Down

0 comments on commit fb6377e

Please sign in to comment.