-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontent.tsx
More file actions
176 lines (154 loc) · 5.97 KB
/
content.tsx
File metadata and controls
176 lines (154 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import type { PlasmoCSConfig } from "plasmo"
import { useStorage } from "@plasmohq/storage/hook"
import { useEffect } from "react"
import hljs from "highlight.js"
import { Code2 } from "lucide-react"
import stackoverflowDark from "data-text:highlight.js/styles/stackoverflow-dark.css"
import stackoverflowLight from "data-text:highlight.js/styles/stackoverflow-light.css"
import githubDark from "data-text:highlight.js/styles/github-dark.css"
import githubLight from "data-text:highlight.js/styles/github.css"
import atomOneDark from "data-text:highlight.js/styles/atom-one-dark.css"
import tailwindCss from "data-text:./style.css"
const themeMap: Record<string, string> = {
"stackoverflow-dark.css": stackoverflowDark,
"stackoverflow-light.css": stackoverflowLight,
"github-dark.css": githubDark,
"github.css": githubLight,
"atom-one-dark.css": atomOneDark
}
export const config: PlasmoCSConfig = {
matches: ["https://v.flomoapp.com/*", "https://flomoapp.com/*"],
all_frames: true
}
export const getStyle = () => {
const style = document.createElement("style")
style.textContent = tailwindCss
return style
}
function highlightCodeBlocks() {
const memos = document.getElementsByClassName("richText")
const memos_array = Array.from(memos)
memos_array.forEach((memo) => {
let children = memo.children
const memo_p_array = Array.from(children)
let languageFlag = false
let codeContentArr: string[] = []
let languageType = ""
for (let i = 0; i < memo_p_array.length; i++) {
const pNode = memo_p_array[i]
const innerHTML = pNode.innerHTML
if (innerHTML.startsWith("```") && innerHTML.substring(3) !== "") {
languageType = "language-" + innerHTML.substring(3).trim()
languageFlag = true
if (memo.contains(pNode)) memo.removeChild(pNode)
continue
} else if (innerHTML.startsWith("```") && innerHTML.substring(3) === "") {
languageFlag = false
const codeForCopy = [...codeContentArr]
let pre = document.createElement("pre")
let code = document.createElement("code")
code.innerHTML = codeContentArr.join("\n")
if (languageType) code.className = languageType
let wrapper = document.createElement("div")
wrapper.style.position = "relative"
wrapper.style.margin = "10px 0"
wrapper.style.borderRadius = "8px"
wrapper.style.overflow = "hidden"
wrapper.style.border = "1px solid rgba(136, 148, 168, 0.2)"
let copyBtn = document.createElement("button")
copyBtn.innerHTML = "Copy"
copyBtn.style.position = "absolute"
copyBtn.style.top = "8px"
copyBtn.style.right = "8px"
copyBtn.style.fontSize = "12px"
copyBtn.style.padding = "4px 8px"
copyBtn.style.background = "#0f172a" // slate-900
copyBtn.style.color = "#f8fafc" // slate-50
copyBtn.style.border = "1px solid #334155" // slate-700
copyBtn.style.borderRadius = "4px"
copyBtn.style.cursor = "pointer"
copyBtn.style.transition = "all 0.2s ease"
// Handlers for hover effects to make it feel premium
copyBtn.onmouseenter = () => {
copyBtn.style.background = "#1e293b" // slate-800
}
copyBtn.onmouseleave = () => {
copyBtn.style.background = "#0f172a"
}
copyBtn.addEventListener("click", function (e) {
e.stopPropagation()
const tempElement = document.createElement("div")
let decodedContent = codeForCopy.map(c => {
tempElement.innerHTML = c
return tempElement.textContent || tempElement.innerText
})
navigator.clipboard.writeText(decodedContent.join("\n")).then(() => {
copyBtn.innerHTML = "Copied!"
copyBtn.style.color = "#34d399" // emerald-400
setTimeout(() => {
copyBtn.innerHTML = "Copy"
copyBtn.style.color = "#f8fafc"
}, 1500)
})
})
pre.appendChild(code)
wrapper.appendChild(pre)
wrapper.appendChild(copyBtn)
pNode.innerHTML = ""
pNode.appendChild(wrapper)
codeContentArr = []
languageType = ""
continue
} else {
if (languageFlag) {
let content = innerHTML
const tempDiv = document.createElement("div")
tempDiv.innerHTML = content
const links = tempDiv.querySelectorAll("a")
links.forEach((link) => {
const href = link.getAttribute("href")
if (href) {
const textNode = document.createTextNode(href)
link.parentNode?.replaceChild(textNode, link)
}
})
codeContentArr.push(tempDiv.innerHTML)
if (memo.contains(pNode)) memo.removeChild(pNode)
}
}
}
})
// Configure highlight.js to ignore unescaped HTML warning
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll()
}
export default function FlomoCodeOverlay() {
const [theme] = useStorage("chooseTheme", "stackoverflow-dark.css")
// Sync theme
useEffect(() => {
if (!theme) return
const cssText = themeMap[theme] || themeMap["stackoverflow-dark.css"]
let styleEl = document.getElementById("flomo-code-theme")
if (!styleEl) {
styleEl = document.createElement("style")
styleEl.id = "flomo-code-theme"
document.head.appendChild(styleEl)
}
styleEl.textContent = cssText
}, [theme])
// Listen for message from background layer & Initial Highlight
useEffect(() => {
setTimeout(() => {
highlightCodeBlocks()
}, 1000) // initial attempt
const listener = (request: any, sender: any, sendResponse: any) => {
if (request.action === "highlightCode") {
setTimeout(highlightCodeBlocks, 300) // slight delay to ensure DOM is updated
sendResponse({ status: "OK" })
}
}
chrome.runtime.onMessage.addListener(listener)
return () => chrome.runtime.onMessage.removeListener(listener)
}, [])
return null
}