mirror of
https://github.com/siyuan-note/siyuan
synced 2026-04-21 13:37:52 +00:00
🎨 Support auto-convert pasted URL to clickable link format (#17338)
* feat: auto-convert pasted URL to clickable link format (#17337) Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/cdea999d-27c0-4260-a0b4-519e011e6667 Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * fix: use angle bracket URL syntax for markdown link safety Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/cdea999d-27c0-4260-a0b4-519e011e6667 Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * feat: add pasteURLAutoConvert editor setting to control URL auto-linking Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/1b722c05-e69f-4964-89bb-7f928d5adeb3 Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * refactor: reuse setInlineMark for paste URL auto-convert, matching Ctrl+K link handler pattern Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/332d1b44-cebe-45b2-833e-72d7e3253a3d Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * refactor: extract shared resolveLinkDest and genLinkText utility functions Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/316f674d-3ce9-4b40-8711-08edb8af1aec Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * Disable automatic URL conversion on paste * feat: add stripScheme option to genLinkText - keep scheme for paste, strip for Ctrl+K Agent-Logs-Url: https://github.com/bytemain/siyuan/sessions/960eaf33-f873-4709-8e63-8d9b473de4ee Co-authored-by: bytemain <13938334+bytemain@users.noreply.github.com> * Improve link handling in paste function Refactor link handling in paste function to update range after setting inline mark. * Fix return statement in paste.ts * style: fix json tag alignment in Editor struct * Update app/src/mobile/settings/editor.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(Link): handle URI decoding more safely in genLinkText Add try-catch block to prevent URI decoding errors and make decoding optional * feat(editor): add auto URL to link conversion on paste Implement automatic conversion of pasted URLs to clickable links when the pasteURLAutoConvert setting is enabled. This improves user experience by eliminating the manual step of creating links for pasted URLs. The functionality is extracted into a separate function for better code organization and reuse. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
918d1bd9f9
commit
5b84279673
24 changed files with 130 additions and 12 deletions
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "تغيير اتجاه المقارنة",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> للبحث عن المستندات فقط",
|
||||
"onlySearchForDocTip": "بعد التمكين، ]] للبحث عن مراجع الكتلة فقط في أسماء المستندات",
|
||||
"pasteURLAutoConvert": "تحويل عنوان URL الملصق تلقائيًا إلى رابط",
|
||||
"pasteURLAutoConvertTip": "عند التمكين، سيؤدي لصق عنوان URL يبدأ بـ http:// أو https:// إلى تحويله تلقائيًا إلى رابط قابل للنقر",
|
||||
"ocrResult": "نص نتيجة OCR",
|
||||
"reOCR": "إعادة OCR",
|
||||
"continueReview1": "متابعة المراجعة",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Vergleichsrichtung wechseln",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> nur Dokumente suchen",
|
||||
"onlySearchForDocTip": "Nach der Aktivierung wird [[ oder 【【 verwendet, um nach Blockreferenzen nur in Dokumentnamen zu suchen",
|
||||
"pasteURLAutoConvert": "Eingefügte URLs automatisch in Links umwandeln",
|
||||
"pasteURLAutoConvertTip": "Wenn aktiviert, werden URLs, die mit http:// oder https:// beginnen, beim Einfügen automatisch in klickbare Links umgewandelt",
|
||||
"ocrResult": "OCR-Ergebnistext",
|
||||
"reOCR": "Re OCR",
|
||||
"continueReview1": "Überprüfung fortsetzen",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Switch comparison direction",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> only search documents",
|
||||
"onlySearchForDocTip": "When enabled, [[ or 【【 to search for block references only in doc names",
|
||||
"pasteURLAutoConvert": "Auto-convert pasted URL to link",
|
||||
"pasteURLAutoConvertTip": "When enabled, pasting a URL starting with http:// or https:// will automatically convert it to a clickable link",
|
||||
"ocrResult": "OCR result text",
|
||||
"reOCR": "Re OCR",
|
||||
"continueReview1": "Continue Review",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Cambiar dirección de comparación",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> solo buscar documentos",
|
||||
"onlySearchForDocTip": "Después de habilitar, [[ o 【【 para buscar referencias de bloque solo en nombres de documentos",
|
||||
"pasteURLAutoConvert": "Convertir automáticamente la URL pegada en enlace",
|
||||
"pasteURLAutoConvertTip": "Cuando está habilitado, pegar una URL que comience con http:// o https:// la convertirá automáticamente en un enlace clicable",
|
||||
"ocrResult": "Texto de resultado de OCR",
|
||||
"reOCR": "Re-OCR",
|
||||
"continueReview1": "Continuar revisión",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Changer le sens de comparaison",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> rechercher uniquement les documents",
|
||||
"onlySearchForDocTip": "Après l'activation, [[ ou 【【 pour rechercher des références de bloc uniquement dans les noms de documents",
|
||||
"pasteURLAutoConvert": "Convertir automatiquement les URL collées en liens",
|
||||
"pasteURLAutoConvertTip": "Lorsque cette option est activée, coller une URL commençant par http:// ou https:// la convertit automatiquement en lien cliquable",
|
||||
"ocrResult": "Texte du résultat OCR",
|
||||
"reOCR": "ReOCR",
|
||||
"continueReview1": "Continuer la révision",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "שנה כיוון השוואה",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> חפש רק מסמכים",
|
||||
"onlySearchForDocTip": "לאחר הפעלה, חפש באמצעות [[ או 【【 רק התייחסויות בלוקים בשמות המסמכים",
|
||||
"pasteURLAutoConvert": "המרה אוטומטית של כתובת URL מודבקת לקישור",
|
||||
"pasteURLAutoConvertTip": "כאשר מופעל, הדבקת כתובת URL שמתחילה ב-http:// או https:// תמיר אותה אוטומטית לקישור לחיץ",
|
||||
"ocrResult": "טקסט תוצאת OCR",
|
||||
"reOCR": "OCR מחדש",
|
||||
"continueReview1": "המשך סקירה",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Cambia direzione di confronto",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> cerca solo nei documenti",
|
||||
"onlySearchForDocTip": "Dopo l'abilitazione, [[ o 【【 per cercare riferimenti di blocchi solo nei nomi dei documenti",
|
||||
"pasteURLAutoConvert": "Converti automaticamente URL incollato in link",
|
||||
"pasteURLAutoConvertTip": "Quando abilitato, incollando un URL che inizia con http:// o https:// verrà automaticamente convertito in un link cliccabile",
|
||||
"ocrResult": "Risultato OCR",
|
||||
"reOCR": "Ripeti OCR",
|
||||
"continueReview1": "Continua la revisione",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "比較方向の切り替え",
|
||||
"onlySearchForDoc": "ドキュメント名のみを検索",
|
||||
"onlySearchForDocTip": "<code class='fn__code'>[[</code> を使用したブロック参照の検索でドキュメント名のみを検索します",
|
||||
"pasteURLAutoConvert": "貼り付けたURLを自動でリンクに変換",
|
||||
"pasteURLAutoConvertTip": "有効にすると、http:// または https:// で始まるURLを貼り付けた際に自動的にクリック可能なリンクに変換します",
|
||||
"ocrResult": "OCR 結果のテキスト",
|
||||
"reOCR": "再 OCR",
|
||||
"continueReview1": "復習を続ける",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "비교 방향 전환",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> 문서만 검색",
|
||||
"onlySearchForDocTip": "활성화하면 [[ 또는 【【 를 사용하여 블록 참조를 검색할 때 문서 이름만 검색합니다",
|
||||
"pasteURLAutoConvert": "붙여넣은 URL을 자동으로 링크로 변환",
|
||||
"pasteURLAutoConvertTip": "활성화하면 http:// 또는 https:// 로 시작하는 URL을 붙여넣을 때 자동으로 클릭 가능한 링크로 변환합니다",
|
||||
"ocrResult": "OCR 결과 텍스트",
|
||||
"reOCR": "다시 OCR",
|
||||
"continueReview1": "복습 계속",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Zmień kierunek porównania",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> tylko szukaj dokumentów",
|
||||
"onlySearchForDocTip": "Po włączeniu, [[ lub 【【 wyszuka odniesienia bloków tylko w nazwach dokumentów",
|
||||
"pasteURLAutoConvert": "Automatycznie konwertuj wklejany URL na link",
|
||||
"pasteURLAutoConvertTip": "Po włączeniu, wklejenie URL zaczynającego się od http:// lub https:// automatycznie przekształci go w klikalny link",
|
||||
"ocrResult": "Tekst wyniku OCR",
|
||||
"reOCR": "Re OCR",
|
||||
"continueReview1": "Kontynuuj przegląd",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Alternar direção de comparação",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> apenas pesquisa documentos",
|
||||
"onlySearchForDocTip": "Quando ativado, [[ ou 【【 para pesquisar referências de bloco apenas em nomes de documentos",
|
||||
"pasteURLAutoConvert": "Converter automaticamente URL colada em link",
|
||||
"pasteURLAutoConvertTip": "Quando ativado, colar uma URL que começa com http:// ou https:// a converte automaticamente em um link clicável",
|
||||
"ocrResult": "Texto do resultado OCR",
|
||||
"reOCR": "Refazer OCR",
|
||||
"continueReview1": "Continuar Revisão",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Переключить направление сравнения",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> только искать документы",
|
||||
"onlySearchForDocTip": "После включения [[ или 【【 искать ссылки на блоки только в названиях документов",
|
||||
"pasteURLAutoConvert": "Автоматически преобразовывать вставленный URL в ссылку",
|
||||
"pasteURLAutoConvertTip": "При включении вставка URL, начинающегося с http:// или https://, автоматически преобразует его в кликабельную ссылку",
|
||||
"ocrResult": "Результаты OCR текста",
|
||||
"reOCR": "Повторить OCR",
|
||||
"continueReview1": "Продолжить просмотр",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Prepnúť smer porovnávania",
|
||||
"onlySearchForDoc": "[[ hľadá iba v dokumentoch",
|
||||
"onlySearchForDocTip": "Ak je povolené, hľadanie cez [[ sa obmedzí len na názvy dokumentov",
|
||||
"pasteURLAutoConvert": "Automaticky previesť vloženú URL na odkaz",
|
||||
"pasteURLAutoConvertTip": "Ak je povolené, vloženie URL začínajúcej na http:// alebo https:// ju automaticky prevedie na klikateľný odkaz",
|
||||
"ocrResult": "Text výsledku OCR",
|
||||
"reOCR": "Spustiť OCR znova",
|
||||
"continueReview1": "Pokračovať v opakovaní",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "Karşılaştırma yönünü değiştir",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> sadece belgelerde ara",
|
||||
"onlySearchForDocTip": "Etkinleştirildiğinde [[ veya 【【 yalnızca belge adlarında blok referanslarını arar",
|
||||
"pasteURLAutoConvert": "Yapıştırılan URL'yi otomatik olarak bağlantıya dönüştür",
|
||||
"pasteURLAutoConvertTip": "Etkinleştirildiğinde, http:// veya https:// ile başlayan bir URL yapıştırıldığında otomatik olarak tıklanabilir bir bağlantıya dönüştürülür",
|
||||
"ocrResult": "OCR sonuç metni",
|
||||
"reOCR": "OCR’yi yeniden çalıştır",
|
||||
"continueReview1": "Gözden geçirmeye devam et",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "交換對比方向",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> 僅搜索文檔",
|
||||
"onlySearchForDocTip": "啟用後使用 [[ 或 【【 搜索塊引用時將只在文檔名中搜索",
|
||||
"pasteURLAutoConvert": "貼上網址時自動轉為連結",
|
||||
"pasteURLAutoConvertTip": "啟用後貼上 http:// 或 https:// 開頭的網址時將自動轉為可點擊的連結",
|
||||
"ocrResult": "OCR 結果文字",
|
||||
"reOCR": "重新 OCR",
|
||||
"continueReview1": "繼續複習",
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@
|
|||
"switchDirect": "交换对比方向",
|
||||
"onlySearchForDoc": "<code class='fn__code'>[[</code> 仅搜索文档",
|
||||
"onlySearchForDocTip": "启用后使用 [[ 或 【【 搜索块引用时将只在文档名中搜索",
|
||||
"pasteURLAutoConvert": "粘贴网址时自动转为链接",
|
||||
"pasteURLAutoConvertTip": "启用后粘贴 http:// 或 https:// 开头的网址时将自动转为可点击的链接",
|
||||
"ocrResult": "OCR 结果文本",
|
||||
"reOCR": "重新 OCR",
|
||||
"continueReview1": "继续复习",
|
||||
|
|
|
|||
|
|
@ -125,6 +125,14 @@ export const editor = {
|
|||
<span class="fn__space"></span>
|
||||
<input class="b3-switch fn__flex-center" id="onlySearchForDoc" type="checkbox"${window.siyuan.config.editor.onlySearchForDoc ? " checked" : ""}/>
|
||||
</label>
|
||||
<label class="fn__flex b3-label">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.pasteURLAutoConvert}
|
||||
<div class="b3-label__text">${window.siyuan.languages.pasteURLAutoConvertTip}</div>
|
||||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<input class="b3-switch fn__flex-center" id="pasteURLAutoConvert" type="checkbox"${window.siyuan.config.editor.pasteURLAutoConvert ? " checked" : ""}/>
|
||||
</label>
|
||||
<label class="fn__flex b3-label">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.md31}
|
||||
|
|
@ -524,6 +532,7 @@ export const editor = {
|
|||
spellcheckLanguages: window.siyuan.config.editor.spellcheckLanguages,
|
||||
/// #endif
|
||||
onlySearchForDoc: (editor.element.querySelector("#onlySearchForDoc") as HTMLInputElement).checked,
|
||||
pasteURLAutoConvert: (editor.element.querySelector("#pasteURLAutoConvert") as HTMLInputElement).checked,
|
||||
floatWindowMode,
|
||||
floatWindowDelay,
|
||||
plantUMLServePath: (editor.element.querySelector("#plantUMLServePath") as HTMLInputElement).value,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ export const initConfigSearch = (element: HTMLElement, app: App) => {
|
|||
"editorMarkdownInlineTag", "editorMarkdownInlineTagTip", "editorMarkdownInlineMath", "editorMarkdownInlineMathTip",
|
||||
"editorMarkdownInlineStrikethrough", "editorMarkdownInlineStrikethroughTip", "editorMarkdownInlineMark", "editorMarkdownInlineMarkTip",
|
||||
"allowHTMLBLockScript", "allowHTMLBLockScriptTip", "floatWindowDelay", "floatWindowDelayTip",
|
||||
"backlinkContainChildren", "backlinkContainChildrenTip", "allowSVGScript", "allowSVGScriptTip"
|
||||
"backlinkContainChildren", "backlinkContainChildrenTip", "allowSVGScript", "allowSVGScriptTip",
|
||||
"pasteURLAutoConvert", "pasteURLAutoConvertTip"
|
||||
]),
|
||||
|
||||
// 文档树
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ const setEditor = (modelMainElement: Element) => {
|
|||
window.siyuan.config.editor.listItemDotNumberClickFocus = (modelMainElement.querySelector("#listItemDotNumberClickFocus") as HTMLInputElement).checked;
|
||||
window.siyuan.config.editor.spellcheck = (modelMainElement.querySelector("#spellcheck") as HTMLInputElement).checked;
|
||||
window.siyuan.config.editor.onlySearchForDoc = (modelMainElement.querySelector("#onlySearchForDoc") as HTMLInputElement).checked;
|
||||
window.siyuan.config.editor.pasteURLAutoConvert = (modelMainElement.querySelector("#pasteURLAutoConvert") as HTMLInputElement).checked;
|
||||
window.siyuan.config.editor.plantUMLServePath = (modelMainElement.querySelector("#plantUMLServePath") as HTMLInputElement).value;
|
||||
window.siyuan.config.editor.katexMacros = (modelMainElement.querySelector("#katexMacros") as HTMLTextAreaElement).value;
|
||||
window.siyuan.config.editor.codeLineWrap = (modelMainElement.querySelector("#codeLineWrap") as HTMLInputElement).checked;
|
||||
|
|
@ -157,7 +158,15 @@ export const initEditor = () => {
|
|||
<div class="b3-label__text">${window.siyuan.languages.onlySearchForDocTip}</div>
|
||||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<input class="b3-switch fn__flex-center" id="onlySearchForDoc" type="checkbox"${window.siyuan.config.editor.spellcheck ? " checked" : ""}/>
|
||||
<input class="b3-switch fn__flex-center" id="onlySearchForDoc" type="checkbox"${window.siyuan.config.editor.onlySearchForDoc ? " checked" : ""}/>
|
||||
</label>
|
||||
<label class="fn__flex b3-label">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.pasteURLAutoConvert}
|
||||
<div class="b3-label__text">${window.siyuan.languages.pasteURLAutoConvertTip}</div>
|
||||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<input class="b3-switch fn__flex-center" id="pasteURLAutoConvert" type="checkbox"${window.siyuan.config.editor.pasteURLAutoConvert ? " checked" : ""}/>
|
||||
</label>
|
||||
<label class="fn__flex b3-label">
|
||||
<div class="fn__flex-1">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {linkMenu} from "../../menus/protyle";
|
|||
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
|
||||
import {readClipboard} from "../util/compatibility";
|
||||
import {Constants} from "../../constants";
|
||||
import {genLinkText, resolveLinkDest} from "./util";
|
||||
|
||||
export class Link extends ToolbarItem {
|
||||
public element: HTMLElement;
|
||||
|
|
@ -44,7 +45,7 @@ export class Link extends ToolbarItem {
|
|||
}
|
||||
}
|
||||
if (!dataHref) {
|
||||
dataHref = protyle.lute.GetLinkDest(clipObject.textPlain);
|
||||
dataHref = resolveLinkDest(clipObject.textPlain, protyle.lute);
|
||||
}
|
||||
if (!dataHref) {
|
||||
// 360
|
||||
|
|
@ -56,16 +57,9 @@ export class Link extends ToolbarItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
// https://github.com/siyuan-note/siyuan/issues/12867
|
||||
if (!dataHref && clipObject.textPlain.startsWith("assets/")) {
|
||||
dataHref = clipObject.textPlain;
|
||||
}
|
||||
// https://github.com/siyuan-note/siyuan/issues/14704#issuecomment-2867555769 第一点 & https://github.com/siyuan-note/siyuan/issues/6798
|
||||
if (dataHref && !dataText) {
|
||||
dataText = decodeURIComponent(dataHref.replace("https://", "").replace("http://", ""));
|
||||
if (dataHref.length > Constants.SIZE_LINK_TEXT_MAX) {
|
||||
dataText = dataHref.substring(0, Constants.SIZE_LINK_TEXT_MAX) + "...";
|
||||
}
|
||||
dataText = genLinkText(dataHref, true, true);
|
||||
showMenu = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,39 @@ export const toolbarKeyToMenu = (toolbar: Array<string | IMenuItem>) => {
|
|||
return toolbarResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect a URL from text, handling the `assets/` prefix and `GetLinkDest`.
|
||||
* Returns the resolved href, or an empty string if no URL was detected.
|
||||
*/
|
||||
export const resolveLinkDest = (text: string, lute: Lute): string => {
|
||||
if (text.startsWith("assets/")) {
|
||||
return text;
|
||||
}
|
||||
return lute.GetLinkDest(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a display label for a link URL: decode, optionally strip protocol, and truncate.
|
||||
* Shared between Ctrl+K link handler and paste URL auto-convert.
|
||||
* @param stripScheme When true, removes https:// and http:// prefixes (used by Ctrl+K).
|
||||
*/
|
||||
export const genLinkText = (href: string, stripScheme: boolean = true, decodeURI: boolean = false): string => {
|
||||
try {
|
||||
let text = stripScheme
|
||||
? href.replace("https://", "").replace("http://", "")
|
||||
: href;
|
||||
if (decodeURI) {
|
||||
text = decodeURIComponent(text);
|
||||
}
|
||||
if (text.length > Constants.SIZE_LINK_TEXT_MAX) {
|
||||
text = text.substring(0, Constants.SIZE_LINK_TEXT_MAX) + "...";
|
||||
}
|
||||
return text;
|
||||
} catch {
|
||||
return href;
|
||||
}
|
||||
};
|
||||
|
||||
export const copyTextByType = async (ids: string[],
|
||||
type: "ref" | "blockEmbed" | "protocol" | "protocolMd" | "hPath" | "id" | "webURL") => {
|
||||
let text = "";
|
||||
|
|
|
|||
|
|
@ -17,6 +17,33 @@ import {getCalloutInfo, getContenteditableElement} from "../wysiwyg/getBlock";
|
|||
import {clearBlockElement} from "./clear";
|
||||
import {removeZWJ} from "./normalizeText";
|
||||
import {base64ToURL} from "../../util/image";
|
||||
import {resolveLinkDest, genLinkText} from "../toolbar/util";
|
||||
|
||||
const pasteAsLink = (text: string, protyle: IProtyle): boolean => {
|
||||
if (!window.siyuan.config.editor.pasteURLAutoConvert) {
|
||||
return false;
|
||||
}
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed || trimmed.includes("\n")) {
|
||||
// TODO 暂不支持多行文本
|
||||
return false;
|
||||
}
|
||||
const linkDest = resolveLinkDest(trimmed, protyle.lute);
|
||||
if (!linkDest) {
|
||||
return false;
|
||||
}
|
||||
const linkText = genLinkText(linkDest, false);
|
||||
const linkNodes = protyle.toolbar.setInlineMark(protyle, "a", "range", {
|
||||
type: "a",
|
||||
color: linkDest + Constants.ZWSP + linkText
|
||||
});
|
||||
if (linkNodes && linkNodes.length > 0) {
|
||||
const lastNode = linkNodes[linkNodes.length - 1];
|
||||
protyle.toolbar.range.setStartAfter(lastNode);
|
||||
protyle.toolbar.range.collapse(true);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const getTextStar = (blockElement: HTMLElement, contentOnly = false) => {
|
||||
const dataType = blockElement.dataset.type;
|
||||
|
|
@ -418,6 +445,9 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (pasteAsLink(tempElement.textContent, protyle)) {
|
||||
return;
|
||||
}
|
||||
let isBlock = false;
|
||||
tempElement.querySelectorAll("[data-node-id]").forEach((e) => {
|
||||
const newId = Lute.NewNodeID();
|
||||
|
|
@ -584,7 +614,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
|
|||
return;
|
||||
} else {
|
||||
// https://github.com/siyuan-note/siyuan/issues/8475
|
||||
const linkDest = textPlain.startsWith("assets/") ? textPlain : protyle.lute.GetLinkDest(textPlain);
|
||||
const linkDest = resolveLinkDest(textPlain, protyle.lute);
|
||||
if (linkDest) {
|
||||
protyle.toolbar.setInlineMark(protyle, "a", "range", {
|
||||
type: "a",
|
||||
|
|
@ -594,6 +624,10 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
|
|||
}
|
||||
}
|
||||
}
|
||||
// Auto-convert pasted URL to link format https://github.com/siyuan-note/siyuan/issues/17337
|
||||
if (pasteAsLink(textPlain, protyle)) {
|
||||
return;
|
||||
}
|
||||
let textPlainDom = protyle.lute.Md2BlockDOM(textPlain);
|
||||
if (textPlainDom && textPlainDom.indexOf("data:image/") > -1) {
|
||||
const tempElement = document.createElement("template");
|
||||
|
|
|
|||
4
app/src/types/config.d.ts
vendored
4
app/src/types/config.d.ts
vendored
|
|
@ -495,6 +495,10 @@ declare namespace Config {
|
|||
* PlantUML rendering service address
|
||||
*/
|
||||
plantUMLServePath: string;
|
||||
/**
|
||||
* Whether to auto-convert pasted URLs to links
|
||||
*/
|
||||
pasteURLAutoConvert: boolean;
|
||||
/**
|
||||
* Whether to enable read-only mode
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ type Editor struct {
|
|||
BacklinkSort *int `json:"backlinkSort"` // 反向链接排序方式
|
||||
BackmentionSort *int `json:"backmentionSort"` // 反链提及排序方式
|
||||
HeadingEmbedMode int `json:"headingEmbedMode"` // 标题嵌入块模式,0:显示标题与下方的块,1:仅显示标题,2:仅显示标题下方的块
|
||||
PasteURLAutoConvert bool `json:"pasteURLAutoConvert"` // 粘贴网址时自动转为链接
|
||||
Markdown *util.Markdown `json:"markdown"` // Markdown 配置
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +101,7 @@ func NewEditor() *Editor {
|
|||
BacklinkSort: func() *int { v := util.SortModeUpdatedDESC; return &v }(),
|
||||
BackmentionSort: func() *int { v := util.SortModeUpdatedDESC; return &v }(),
|
||||
HeadingEmbedMode: 0,
|
||||
PasteURLAutoConvert: false,
|
||||
Markdown: util.MarkdownSettings,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue