Skip to content

Commit f3876e0

Browse files
committed
feat: 新增快速插入 Obsidian Callouts #254
1 parent 8ca32e8 commit f3876e0

6 files changed

Lines changed: 297 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
- feat: 添加最新帖子后台预览功能 #253
2-
- feat: 添加智能文字悬停提示功能 #253
3-
- feat: 添加最新帖子点击自动移除功能 #253
1+
- feat: 新增快速插入 Obsidian Callouts #254

entrypoints/App.vue

Lines changed: 6 additions & 1 deletion
Large diffs are not rendered by default.
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
<template>
2+
<div class="item">
3+
<div class="tit">{{ sort }}. 是否显示 Obsidian Callouts</div>
4+
<input
5+
type="checkbox"
6+
:checked="modelValue"
7+
@change="$emit('update:modelValue', $event.target.checked)"
8+
/>
9+
</div>
10+
</template>
11+
12+
<script>
13+
const emojiSet = [
14+
{
15+
id: 1,
16+
html: `<blockquote data-callout-type="note" class="callout" dir="auto" style="background-color: rgba(8, 109, 221, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-far-pen-to-square svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-pen-to-square"></use></svg></span><span class="callout-title-inner">Note</span></div>
17+
<div class="callout-content"><p>
18+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
19+
value: `> [!note]
20+
> Lorem ipsum dolor sit amet`,
21+
},
22+
{
23+
id: 2,
24+
html: `<blockquote data-callout-type="abstract" class="callout" dir="auto" style="background-color: rgba(0, 191, 188, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-far-clipboard svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-clipboard"></use></svg></span><span class="callout-title-inner">Abstract</span></div>
25+
<div class="callout-content"><p>
26+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
27+
value: `> [!abstract]
28+
> Lorem ipsum dolor sit amet`,
29+
},
30+
{
31+
id: 3,
32+
html: `<blockquote data-callout-type="info" class="callout" dir="auto" style="background-color: rgba(2, 122, 255, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-far-lightbulb svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-lightbulb"></use></svg></span><span class="callout-title-inner">Info</span></div>
33+
<div class="callout-content"><p>
34+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
35+
value: `> [!info]
36+
> Lorem ipsum dolor sit amet`,
37+
},
38+
{
39+
id: 4,
40+
html: `<blockquote data-callout-type="todo" class="callout" dir="auto" style="background-color: rgba(2, 122, 255, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-far-circle-check svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-circle-check"></use></svg></span><span class="callout-title-inner">Todo</span></div>
41+
<div class="callout-content"><p>
42+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
43+
value: `> [!todo]
44+
> Lorem ipsum dolor sit amet`,
45+
},
46+
{
47+
id: 5,
48+
html: `<blockquote data-callout-type="tip" class="callout" dir="auto" style="background-color: rgba(0, 191, 188, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-fire-flame-curved svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#fire-flame-curved"></use></svg></span><span class="callout-title-inner">Tip</span></div>
49+
<div class="callout-content"><p>
50+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
51+
value: `> [!tip]
52+
> Lorem ipsum dolor sit amet`,
53+
},
54+
{
55+
id: 6,
56+
html: `<blockquote data-callout-type="success" class="callout" dir="auto" style="background-color: rgba(68, 207, 110, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-check svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#check"></use></svg></span><span class="callout-title-inner">Success</span></div>
57+
<div class="callout-content"><p>
58+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
59+
value: `> [!success]
60+
> Lorem ipsum dolor sit amet`,
61+
},
62+
{
63+
id: 7,
64+
html: `<blockquote data-callout-type="question" class="callout" dir="auto" style="background-color: rgba(236, 117, 0, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-far-circle-question svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-circle-question"></use></svg></span><span class="callout-title-inner">Question</span></div>
65+
<div class="callout-content"><p>
66+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
67+
value: `> [!question]
68+
> Lorem ipsum dolor sit amet`,
69+
},
70+
{
71+
id: 8,
72+
html: `<blockquote data-callout-type="warning" class="callout" dir="auto" style="background-color: rgba(236, 117, 0, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-triangle-exclamation svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#triangle-exclamation"></use></svg></span><span class="callout-title-inner">Warning</span></div>
73+
<div class="callout-content"><p>
74+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
75+
value: `> [!warning]
76+
> Lorem ipsum dolor sit amet`,
77+
},
78+
{
79+
id: 9,
80+
html: `<blockquote data-callout-type="failure" class="callout" dir="auto" style="background-color: rgba(233, 49, 71, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-xmark svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#xmark"></use></svg></span><span class="callout-title-inner">Failure</span></div>
81+
<div class="callout-content"><p>
82+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
83+
value: `> [!failure]
84+
> Lorem ipsum dolor sit amet`,
85+
},
86+
{
87+
id: 10,
88+
html: `<blockquote data-callout-type="danger" class="callout" dir="auto" style="background-color: rgba(233, 49, 71, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-bolt svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#bolt"></use></svg></span><span class="callout-title-inner">Danger</span></div>
89+
<div class="callout-content"><p>
90+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
91+
value: `> [!danger]
92+
> Lorem ipsum dolor sit amet`,
93+
},
94+
{
95+
id: 11,
96+
html: `<blockquote data-callout-type="bug" class="callout" dir="auto" style="background-color: rgba(233, 49, 71, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-bug svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#bug"></use></svg></span><span class="callout-title-inner">Bug</span></div>
97+
<div class="callout-content"><p>
98+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
99+
value: `> [!bug]
100+
> Lorem ipsum dolor sit amet`,
101+
},
102+
{
103+
id: 12,
104+
html: `<blockquote data-callout-type="example" class="callout" dir="auto" style="background-color: rgba(120, 82, 238, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-list svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#list"></use></svg></span><span class="callout-title-inner">Example</span></div>
105+
<div class="callout-content"><p>
106+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
107+
value: `> [!example]
108+
> Lorem ipsum dolor sit amet`,
109+
},
110+
{
111+
id: 13,
112+
html: `<blockquote data-callout-type="quote" class="callout" dir="auto" style="background-color: rgba(158, 158, 158, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-quote-left svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#quote-left"></use></svg></span><span class="callout-title-inner">Quote</span></div>
113+
<div class="callout-content"><p>
114+
Lorem ipsum dolor sit amet</p></div></blockquote>`,
115+
value: `> [!quote]
116+
> Lorem ipsum dolor sit amet`,
117+
},
118+
{
119+
id: 14,
120+
html: `<blockquote data-callout-type="warning" class="callout is-collapsible" dir="auto" style="background-color: rgba(236, 117, 0, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-triangle-exclamation svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#triangle-exclamation"></use></svg></span><span class="callout-title-inner">别看了</span><span class="callout-fold"><svg class="fa d-icon d-icon-chevron-down svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#chevron-down"></use></svg></span></div>
121+
<div class="callout-content"><p>
122+
快折起来。</p></div></blockquote>`,
123+
value: `> [!warning]+ 别看了
124+
> 快折起来。`,
125+
},
126+
{
127+
id: 15,
128+
html: `<blockquote data-callout-type="success" class="callout is-collapsible is-collapsed" dir="auto" style="background-color: rgba(68, 207, 110, 0.1);"><div class="callout-title"><span class="callout-icon"><svg class="fa d-icon d-icon-check svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#check"></use></svg></span><span class="callout-title-inner">非常成功</span><span class="callout-fold is-collapsed"><svg class="fa d-icon d-icon-chevron-down svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#chevron-down"></use></svg></span></div>
129+
<div class="callout-content" style="display: none;"><p>
130+
确实如此。</p></div></blockquote>`,
131+
value: `> [!success]- 非常成功
132+
> 确实如此。`,
133+
},
134+
];
135+
136+
export default {
137+
data() {
138+
return {
139+
emojiTimer: null,
140+
};
141+
},
142+
props: ["modelValue", "sort"],
143+
emits: ["update:modelValue"],
144+
created() {
145+
if (this.modelValue) {
146+
this.setupEmojiButton();
147+
}
148+
},
149+
methods: {
150+
setupEmojiButton() {
151+
this.emojiTimer = setInterval(() => {
152+
var editor = document.querySelector(".d-editor-button-bar");
153+
if (!document.querySelector(".obsidian-callouts-button") && editor) {
154+
var ObsidianCalloutsBtn = document.createElement("button");
155+
ObsidianCalloutsBtn.classList.add(
156+
"btn",
157+
"no-text",
158+
"btn-icon",
159+
"emoji",
160+
"obsidian-callouts-button"
161+
);
162+
ObsidianCalloutsBtn.title = "插入 Obsidian Callouts";
163+
ObsidianCalloutsBtn.innerHTML = `<svg class="fa d-icon d-icon-far-lightbulb svg-icon svg-string" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><use href="#far-lightbulb"></use></svg>`;
164+
editor.appendChild(ObsidianCalloutsBtn);
165+
ObsidianCalloutsBtn.addEventListener("click", function () {
166+
var ObsidianCalloutsPicke = document.createElement("div");
167+
ObsidianCalloutsPicke.className = "ObsidianCalloutsPicke";
168+
var emojiSetHtml = emojiSet
169+
.map((emo) => `<div title="${emo.value}">${emo.html}</div>`)
170+
.join("");
171+
ObsidianCalloutsPicke.innerHTML = emojiSetHtml;
172+
ObsidianCalloutsPicke.style.position = "absolute";
173+
ObsidianCalloutsPicke.style.background = "#FFF";
174+
ObsidianCalloutsPicke.style.border = "1px solid #ddd";
175+
ObsidianCalloutsPicke.style.padding = "10px";
176+
if (
177+
document.body.contains(document.querySelector(".ObsidianCalloutsPicke"))
178+
) {
179+
document.querySelector(".ObsidianCalloutsPicke").remove();
180+
} else {
181+
ObsidianCalloutsBtn.after(ObsidianCalloutsPicke);
182+
}
183+
ObsidianCalloutsPicke.addEventListener("click", function (e) {
184+
var textAreaObsidianCallouts = document.querySelector(".d-editor-input");
185+
if (!textAreaObsidianCallouts) {
186+
alert("找不到输入框");
187+
return;
188+
}
189+
190+
var clickedItem = e.target.closest("[title]"); // 查找有 title 属性的最近父级
191+
192+
var emojiMarkdownObsidianCallouts = `${
193+
e.target.title || clickedItem?.title || ""
194+
}`;
195+
196+
// 在光标位置插入 Obsidian Callouts
197+
var startPosOb = textAreaObsidianCallouts.selectionStart;
198+
var endPosOb = textAreaObsidianCallouts.selectionEnd;
199+
textAreaObsidianCallouts.value =
200+
textAreaObsidianCallouts.value.substring(0, startPosOb) +
201+
emojiMarkdownObsidianCallouts +
202+
textAreaObsidianCallouts.value.substring(
203+
endPosOb,
204+
textAreaObsidianCallouts.value.length
205+
);
206+
// 触发输入事件
207+
var event = new Event("input", {
208+
bubbles: true,
209+
cancelable: true,
210+
});
211+
textAreaObsidianCallouts.dispatchEvent(event);
212+
// 隐藏选择器
213+
ObsidianCalloutsPicke.remove();
214+
});
215+
});
216+
}
217+
}, 100);
218+
},
219+
},
220+
beforeUnmount() {
221+
if (this.emojiTimer) {
222+
clearInterval(this.emojiTimer);
223+
this.emojiTimer = null;
224+
}
225+
},
226+
beforeDestroy() {
227+
if (this.emojiTimer) {
228+
clearInterval(this.emojiTimer);
229+
this.emojiTimer = null;
230+
}
231+
},
232+
};
233+
234+
// 为了保持原有功能,保留全局的表情插入函数
235+
window.insertEmojiObsidian = function (event) {
236+
var textAreaObsidianCallouts = document.querySelector(".d-editor-input");
237+
if (!textAreaObsidianCallouts) {
238+
alert("找不到输入框");
239+
return;
240+
}
241+
var emojiMarkdownObsidianCallouts = `:${event.target.getAttribute("name")}: `;
242+
243+
// 在光标位置插入表情包
244+
var startPosObsidian = textAreaObsidianCallouts.selectionStart;
245+
var endPosObsidian = textAreaObsidianCallouts.selectionEnd;
246+
textAreaObsidianCallouts.value =
247+
textAreaObsidianCallouts.value.substring(0, startPosObsidian) +
248+
emojiMarkdownObsidianCallouts +
249+
textAreaObsidianCallouts.value.substring(
250+
endPosObsidian,
251+
textAreaObsidianCallouts.value.length
252+
);
253+
254+
// 触发输入事件
255+
var inputEventObsidian = new Event("input", {
256+
bubbles: true,
257+
cancelable: true,
258+
});
259+
textAreaObsidianCallouts.dispatchEvent(inputEventObsidian);
260+
261+
// 隐藏选择器
262+
if (document.querySelector(".ObsidianCalloutsPicke")) {
263+
document.querySelector(".ObsidianCalloutsPicke").remove();
264+
}
265+
};
266+
</script>

entrypoints/app.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,4 +1223,23 @@ body.body-preview #main-outlet-wrapper {
12231223

12241224
#linuxDoLevelPopupContent .text-red-500 {
12251225
color: rgb(239, 68, 68);
1226+
}
1227+
1228+
.ObsidianCalloutsPicke {
1229+
width: 560px;
1230+
top: 0;
1231+
left: 100%;
1232+
position: absolute;
1233+
height: 100%;
1234+
overflow: auto;
1235+
background-color: rgba(0, 0, 0, 0.8);
1236+
padding: 10px;
1237+
border-radius: 5px;
1238+
z-index: 9;
1239+
}
1240+
1241+
.ObsidianCalloutsPicke>div {
1242+
width: 100%;
1243+
margin-bottom: 10px;
1244+
cursor: pointer;
12261245
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "linuxdo-scripts",
33
"description": "manifest.json description",
44
"private": true,
5-
"version": "1.4.8",
5+
"version": "1.4.9",
66
"type": "module",
77
"scripts": {
88
"dev": "wxt",

version-log.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.4.9
2+
3+
- feat: 新增快速插入 Obsidian Callouts #254
4+
15
## 1.4.8
26

37
- feat: 添加最新帖子后台预览功能 #253

0 commit comments

Comments
 (0)