Merge branch 'dev' into dev-font-1

This commit is contained in:
Jeffrey Chen 2024-12-01 03:36:07 +08:00 committed by GitHub
commit 4bf6460cef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
141 changed files with 1483 additions and 578 deletions

22
API.md
View file

@ -416,6 +416,28 @@ Rename a document by `id`:
"data": null
}
```
Remove a document by `id`:
* `/api/filetree/removeDocByID`
* Parameters
```json
{
"id": "20210902210113-0avi12f"
}
```
* `id`: Document ID
* Return value
```json
{
"code": 0,
"msg": "",
"data": null
}
```
### Move documents

View file

@ -416,6 +416,28 @@
"data": null
}
```
通过 `id` 删除文档:
* `/api/filetree/removeDocByID`
* 参数
```json
{
"id": "20210902210113-0avi12f"
}
```
* `id`:文档 ID
* 返回值
```json
{
"code": 0,
"msg": "",
"data": null
}
```
### 移动文档

View file

@ -1,4 +1,6 @@
{
"empty": "Leer",
"newRowInRelation": "Erstellen Sie einen neuen Eintrag in ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Schlüsselinhalt",
"addDesc": "Beschreibung hinzufügen",
"dataRepoAutoPurgeIndexRetentionDays": "Daten-Snapshot-Aufbewahrungstage",

View file

@ -1,4 +1,6 @@
{
"empty": "Empty",
"newRowInRelation": "Create a new entry in ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Key content",
"addDesc": "Add description",
"dataRepoAutoPurgeIndexRetentionDays": "Data snapshot retention days",

View file

@ -1,4 +1,6 @@
{
"empty": "Vacío",
"newRowInRelation": "Crear una nueva entrada en ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Contenido de la clave",
"addDesc": "Agregar descripción",
"dataRepoAutoPurgeIndexRetentionDays": "Días de retención de instantáneas de datos",

View file

@ -1,4 +1,5 @@
{
"newRowInRelation": "Créer une nouvelle entrée dans ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Contenu de la clé",
"addDesc": "Ajouter une description",
"dataRepoAutoPurgeIndexRetentionDays": "Jours de rétention des instantanés de données",
@ -601,7 +602,7 @@
"querySyntax": "Syntaxe de la requête",
"rollback": "Rollback",
"custom": "Personnalisé",
"feedback": "Commentaires",
"feedback": "Retour d'information",
"inbox": "Boîte de réception",
"turnToStatic": "Texte d'ancrage statique",
"turnToDynamic": "Texte d'ancrage dynamique",

View file

@ -1,4 +1,6 @@
{
"empty": "ריק",
"newRowInRelation": "צור ערך חדש ב-${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "תוכן המפתח",
"addDesc": "הוסף תיאור",
"dataRepoAutoPurgeIndexRetentionDays": "ימי שמירת תמונות נתונים",

View file

@ -1,4 +1,6 @@
{
"empty": "Vuoto",
"newRowInRelation": "Crea una nuova voce in ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Contenuto della chiave",
"addDesc": "Aggiungi descrizione",
"dataRepoAutoPurgeIndexRetentionDays": "Giorni di conservazione degli snapshot dei dati",

View file

@ -1,4 +1,6 @@
{
"empty": "空白",
"newRowInRelation": "${x} に新しい項目を作成 <b class='ft__on-surface'>${y}</b>",
"keyContent": "キーコンテンツ",
"addDesc": "説明を追加",
"dataRepoAutoPurgeIndexRetentionDays": "データスナップショットの保持日数",

View file

@ -1,4 +1,6 @@
{
"empty": "Pusty",
"newRowInRelation": "Utwórz nowy wpis w ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Zawartość klucza",
"addDesc": "Dodaj opis",
"dataRepoAutoPurgeIndexRetentionDays": "Dni przechowywania migawek danych",

View file

@ -1,4 +1,6 @@
{
"empty": "Пусто",
"newRowInRelation": "Создать новую запись в ${x} <b class='ft__on-surface'>${y}</b>",
"keyContent": "Содержимое ключа",
"addDesc": "Добавить описание",
"dataRepoAutoPurgeIndexRetentionDays": "Срок хранения снимков данных",

View file

@ -1,4 +1,6 @@
{
"empty": "空白",
"newRowInRelation": "在 ${x} 中新建條目 <b class='ft__on-surface'>${y}</b>",
"keyContent": "主鍵內容",
"addDesc": "添加描述",
"dataRepoAutoPurgeIndexRetentionDays": "數據快照保留天數",
@ -601,7 +603,7 @@
"querySyntax": "查詢語法",
"rollback": "回復",
"custom": "自定義",
"feedback": "反饋",
"feedback": "問題反饋",
"inbox": "收件箱",
"turnToStatic": "靜態錨文字",
"turnToDynamic": "動態錨文字",

View file

@ -1,4 +1,6 @@
{
"empty": "空白",
"newRowInRelation": "在 ${x} 中新建条目 <b class='ft__on-surface'>${y}</b>",
"keyContent": "主键内容",
"addDesc": "添加描述",
"dataRepoAutoPurgeIndexRetentionDays": "数据快照保留天数",
@ -601,7 +603,7 @@
"querySyntax": "查询语法",
"rollback": "回滚",
"custom": "自定义",
"feedback": "反馈",
"feedback": "问题反馈",
"inbox": "收集箱",
"turnToStatic": "静态锚文本",
"turnToDynamic": "动态锚文本",

View file

@ -27,7 +27,7 @@
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Segoe UI", "Tahoma", "Arial", "Other Emojis", sans-serif;
--b3-font-family-protyle: var(--b3-font-family);
--b3-font-family-code: "Number Glyphs Of Custom Font", "Number Glyphs", "Segoe Good Emoji", "Other SiYuan Emojis", "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
--b3-font-family-graph: mononoki;
--b3-font-family-graph: arial;
--b3-font-family-emoji: "Segoe Good Emoji", "Other Emojis";
--b3-font-family-math: KaTeX_Math;
--b3-font-size: 14px;
@ -207,7 +207,7 @@
}
/* https://github.com/siyuan-note/siyuan/issues/6440 */
.protyle-action--order:after {
.protyle-action--order::after {
mix-blend-mode: multiply;
}

View file

@ -25,7 +25,7 @@
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Segoe UI", "Tahoma", "Arial", "Other Emojis", sans-serif;
--b3-font-family-protyle: var(--b3-font-family);
--b3-font-family-code: "Number Glyphs Of Custom Font", "Number Glyphs", "Segoe Good Emoji", "Other SiYuan Emojis", "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
--b3-font-family-graph: mononoki;
--b3-font-family-graph: arial;
--b3-font-family-emoji: "Segoe Good Emoji", "Other Emojis";
--b3-font-family-math: KaTeX_Math;
--b3-font-size: 14px;
@ -205,7 +205,7 @@
}
/* https://github.com/siyuan-note/siyuan/issues/6440 */
.protyle-action--order:after {
.protyle-action--order::after {
mix-blend-mode: screen;
}

View file

@ -8,9 +8,55 @@
"title": "Please Start Here",
"title-img": "background-color:#556;background-image: linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a);background-size:80px 140px;background-position: 0 0, 0 0, 40px 70px, 40px 70px, 0 0, 40px 70px;",
"type": "doc",
"updated": "20241018102340"
"updated": "20241125224626"
},
"Children": [
{
"ID": "20241125224615-dwfqru1",
"Type": "NodeBlockquote",
"Properties": {
"id": "20241125224615-dwfqru1",
"updated": "20241125224626"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20241125224615-z2fevdf",
"Type": "NodeParagraph",
"Properties": {
"id": "20241125224615-z2fevdf",
"updated": "20241125224626"
},
"Children": [
{
"Type": "NodeText",
"Data": "When you close SiYuan Notes, the User Guide will be automatically closed. You can click "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "Main Menu"
},
{
"Type": "NodeText",
"Data": " - "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "User Guide"
},
{
"Type": "NodeText",
"Data": " to view it again"
}
]
}
]
},
{
"ID": "20210528120135-bznvpp6",
"Type": "NodeSuperBlock",

View file

@ -7,7 +7,7 @@
"id": "20200924100950-9op5xi1",
"title": "Shortcuts",
"type": "doc",
"updated": "20241009230212"
"updated": "20241128113606"
},
"Children": [
{
@ -12329,7 +12329,7 @@
"HeadingLevel": 3,
"Properties": {
"id": "20220619002135-5dfw1yo",
"updated": "20241009230212"
"updated": "20241128113606"
},
"Children": [
{
@ -12349,7 +12349,7 @@
"Properties": {
"colgroup": "||",
"id": "20220619002135-s399g7e",
"updated": "20241009230212"
"updated": "20241128113606"
},
"Children": [
{
@ -12653,7 +12653,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "Move"
"Data": "Generate block ref"
}
]
},
@ -12692,7 +12692,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "Generate block ref"
"Data": "Move"
}
]
},

View file

@ -8,9 +8,55 @@
"title": "请从这里开始",
"title-img": "background-color:#556;background-image: linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a);background-size:80px 140px;background-position: 0 0, 0 0, 40px 70px, 40px 70px, 0 0, 40px 70px;",
"type": "doc",
"updated": "20241018102134"
"updated": "20241125224159"
},
"Children": [
{
"ID": "20241125224159-8zf3bos",
"Type": "NodeBlockquote",
"Properties": {
"id": "20241125224159-8zf3bos",
"updated": "20241125224159"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20241125224159-vcaj2bv",
"Type": "NodeParagraph",
"Properties": {
"id": "20241125224159-vcaj2bv",
"updated": "20241125224159"
},
"Children": [
{
"Type": "NodeText",
"Data": "关闭思源笔记时会自动关闭用户指南,可以点击 "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "主菜单"
},
{
"Type": "NodeText",
"Data": " - "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "用户指南"
},
{
"Type": "NodeText",
"Data": " 再次查看"
}
]
}
]
},
{
"ID": "20210528115012-vst5lwt",
"Type": "NodeSuperBlock",

View file

@ -7,7 +7,7 @@
"id": "20200813004551-gm0pbn1",
"title": "快捷键",
"type": "doc",
"updated": "20241009225803"
"updated": "20241128112739"
},
"Children": [
{
@ -12388,7 +12388,7 @@
"HeadingLevel": 3,
"Properties": {
"id": "20220619001156-26volkp",
"updated": "20241009225803"
"updated": "20241128112739"
},
"Children": [
{
@ -12408,7 +12408,7 @@
"Properties": {
"colgroup": "||",
"id": "20220619001217-e9cwukj",
"updated": "20241009225803"
"updated": "20241128112739"
},
"Children": [
{
@ -12711,7 +12711,7 @@
},
{
"Type": "NodeText",
"Data": "移动"
"Data": "生成块引用"
}
]
},
@ -12762,7 +12762,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "生成块引用"
"Data": "移动"
}
]
},

View file

@ -8,9 +8,55 @@
"title": "請從這裡開始",
"title-img": "background-color:#556;background-image: linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a);background-size:80px 140px;background-position: 0 0, 0 0, 40px 70px, 40px 70px, 0 0, 40px 70px;",
"type": "doc",
"updated": "20241018105300"
"updated": "20241125224503"
},
"Children": [
{
"ID": "20241125224503-8vqkbc9",
"Type": "NodeBlockquote",
"Properties": {
"id": "20241125224503-8vqkbc9",
"updated": "20241125224503"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20241125224503-fqq0875",
"Type": "NodeParagraph",
"Properties": {
"id": "20241125224503-fqq0875",
"updated": "20241125224503"
},
"Children": [
{
"Type": "NodeText",
"Data": "關閉思源筆記時會自動關閉用戶指南,可以點擊 "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "主菜單"
},
{
"Type": "NodeText",
"Data": " - "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "用戶指南"
},
{
"Type": "NodeText",
"Data": " ​再次查看"
}
]
}
]
},
{
"ID": "20211226115745-rorv31l",
"Type": "NodeSuperBlock",

View file

@ -7,7 +7,7 @@
"id": "20211226122549-jktxego",
"title": "快捷鍵",
"type": "doc",
"updated": "20241018105254"
"updated": "20241128113116"
},
"Children": [
{
@ -12564,7 +12564,7 @@
"HeadingLevel": 3,
"Properties": {
"id": "20220619002223-zliquo3",
"updated": "20241009230052"
"updated": "20241128113116"
},
"Children": [
{
@ -12584,7 +12584,7 @@
"Properties": {
"colgroup": "||",
"id": "20220619002223-xwob5s8",
"updated": "20241009230052"
"updated": "20241128113116"
},
"Children": [
{
@ -12896,7 +12896,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "移動"
"Data": "生成塊引用"
}
]
},
@ -12935,7 +12935,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "生成塊引用"
"Data": "移動"
}
]
},

View file

@ -9,9 +9,55 @@
"title": "スタートガイド",
"title-img": "background-color:#556;background-image: linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a),linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a);background-size:80px 140px;background-position: 0 0, 0 0, 40px 70px, 40px 70px, 0 0, 40px 70px;",
"type": "doc",
"updated": "20241018102426"
"updated": "20241125225136"
},
"Children": [
{
"ID": "20241125224702-5a9o34q",
"Type": "NodeBlockquote",
"Properties": {
"id": "20241125224702-5a9o34q",
"updated": "20241125225136"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20241125225100-s0akx3f",
"Type": "NodeParagraph",
"Properties": {
"id": "20241125225100-s0akx3f",
"updated": "20241125225136"
},
"Children": [
{
"Type": "NodeText",
"Data": "SiYuan を閉じると、ユーザーガイドは自動的に閉じられます。"
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "メインメニュー"
},
{
"Type": "NodeText",
"Data": " - "
},
{
"Type": "NodeTextMark",
"TextMarkType": "kbd",
"TextMarkTextContent": "ユーザーガイド"
},
{
"Type": "NodeText",
"Data": " ​をクリックすると、再度表示できます"
}
]
}
]
},
{
"ID": "20240530101000-x3xk6o7",
"Type": "NodeSuperBlock",

View file

@ -9,7 +9,7 @@
"id": "20240530101000-xsbxokr",
"title": "ショートカット",
"type": "doc",
"updated": "20241009230427"
"updated": "20241128113339"
},
"Children": [
{
@ -12781,7 +12781,7 @@
"Properties": {
"ID": "20240530101000-xjv6i4l",
"id": "20240530101000-mifghto",
"updated": "20241009230427"
"updated": "20241128113339"
},
"Children": [
{
@ -12811,7 +12811,7 @@
"Properties": {
"colgroup": "||",
"id": "20240530101000-4iuhg30",
"updated": "20241009230427"
"updated": "20241128113339"
},
"Children": [
{
@ -13134,7 +13134,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "ブロックを移動"
"Data": "ブロック参照を生成"
}
]
},
@ -13173,7 +13173,7 @@
"Children": [
{
"Type": "NodeText",
"Data": "ブロック参照を生成"
"Data": "ブロックを移動"
}
]
},

View file

@ -329,8 +329,8 @@ html {
opacity: .38;
}
.dragover__top:after,
.dragover__bottom:after {
.dragover__top::after,
.dragover__bottom::after {
content: "";
width: var(--file-toggle-width);
height: 4px;
@ -341,7 +341,7 @@ html {
z-index: 1;
}
.dragover__top:after {
.dragover__top::after {
top: -3px;
bottom: auto;
}

View file

@ -29,7 +29,7 @@
background: var(--b3-border-color);
border-radius: var(--b3-border-radius);
&:after {
&::after {
content: " ";
border-radius: var(--b3-border-radius);
position: absolute;
@ -125,14 +125,28 @@
position: relative;
font-size: 87.5%;
&.dragover__top,
&.dragover__bottom {
border-bottom-color: var(--b3-theme-primary-lighter);
box-shadow: none !important;
}
&.dragover__top::after,
&.dragover__bottom::after {
content: '';
position: absolute;
left: 0;
right: 0;
height: 4px;
background-color: var(--b3-theme-primary-lighter);
z-index: 3;
}
&.dragover__top {
z-index: 3;
box-shadow: 0 -3px 0 var(--b3-theme-primary-lighter), inset 0 2px 0 var(--b3-theme-primary-lighter) !important;
&.dragover__top::after {
top: -2.5px;
}
&.dragover__bottom::after {
bottom: -2.5px;
}
&:hover [data-type="block-more"] {
@ -179,7 +193,7 @@
.av__calc {
display: flex;
align-items: baseline;
align-items: center;
padding: 5px;
border-right: 1px;
flex-direction: row-reverse;
@ -188,6 +202,7 @@
overflow: hidden;
font-size: 75%;
white-space: nowrap;
line-height: 1.625em;
cursor: pointer;
&[data-dtype="lineNumber"] {
@ -485,7 +500,6 @@
line-height: 20px;
padding: 0 4px;
font-size: 12px;
font-family: var(--b3-font-family-emoji);
align-self: center;
opacity: 1;
}

View file

@ -2,15 +2,20 @@
&__avvalue {
cursor: pointer;
transition: var(--b3-transition);
transition: var(--b3-background-transition);
border-radius: var(--b3-border-radius);
padding: 4px 8px;
line-height: 26px;
min-height: 26px;
flex-wrap: wrap;
&:hover {
background-color: var(--b3-theme-background);
&:not(.custom-attr__avvalue--readonly):hover,
&--active {
background-color: var(--b3-theme-surface-light);
}
&--readonly {
cursor: default;
}
.av__checkbox {
@ -40,14 +45,20 @@
.block__logo:not(.popover__block) {
width: 160px;
color: var(--b3-theme-on-surface);
border-radius: var(--b3-border-radius);
transition: var(--b3-background-transition);
min-height: 34px;
align-self: flex-start;
margin-top: 5px;
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
&:hover {
background-color: var(--b3-theme-surface-light);
}
}
.block__icons {
@ -65,16 +76,35 @@
background-color: transparent;
}
}
[placeholder]:empty::after {
color: var(--b3-empty-color);
content: attr(placeholder);
}
}
.b3-button[data-type="addColumn"] {
margin-left: 28px;
svg {
width: 16px;
height: 16px;
margin-right: 8px;
}
&:hover {
background-color: var(--b3-theme-surface-light);
}
}
.b3-text-field--text {
transition: var(--b3-transition);
transition: var(--b3-background-transition);
min-height: 34px;
background-color: transparent;
padding: 7px 8px;
&:hover {
background-color: var(--b3-theme-background);
background-color: var(--b3-theme-surface-light);
}
}
@ -86,7 +116,7 @@
max-height: 24px;
}
.dragover__top.av__row {
box-shadow: 0 -2px 0 var(--b3-theme-primary-lighter), inset 0 2px 0 var(--b3-theme-primary-lighter) !important;
.av__row.dragover__top::after {
top: -1.5px;
}
}

View file

@ -1,5 +1,16 @@
.dragover {
background-color: var(--b3-theme-primary-lightest) !important;
&::after {
background-color: var(--b3-theme-primary-lightest);
position: absolute;
width: 100%;
height: 100%;
content: " ";
left: 0;
top: 0;
z-index: 3;
pointer-events: none;
}
// 需要 !important否则拖拽到闪卡无效果
&__top {

View file

@ -7,7 +7,7 @@
position: relative;
z-index: 1;
[data-node-id].li[fold="1"] > .protyle-action:after {
[data-node-id].li[fold="1"] > .protyle-action::after {
background-color: transparent;
border: 1px solid var(--b3-list-hover);
box-sizing: border-box;

View file

@ -1,4 +1,9 @@
.history {
&__action {
overflow: auto;
border-bottom: 1px solid var(--b3-border-color);
}
&__text {
background-color: var(--b3-theme-background);
padding: 16px;

View file

@ -2,7 +2,7 @@
overflow-y: hidden; // https://github.com/siyuan-note/siyuan/issues/6706
&__wnd--active .layout-tab-bar .item--focus {
&:after {
&::after {
background-color: var(--b3-theme-primary);
}
@ -111,11 +111,11 @@
position: relative;
z-index: 4; // 需大于 #sidebarContainer https://github.com/siyuan-note/siyuan/issues/11759
&:hover:after {
&:hover::after {
background-color: var(--b3-scroll-color);
}
&:after {
&::after {
content: "";
width: 100%;
height: .5px;
@ -133,7 +133,7 @@
margin: 0 -6px 0 0;
height: auto;
&:after {
&::after {
top: 0;
width: .5px;
left: 0;
@ -226,7 +226,7 @@
max-width: none;
flex: 1;
&.item--focus:after {
&.item--focus::after {
background-color: var(--b3-theme-primary);
}
}
@ -268,7 +268,7 @@
}
}
&--focus:after {
&--focus::after {
content: "";
width: 100%;
height: 3px;
@ -384,12 +384,12 @@
padding: 0;
.dock__item {
&[data-index="0"]:after {
&[data-index="0"]::after {
top: -32px;
bottom: auto;
}
&[data-index="1"]:after {
&[data-index="1"]::after {
bottom: 100%;
}
}

View file

@ -24,7 +24,7 @@
margin: 0 -6px 0 0;
height: auto;
&:after {
&::after {
width: .5px;
height: 100%;
}
@ -104,7 +104,7 @@
position: relative;
z-index: 2;
&:after {
&::after {
content: "";
display: block;
background-color: var(--b3-theme-surface-lighter);
@ -116,7 +116,7 @@
height: .5px;
}
&:hover:after {
&:hover::after {
background-color: var(--b3-scroll-color);
}
}

View file

@ -66,8 +66,7 @@
font-size: 16px;
}
&--text,
&--cancel {
&--text {
color: var(--b3-theme-primary);
background-color: transparent;
@ -85,6 +84,18 @@
&--cancel {
color: var(--b3-theme-on-surface);
background-color: transparent;
&:hover,
&:focus {
background-color: var(--b3-list-hover);
box-shadow: none;
}
&:active {
background-color: var(--b3-list-icon-hover);
box-shadow: none;
}
}
&--outline {

View file

@ -54,6 +54,7 @@
}
&__header {
cursor: default;
padding: 9px 24px;
line-height: 24px;
font-size: 16px;

View file

@ -8,7 +8,7 @@
border-radius: var(--b3-border-radius);
&:hover:not(.b3-list-item--focus):not(.dragover):not(.dragover__top):not(.dragover__bottom),
&--focus:not(.dragover) {
&--focus:not(.dragover):not(.dragover__top):not(.dragover__bottom) {
background-color: var(--b3-list-hover);
}
}
@ -27,7 +27,7 @@
position: relative;
}
.b3-list__panel:before {
.b3-list__panel::before {
content: "";
height: 100%;
top: 0;

View file

@ -41,7 +41,7 @@
&--error .b3-snackbar__content {
padding-left: 47px;
&:after {
&::after {
content: "";
position: absolute;
left: 16px;

View file

@ -24,7 +24,7 @@
align-self: center;
}
&:after {
&::after {
width: 8px;
height: 8px;
border-radius: 50%;
@ -40,7 +40,7 @@
transition: left 80ms linear, background-color 80ms linear, width 80ms linear, height 80ms linear;
}
&:before {
&::before {
z-index: 2;
content: "";
left: 7px;
@ -59,28 +59,18 @@
background-color: var(--b3-switch-checked-background);
border-color: transparent;
&:after {
&::after {
background-color: var(--b3-switch-checked);
height: 12px;
width: 12px;
}
&:before,
&:after {
&::before,
&::after {
left: 17px;
}
&:hover:not(:disabled) {
&:after {
background-color: var(--b3-switch-checked-hover);
}
&:before {
background-color: var(--b3-switch-checked-hover2);
}
}
&:active:not(:disabled):after {
&:active:not(:disabled)::after {
height: 14px;
width: 14px;
}
@ -91,12 +81,24 @@
cursor: auto;
}
&:active:not(:disabled):after {
&:active:not(:disabled)::after {
height: 10px;
width: 10px;
}
}
&:hover:not(:disabled):before {
display: inline-block;
label:hover .b3-switch:not(:disabled)::before,
.b3-switch:hover:not(:disabled)::before {
display: inline-block;
}
label:hover .b3-switch:checked:not(:disabled),
.b3-switch:checked:hover:not(:disabled) {
&::after {
background-color: var(--b3-switch-checked-hover);
}
&::before {
background-color: var(--b3-switch-checked-hover2);
}
}

View file

@ -197,8 +197,8 @@
}
@media screen and (max-width: 520px) {
.b3-tooltips:before,
.b3-tooltips:after {
.b3-tooltips::before,
.b3-tooltips::after {
content: none;
}
}

View file

@ -169,7 +169,7 @@
blockquote,
.bq {
&:before {
&::before {
content: '';
background-color: var(--b3-theme-surface-lighter);
width: .25em;
@ -391,7 +391,7 @@
display: flex;
align-items: baseline; // https://ld246.com/article/1645933216334
&:before {
&::before {
content: "";
flex: 1;
}
@ -484,17 +484,25 @@
position: relative;
display: inline-block;
min-width: 22px;
&[style^=width] img {
width: 100%;
}
}
.protyle-action__title {
width: 100%;
display: block;
display: flex;
font-size: 85%;
color: var(--b3-theme-on-surface);
word-break: break-word;
white-space: break-spaces;
line-height: normal;
padding: 4px 0;
& > span {
flex-grow: 1;
width: 0;
}
}
}

View file

@ -234,7 +234,7 @@
cursor: ew-resize;
right: -6px;
&:after {
&::after {
content: "";
width: 1px;
height: 100%;
@ -244,7 +244,7 @@
left: 3px;
}
&:hover:after {
&:hover::after {
background-color: var(--b3-scroll-color);
}
}

View file

@ -390,7 +390,7 @@
padding: 0 4px 0 2px;
white-space: break-spaces;
&:empty:after {
&:empty::after {
content: attr(data-tip);
color: var(--b3-theme-on-surface-light);
cursor: text;
@ -420,11 +420,11 @@ table[contenteditable="true"] + .protyle-action__table {
cursor: col-resize;
z-index: 2;
&:hover:after {
&:hover::after {
background-color: var(--b3-theme-primary-light);
}
&:after {
&::after {
top: 0;
width: 2px;
left: 2px;

View file

@ -5,7 +5,7 @@
user-select: auto;
overflow-x: clip;
&--empty:empty:before {
&--empty:empty::before {
color: var(--b3-empty-color);
content: attr(placeholder);
}
@ -18,6 +18,16 @@
outline: none;
}
&::highlight(search-mark) {
background-color: var(--b3-protyle-inline-mark-background);
color: var(--b3-protyle-inline-mark-color);
}
&::highlight(search-mark-hl) {
background-color: var(--b3-theme-primary-lighter);
box-shadow: 0 0 0 .5px var(--b3-theme-on-background);
}
[data-node-id] {
position: relative;
@ -43,7 +53,7 @@
position: relative;
height: 26px;
&:after {
&::after {
position: absolute;
content: " ";
height: 1px;
@ -55,18 +65,6 @@
}
}
.bq {
.dragover {
&__top:not(.av__row) {
box-shadow: 0 -3px 0 var(--b3-theme-primary-lighter), inset 0 1px 0 var(--b3-theme-primary-lighter) !important;
}
&__bottom:not(.av__row) {
box-shadow: 0 3px 0 var(--b3-theme-primary-lighter), inset 0 -1px 0 var(--b3-theme-primary-lighter) !important;
}
}
}
&.list {
padding: 0;
display: flex;
@ -86,14 +84,14 @@
display: flex;
flex-direction: column;
&:before {
&::before {
content: "";
position: absolute;
border-left: .5px solid var(--b3-theme-background-light);
left: 17px;
}
&:hover:before {
&:hover::before {
border-left-color: var(--b3-scroll-color);
}
@ -111,11 +109,11 @@
}
&[fold="1"] {
&:before {
&::before {
content: none;
}
& > .protyle-action:after {
& > .protyle-action::after {
background-color: var(--b3-list-hover);
}
@ -147,7 +145,7 @@
padding-bottom: 0;
}
&:after {
&::after {
content: "";
position: absolute;
border-radius: 50%;
@ -163,7 +161,7 @@
position: relative;
}
&--order:after {
&--order::after {
border-radius: var(--b3-border-radius);
}
}
@ -177,11 +175,11 @@
display: flex;
flex-wrap: wrap;
justify-content: space-between;
column-gap: 1.5em;
& > div {
flex: 1;
flex: 1 0 10%;
box-sizing: border-box;
margin-right: 24px;
min-width: 1px;
&:nth-last-child(2),
@ -334,7 +332,7 @@
filter: brightness(.68);
}
&--drag > span:after {
&--drag > span::after {
content: "";
position: absolute;
top: 0;
@ -363,8 +361,8 @@
box-shadow: 0 0 1px 1px var(--b3-theme-on-background);
}
&:before,
&:after {
&::before,
&::after {
position: absolute;
width: 4px;
content: "";
@ -372,7 +370,7 @@
left: -4px;
}
&:after {
&::after {
left: 4px;
width: 8px
}
@ -409,7 +407,7 @@
}
&--drag {
.iframe-content:after {
.iframe-content::after {
content: "";
position: absolute;
top: 0;
@ -433,7 +431,7 @@
box-shadow: 0 0 1px 1px var(--b3-theme-on-surface);
box-sizing: border-box;
&:after {
&::after {
content: "";
background-color: var(--b3-theme-surface);
width: 32px;
@ -449,7 +447,7 @@
}
&:hover,
&:hover:after {
&:hover::after {
background-color: var(--b3-theme-background);
box-shadow: 0 0 1px 1px var(--b3-theme-on-background);
}
@ -459,17 +457,10 @@
&--select,
&--hl {
&:after {
background-color: var(--b3-theme-primary-lightest);
position: absolute;
width: 100%;
height: 100%;
content: " ";
left: 0;
top: 0;
@extend .dragover;
&::after {
border-radius: var(--b3-border-radius);
z-index: 3;
pointer-events: none;
}
}
@ -483,11 +474,11 @@
}
.dragover {
&__top:not(.av__row) {
&__top {
box-shadow: 0 -4px 0 0 var(--b3-theme-primary-lighter) !important;
}
&__bottom:not(.av__row) {
&__bottom {
box-shadow: 0 4px 0 0 var(--b3-theme-primary-lighter) !important
}
}
@ -515,7 +506,7 @@
min-height: 26px !important;
}
div[fold="1"][data-type="NodeHeading"]:before {
div[fold="1"][data-type="NodeHeading"]::before {
content: "";
height: 16px !important;
width: 16px;
@ -600,7 +591,7 @@
cursor: pointer;
&:hover {
&:after {
&::after {
background-color: var(--b3-theme-background-light);
}

View file

@ -71,6 +71,11 @@
&__panel {
flex-direction: column;
& > .fn__flex-column {
min-height: auto;
border-radius: var(--b3-border-radius-b);
}
& > .history__side {
height: 40%;
overflow: auto;

View file

@ -337,8 +337,8 @@ export class BlockPanel {
this.element.querySelector(".block__content").addEventListener("scroll", () => {
this.editors.forEach(item => {
hideElements(["gutter"], item.protyle)
})
})
hideElements(["gutter"], item.protyle);
});
});
}
}

View file

@ -66,7 +66,7 @@ export const globalClick = (event: MouseEvent & { target: HTMLElement }) => {
}
const copyElement = hasTopClosestByClassName(event.target, "protyle-action__copy");
if (copyElement) {
let text = copyElement.parentElement.nextElementSibling.textContent.replace("\n", "");
let text = copyElement.parentElement.nextElementSibling.textContent.replace(/\n$/, "");
text = text.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
writeText(text);
showMessage(window.siyuan.languages.copied, 2000);

View file

@ -160,7 +160,7 @@ const filterList = (inputElement: HTMLInputElement, listElement: Element) => {
const elementValue = element.querySelector(".b3-list-item__text").textContent.toLowerCase();
const command = element.dataset.command;
if (inputValue.indexOf(elementValue) > -1 || elementValue.indexOf(inputValue) > -1 ||
inputValue.indexOf(command) > -1 || command.indexOf(inputValue) > -1) {
inputValue.indexOf(command) > -1 || command?.indexOf(inputValue) > -1) {
if (!hasFocus) {
element.classList.add("b3-list-item--focus");
}

View file

@ -99,7 +99,7 @@ export const genCardHTML = (options: {
<div>🔮</div>
${window.siyuan.languages.noDueCard}
</div>
<div class="fn__flex card__action${options.cardsData.cards.length === 0 ? " fn__none" : ""}">
<div class="fn__flex card__action fn__none">
<button class="b3-button b3-button--cancel" disabled="disabled" data-type="-2" style="width: 25%;min-width: 86px;display: flex">
<svg><use xlink:href="#iconLeft"></use></svg>
(p / q)

View file

@ -216,7 +216,7 @@ ${checkUpdateHTML}
<span style="color:var(--b3-theme-background);font-family: cursive;">&nbsp;</span>
</div>
<div class='fn__hr'></div>
${window.siyuan.languages.about1}
${window.siyuan.languages.about1} ${"harmony" === window.siyuan.config.system.container? " • " + window.siyuan.languages.feedback + " 845765@qq.com" : ""}
</div>`;
},
bindEvent: () => {

View file

@ -52,6 +52,24 @@ export const keymap = {
</span>
<span data-type="update" class="config-keymap__key">${keyValue}</span>
<input data-key="plugin${Constants.ZWSP}${item.name}${Constants.ZWSP}${command.langKey}" data-value="${command.customHotkey}" data-default="${command.hotkey}" class="b3-text-field fn__none" value="${keyValue}" spellcheck="false">
</label>`;
});
item.updateProtyleToolbar([]).forEach(toolbarItem => {
if (typeof toolbarItem === "string" || Constants.INLINE_TYPE.concat("|").includes(toolbarItem.name) || !toolbarItem.hotkey) {
return;
}
const dockKeymap = window.siyuan.config.keymap.plugin[item.name][toolbarItem.name];
const keyValue = updateHotkeyTip(dockKeymap.custom);
commandHTML += `<label class="b3-list-item b3-list-item--narrow b3-list-item--hide-action">
<span class="b3-list-item__text">${toolbarItem.tip||window.siyuan.languages[toolbarItem.lang]}</span>
<span data-type="reset" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.reset}">
<svg><use xlink:href="#iconUndo"></use></svg>
</span>
<span data-type="clear" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.remove}">
<svg><use xlink:href="#iconTrashcan"></use></svg>
</span>
<span data-type="update" class="config-keymap__key">${keyValue}</span>
<input data-key="plugin${Constants.ZWSP}${item.name}${Constants.ZWSP}${toolbarItem.name}" data-value="${dockKeymap.custom}" data-default="${dockKeymap.default}" class="b3-text-field fn__none" value="${keyValue}" spellcheck="false">
</label>`;
});
Object.keys(item.docks).forEach(key => {

View file

@ -86,7 +86,7 @@ export const initConfigSearch = (element: HTMLElement, app: App) => {
getLang(["cloudStorage", "trafficStat", "sync", "backup", "cdn", "total", "sizeLimit", "cloudBackup",
"cloudBackupTip", "updatePath", "cloudSync", "upload", "download", "syncMode", "syncModeTip",
"generateConflictDoc", "generateConflictDocTip", "syncProvider", "syncProviderTip",
"syncMode1", "syncMode2", "reposTip", "openSyncTip1", "openSyncTip2", "cloudSyncDir", "config"]),
"syncMode1", "syncMode2", "reposTip", "openSyncTip1", "openSyncTip2", "cloudSyncDir", "cloudSyncDirTip", "config"]),
// 发布
getLang(["publishService", "publishServiceTip", "publishServicePort", "publishServicePortTip",
@ -100,7 +100,8 @@ export const initConfigSearch = (element: HTMLElement, app: App) => {
"systemLog", "importKey", "genKey", "genKeyByPW", "copyKey", "resetRepo", "systemLogTip", "export",
"downloadLatestVer", "safeQuit", "directConnection", "siyuanNote", "key", "password", "copied", "resetRepoTip",
"autoDownloadUpdatePkg", "autoDownloadUpdatePkgTip", "networkProxy", "keyPlaceholder", "initRepoKeyTip",
"googleAnalytics", "googleAnalyticsTip"]),
"googleAnalytics", "googleAnalyticsTip", "dataRepoPurge", "dataRepoPurgeTip", "dataRepoAutoPurgeIndexRetentionDays",
"dataRepoAutoPurgeRetentionIndexesDaily"]),
];
const inputElement = element.querySelector(".b3-form__icon input") as HTMLInputElement;
/// #if !BROWSER

View file

@ -194,10 +194,10 @@ export abstract class Constants {
public static readonly HELP_PATH = {
zh_CN: "20210808180117-czj9bvb",
zh_CHT: "20211226090932-5lcq56f",
ja_JP: "20240530133126-axarxgx",
en_US: "20210808180117-6v0mkxr",
fr_FR: "20210808180117-6v0mkxr",
es_ES: "20210808180117-6v0mkxr",
ja_JP: "20240530133126-axarxgx",
it_IT: "20210808180117-6v0mkxr",
de_DE: "20210808180117-6v0mkxr",
he_IL: "20210808180117-6v0mkxr",

View file

@ -14,13 +14,12 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
document.body.insertAdjacentHTML("beforeend", `<div class="tooltip" id="tooltip">${message}</div>`);
messageElement = document.getElementById("tooltip");
} else {
messageElement.className = "tooltip";
messageElement.innerHTML = message;
}
if (tooltipClass) {
messageElement.classList.add("tooltip--" + tooltipClass);
} else {
messageElement.className = "tooltip";
}
let left = targetRect.left;
@ -44,7 +43,7 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
left = parentRect.right + 8;
} else if (position?.endsWith("parentW")) {
// 数据库属性视图
top = parentRect.top + parseInt(position) || 8;
top = parentRect.top + (parseInt(position) || 8);
left = parentRect.left - messageElement.clientWidth;
}

View file

@ -62,6 +62,7 @@ ${unicode2Emoji(emoji.unicode)}</button>`;
});
entrie.target.innerHTML = html;
entrie.target.removeAttribute("data-index");
entrie.target.style.minHeight = "";
}
});
});

View file

@ -15,7 +15,6 @@ let isLoading = false;
const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
const previousElement = element.querySelector('[data-type="docprevious"]');
const nextElement = element.querySelector('[data-type="docnext"]');
element.setAttribute("data-page", currentPage.toString());
if (currentPage > 1) {
previousElement.removeAttribute("disabled");
} else {
@ -23,8 +22,9 @@ const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
}
const opElement = element.querySelector('.b3-select[data-type="opselect"]') as HTMLSelectElement;
const listElement = element.querySelector(".b3-list--background");
element.querySelector(".protyle-title__input").classList.add("fn__none");
element.querySelector('.history__text[data-type="docPanel"]').classList.add("fn__none");
element.querySelector('.history__text[data-type="mdPanel"]').classList.remove("fn__none");
element.querySelector('.history__text[data-type="mdPanel"]').classList.add("fn__none");
fetchPost("/api/history/searchHistory", {
query: id,
page: currentPage,
@ -36,7 +36,16 @@ const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
} else {
nextElement.setAttribute("disabled", "disabled");
}
nextElement.nextElementSibling.nextElementSibling.textContent = `${currentPage}/${response.data.pageCount || 1}`;
const pageNumElement = element.querySelector('[data-type="jumpRepoPage"]');
if (response.data.pageCount > 1) {
pageNumElement.removeAttribute("disabled");
} else {
pageNumElement.setAttribute("disabled", "disabled");
}
pageNumElement.setAttribute("data-totalpage", response.data.pageCount.toString());
pageNumElement.textContent = currentPage.toString();
const pageInfoElement = nextElement.nextElementSibling.nextElementSibling;
pageInfoElement.textContent = window.siyuan.languages.pageCountAndHistoryCount.replace("${x}", response.data.pageCount).replace("${y}", response.data.totalCount);
if (response.data.histories.length === 0) {
listElement.innerHTML = `<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>`;
return;
@ -61,40 +70,38 @@ export const openDocHistory = (options: {
notebookId: string,
pathString: string
}) => {
const contentHTML = `<div class="fn__flex fn__flex-1 history__panel">
const contentHTML = `<div class="history__action">
<div class="block__icons">
<span data-type="docprevious" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href="#iconLeft"></use></svg></span>
<button class="b3-button b3-button--text ft__selectnone" data-type="jumpRepoPage" disabled>1</button>
<span data-type="docnext" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.nextLabel}"><svg><use xlink:href="#iconRight"></use></svg></span>
<span class="fn__space"></span>
<span class="ft__on-surface fn__flex-shrink ft__selectnone">${window.siyuan.languages.pageCountAndHistoryCount}</span>
<span class="fn__space"></span>
<div class="fn__flex-1"></div>
<select data-type="opselect" class="b3-select">
<option value="all" selected>${window.siyuan.languages.allOp}</option>
<option value="update">${window.siyuan.languages.historyUpdate}</option>
<option value="format">${window.siyuan.languages.historyFormat}</option>
<option value="sync">${window.siyuan.languages.historySync}</option>
<option value="replace">${window.siyuan.languages.historyReplace}</option>
<option value="outline">${window.siyuan.languages.historyOutline}</option>
</select>
</div>
</div>
<div class="fn__flex fn__flex-1 history__panel">
<ul class="b3-list b3-list--background history__side" ${isMobile() ? "" : `style="width: ${window.siyuan.storage[Constants.LOCAL_HISTORY].sideDocWidth}"`}>
<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>
</ul>
<div class="history__resize"></div>
<div class="fn__flex-1 fn__flex-column">
<div class="protyle-title__input ft__center ft__breakword"></div>
<div class="protyle-title__input fn__none ft__center ft__breakword"></div>
<textarea class="fn__flex-1 history__text fn__none" readonly data-type="mdPanel"></textarea>
<div class="fn__flex-1 history__text fn__none" style="padding: 0" data-type="docPanel"></div>
</div>
</div>`;
const dialog = new Dialog({
title:`<div class="block__icons">
${isMobile() ? "" : options.pathString}
<span class="fn__space"></span>
<div class="fn__flex-1"></div>
<select data-type="opselect" class="b3-select">
<option value="all" selected>${window.siyuan.languages.allOp}</option>
<option value="clean">${window.siyuan.languages.historyClean}</option>
<option value="update">${window.siyuan.languages.historyUpdate}</option>
<option value="delete">${window.siyuan.languages.historyDelete}</option>
<option value="format">${window.siyuan.languages.historyFormat}</option>
<option value="sync">${window.siyuan.languages.historySync}</option>
<option value="replace">${window.siyuan.languages.historyReplace}</option>
<option value="outline">${window.siyuan.languages.historyOutline}</option>
</select>
<span class="fn__space"></span>
<span data-type="docprevious" class="block__icon block__icon--show b3-tooltips b3-tooltips__s" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href="#iconLeft"></use></svg></span>
<span class="fn__space"></span>
<span data-type="docnext" class="block__icon block__icon--show b3-tooltips b3-tooltips__s" disabled="disabled" aria-label="${window.siyuan.languages.nextLabel}"><svg><use xlink:href="#iconRight"></use></svg></span>
<span class="fn__space"></span>
<span>1/1</span>
${isMobile() ? '<span class="fn__space"></span><span data-type="close" class="block__icon block__icon--show"><svg><use xlink:href="#iconClose"></use></svg></span>' : ""}
</div>`,
title: options.pathString,
content: contentHTML,
width: isMobile() ? "100vw" : "90vw",
height: isMobile() ? "100vh" : "80vh",
@ -127,13 +134,13 @@ export const openDocHistory = (options: {
typewriterMode: false,
});
disabledProtyle(historyEditor.protyle);
const pageNumElement = dialog.element.querySelector('[data-type="jumpRepoPage"]');
const titleElement = dialog.element.querySelector(".protyle-title__input");
dialog.element.addEventListener("click", (event) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(dialog.element)) {
const type = target.getAttribute("data-type");
if (type === "close") {
dialog.destroy();
} else if (type === "rollback" && !isLoading) {
if (type === "rollback" && !isLoading) {
getHistoryPath(target.parentElement, opElement.value, options.id, (item) => {
const dataPath = item.path;
isLoading = false;
@ -168,7 +175,8 @@ export const openDocHistory = (options: {
action: [Constants.CB_GET_HISTORY, Constants.CB_GET_HTML],
});
}
dialog.element.querySelector(".protyle-title__input").textContent = item.title;
titleElement.textContent = item.title;
titleElement.classList.remove("fn__none");
isLoading = false;
});
target.parentElement.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
@ -178,11 +186,24 @@ export const openDocHistory = (options: {
event.preventDefault();
break;
} else if ((type === "docprevious" || type === "docnext") && target.getAttribute("disabled") !== "disabled") {
const currentPage = parseInt(dialog.element.getAttribute("data-page"));
const currentPage = parseInt(pageNumElement.textContent);
renderDoc(dialog.element, type === "docprevious" ? currentPage - 1 : currentPage + 1, options.id);
event.stopPropagation();
event.preventDefault();
break;
} else if (type === "jumpRepoPage") {
const totalPage = parseInt(target.getAttribute("data-totalpage") || "1");
confirmDialog(
window.siyuan.languages.jumpToPage.replace("${x}", totalPage),
`<input class="b3-text-field fn__block" type="number" min="1" max="${totalPage}" value="${pageNumElement.textContent}">`,
(confirmD) => {
const inputElement = confirmD.element.querySelector(".b3-text-field") as HTMLInputElement;
if (inputElement.value === "") {
return;
}
renderDoc(dialog.element, Math.max(1, Math.min(parseInt(inputElement.value), totalPage)), options.id);
}
);
}
target = target.parentElement;
}

View file

@ -354,7 +354,7 @@ export const openHistory = (app: App) => {
</div>
<div class="fn__flex-1 fn__flex" id="historyContainer">
<div data-type="doc" class="history__repo fn__block" data-init="true">
<div style="overflow:auto;border-bottom: 1px solid var(--b3-border-color);">
<div class="history__action">
<div class="block__icons">
<span data-type="docprevious" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href='#iconLeft'></use></svg></span>
<button class="b3-button b3-button--text ft__selectnone" data-type="jumpHistoryPage" data-totalpage="1">1</button>
@ -409,7 +409,7 @@ export const openHistory = (app: App) => {
<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>
</ul>
<div data-type="repo" class="fn__none history__repo">
<div style="overflow: auto"">
<div class="history__action">
<div class="block__icons">
<span data-type="previous" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href='#iconLeft'></use></svg></span>
<button class="b3-button b3-button--text ft__selectnone" data-type="jumpRepoPage" data-totalpage="1">1</button>
@ -445,6 +445,7 @@ export const openHistory = (app: App) => {
icon: "iconHistory",
title: window.siyuan.languages.dataHistory,
bindEvent(element) {
element.firstElementChild.setAttribute("style", "background-color:var(--b3-theme-background);height:100%");
bindEvent(app, element.firstElementChild);
}
});
@ -839,9 +840,9 @@ const bindEvent = (app: App, element: Element, dialog?: Dialog) => {
if (totalPage > 1) {
confirmDialog(
window.siyuan.languages.jumpToPage.replace("${x}", totalPage),
`<input style="width: 100%;" class="b3-text-field fn__flex-center" type="number" min="1" max="${totalPage}" value="${currentPage}">`,
(dialog: Dialog) => {
const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
`<input class="b3-text-field fn__block" type="number" min="1" max="${totalPage}" value="${currentPage}">`,
(confirmD) => {
const inputElement = confirmD.element.querySelector(".b3-text-field") as HTMLInputElement;
if (inputElement.value === "") {
return;
}
@ -858,9 +859,9 @@ const bindEvent = (app: App, element: Element, dialog?: Dialog) => {
if (totalPage > 1) {
confirmDialog(
window.siyuan.languages.jumpToPage.replace("${x}", totalPage),
`<input style="width: 100%;" class="b3-text-field fn__flex-center" type="number" min="1" max="${totalPage}" value="${currentPage}">`,
(dialog: Dialog) => {
const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
`<input class="b3-text-field fn__block" type="number" min="1" max="${totalPage}" value="${currentPage}">`,
(confirmD) => {
const inputElement = confirmD.element.querySelector(".b3-text-field") as HTMLInputElement;
if (inputElement.value === "") {
return;
}

View file

@ -10,6 +10,7 @@ import {openFileById} from "../../editor/util";
import {Protyle} from "../../protyle";
import {MenuItem} from "../../menus/Menu";
import {App} from "../../index";
import {searchMarkRender} from "../../protyle/render/searchMarkRender";
export class Backlink extends Model {
public element: HTMLElement;
@ -456,6 +457,7 @@ export class Backlink extends Model {
}
});
editor.protyle.notebookId = liElement.getAttribute("data-notebook-id");
searchMarkRender(editor.protyle, editor.protyle.wysiwyg.element.querySelectorAll('span[data-type~="search-mark"]'));
this.editors.push(editor);
});
}

View file

@ -737,7 +737,7 @@ export class Files extends Model {
}
private updateDocInfo(data: IWebSocketData) {
const liElement = this.element.querySelector(`li[data-node-id="${data.data.rootID}"]`)
const liElement = this.element.querySelector(`li[data-node-id="${data.data.rootID}"]`);
if (liElement) {
liElement.setAttribute("data-count", data.data.subFileCount);
liElement.querySelector(".ariaLabel")?.setAttribute("aria-label", this.genDocAriaLabel(data.data, escapeGreat));

View file

@ -339,11 +339,15 @@ ${data.shorthandContent}
id: item
}, (response) => {
this.data[response.data.oId] = response.data;
let md = response.data.shorthandMd;
if ("" === md && "" === response.data.shorthandContent && "" != response.data.shorthandURL) {
md = "[" + response.data.shorthandTitle + "](" + response.data.shorthandURL + ")";
}
fetchPost("/api/filetree/createDoc", {
notebook: toNotebook[0],
path: pathPosix().join(getDisplayName(toPath[0], false, true), Lute.NewNodeID() + ".sy"),
title: replaceFileName(response.data.shorthandTitle),
md: response.data.shorthandMd,
md: md,
}, () => {
this.remove(item);
});

View file

@ -184,6 +184,7 @@ export const openFileAttr = (attrs: IObject, focusName = "bookmark", protyle?: I
});
const dialog = new Dialog({
width: isMobile() ? "92vw" : "50vw",
containerClassName: "b3-dialog__container--theme",
height: "80vh",
content: `<div class="fn__flex-column">
<div class="layout-tab-bar fn__flex" style="flex-shrink:0;border-radius: var(--b3-border-radius-b) var(--b3-border-radius-b) 0 0">
@ -234,7 +235,7 @@ export const openFileAttr = (attrs: IObject, focusName = "bookmark", protyle?: I
<div data-type="custom" class="fn__none custom-attr">
${customHTML}
<div class="b3-label">
<button data-action="addCustom" class="b3-button b3-button--outline">
<button data-action="addCustom" class="b3-button b3-button--cancel">
<svg><use xlink:href="#iconAdd"></use></svg>${window.siyuan.languages.addAttr}
</button>
</div>

View file

@ -991,7 +991,7 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
hideElements(["util", "toolbar", "hint"], protyle);
const id = nodeElement.getAttribute("data-node-id");
const imgElement = assetElement.querySelector("img");
const titleElement = assetElement.querySelector(".protyle-action__title") as HTMLElement;
const titleElement = assetElement.querySelector(".protyle-action__title span") as HTMLElement;
const html = nodeElement.outerHTML;
if (!protyle.disabled) {
window.siyuan.menus.menu.append(new MenuItem({
@ -1173,7 +1173,6 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
alignImgLeft(protyle, nodeElement, [assetElement], id, html);
}
}).element);
const width = imgElement.style.width.endsWith("vw") ? parseInt(imgElement.style.width) : 0;
let rangeElement: HTMLInputElement;
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.width,
@ -1181,7 +1180,7 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
iconHTML: "",
type: "readonly",
label: `<div class="fn__flex-center">
<input class="b3-text-field" value="${imgElement.style.width.endsWith("px") ? parseInt(imgElement.style.width) : ""}" type="number" style="margin: 4px" placeholder="${window.siyuan.languages.width}"> px
<input class="b3-text-field" style="margin: 4px 8px 4px 0" value="${imgElement.parentElement.style.width.endsWith("px") ? parseInt(imgElement.parentElement.style.width) : ""}" type="number" placeholder="${window.siyuan.languages.width}">px
</div>`,
bind(element) {
const inputElement = element.querySelector("input");
@ -1189,11 +1188,11 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
rangeElement.value = "0";
rangeElement.parentElement.setAttribute("aria-label", inputElement.value ? (inputElement.value + "px") : window.siyuan.languages.default);
imgElement.style.width = inputElement.value ? (inputElement.value + "px") : "";
imgElement.parentElement.style.width = inputElement.value ? (inputElement.value + "px") : "";
imgElement.style.height = "";
});
inputElement.addEventListener("blur", () => {
if (inputElement.value === imgElement.style.width.replace("px", "")) {
if (inputElement.value === imgElement.parentElement.style.width.replace("px", "")) {
return;
}
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
@ -1213,13 +1212,14 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
}, {
iconHTML: "",
type: "readonly",
label: `<div style="margin: 4px 0;" aria-label="${imgElement.style.width.endsWith("px") ? imgElement.style.width : (imgElement.style.width?.replace("vw", "%") || window.siyuan.languages.default)}" class="b3-tooltips b3-tooltips__n${isMobile() ? "" : " fn__size200"}">
<input style="box-sizing: border-box" value="${width}" class="b3-slider fn__block" max="100" min="1" step="1" type="range">
label: `<div style="margin: 4px 0;" aria-label="${imgElement.parentElement.style.width ? imgElement.parentElement.style.width.replace("vw", "%") : window.siyuan.languages.default}" class="b3-tooltips b3-tooltips__n${isMobile() ? "" : " fn__size200"}">
<input style="box-sizing: border-box" value="${(imgElement.parentElement.style.width.endsWith("%")||imgElement.parentElement.style.width.endsWith("vw")) ? parseInt(imgElement.parentElement.style.width) : 0}" class="b3-slider fn__block" max="100" min="1" step="1" type="range">
</div>`,
bind(element) {
rangeElement = element.querySelector("input");
rangeElement.addEventListener("input", () => {
imgElement.style.width = rangeElement.value + "vw";
imgElement.parentElement.style.width = rangeElement.value + "%";
imgElement.style.height = "";
rangeElement.parentElement.setAttribute("aria-label", `${rangeElement.value}%`);
});
rangeElement.addEventListener("change", () => {
@ -1236,14 +1236,13 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
]
}).element);
let rangeHeightElement: HTMLInputElement;
const height = imgElement.style.height.endsWith("vh") ? parseInt(imgElement.style.height) : 0;
window.siyuan.menus.menu.append(new MenuItem({
label: window.siyuan.languages.height,
submenu: [{
iconHTML: "",
type: "readonly",
label: `<div class="fn__flex-center">
<input class="b3-text-field" value="${imgElement.style.height.endsWith("px") ? parseInt(imgElement.style.height) : ""}" type="number" style="margin: 4px" placeholder="${window.siyuan.languages.height}"> px
<input class="b3-text-field" value="${imgElement.style.height.endsWith("px") ? parseInt(imgElement.style.height) : ""}" type="number" style="margin: 4px 8px 4px 0" placeholder="${window.siyuan.languages.height}">px
</div>`,
bind(element) {
const inputElement = element.querySelector("input");
@ -1252,8 +1251,7 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
rangeHeightElement.parentElement.setAttribute("aria-label", inputElement.value ? (inputElement.value + "px") : window.siyuan.languages.default);
imgElement.style.height = inputElement.value ? (inputElement.value + "px") : "";
assetElement.style.width = "";
imgElement.style.width = "";
imgElement.parentElement.style.width = "";
});
inputElement.addEventListener("blur", () => {
if (inputElement.value === imgElement.style.height.replace("px", "")) {
@ -1276,14 +1274,13 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
}, {
iconHTML: "",
type: "readonly",
label: `<div style="margin: 4px 0;" aria-label="${imgElement.style.height.endsWith("vh") ? parseInt(imgElement.style.height) + "%" : (imgElement.style.height || window.siyuan.languages.default)}" class="b3-tooltips b3-tooltips__n${isMobile() ? "" : " fn__size200"}">
<input style="box-sizing: border-box" value="${height}" class="b3-slider fn__block" max="100" min="1" step="1" type="range">
label: `<div style="margin: 4px 0;" aria-label="${imgElement.style.height ? imgElement.style.height.replace("vh", "%") : window.siyuan.languages.default}" class="b3-tooltips b3-tooltips__n${isMobile() ? "" : " fn__size200"}">
<input style="box-sizing: border-box" value="${imgElement.style.height.endsWith("vh") ? parseInt(imgElement.style.height) : 0}" class="b3-slider fn__block" max="100" min="1" step="1" type="range">
</div>`,
bind(element) {
rangeHeightElement = element.querySelector("input");
rangeHeightElement.addEventListener("input", () => {
assetElement.style.width = "";
imgElement.style.width = "";
imgElement.parentElement.style.width = "";
imgElement.style.height = rangeHeightElement.value + "vh";
rangeHeightElement.parentElement.setAttribute("aria-label", `${rangeHeightElement.value}%`);
});
@ -1823,11 +1820,7 @@ const genImageWidthMenu = (label: string, imgElement: HTMLElement, protyle: IPro
label,
click() {
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
if (label === window.siyuan.languages.default) {
imgElement.style.width = "";
} else {
imgElement.style.width = label.replace("%", "vw");
}
imgElement.parentElement.style.width = label === window.siyuan.languages.default ? "" : label;
imgElement.style.height = "";
updateTransaction(protyle, id, nodeElement.outerHTML, html);
focusBlock(nodeElement);
@ -1841,11 +1834,7 @@ const genImageHeightMenu = (label: string, imgElement: HTMLElement, protyle: IPr
label,
click() {
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
if (label === window.siyuan.languages.default) {
imgElement.style.height = "";
} else {
imgElement.style.height = parseInt(label) + "vh";
}
imgElement.style.height = label === window.siyuan.languages.default ? "" : parseInt(label) + "vh";
imgElement.style.width = "";
updateTransaction(protyle, id, nodeElement.outerHTML, html);
focusBlock(nodeElement);

View file

@ -172,9 +172,12 @@ export const openEditorTab = (app: App, ids: string[], notebookId?: string, path
};
export const copyPNGByLink = (link: string) => {
if (isInAndroid() || isInHarmony()) {
if (isInAndroid()) {
window.JSAndroid.writeImageClipboard(link);
return;
} else if (isInHarmony()) {
window.JSHarmony.writeImageClipboard(link);
return;
} else {
const canvas = document.createElement("canvas");
const tempElement = document.createElement("img");

View file

@ -34,7 +34,7 @@ class App {
public appId: string;
constructor() {
if (!window.webkit?.messageHandlers && !window.JSAndroid) {
if (!window.webkit?.messageHandlers && !window.JSAndroid && !window.JSHarmony) {
registerServiceWorker(`${Constants.SERVICE_WORKER_PATH}?v=${Constants.SIYUAN_VERSION}`);
}
addBaseURL();

View file

@ -169,7 +169,7 @@ export const initAbout = () => {
</div>
</div>
<div style="color:var(--b3-theme-surface);font-family: cursive;">&nbsp;</div>
${window.siyuan.languages.about1}
${window.siyuan.languages.about1} ${"harmony" === window.siyuan.config.system.container? " • " + window.siyuan.languages.feedback + " 845765@qq.com" : ""}
</div>
</div>`,
bindEvent(modelMainElement: HTMLElement) {

View file

@ -15,6 +15,7 @@ import {hasClosestByAttribute} from "../protyle/util/hasClosest";
import {BlockPanel} from "../block/Panel";
import {Setting} from "./Setting";
import {clearOBG} from "../layout/dock/util";
import {Constants} from "../constants";
export class Plugin {
private app: App;
@ -75,6 +76,29 @@ export class Plugin {
value: options.name,
writable: false,
});
this.updateProtyleToolbar([]).forEach(toolbarItem => {
if (typeof toolbarItem === "string" || Constants.INLINE_TYPE.concat("|").includes(toolbarItem.name) || !toolbarItem.hotkey) {
return;
}
if (!window.siyuan.config.keymap.plugin) {
window.siyuan.config.keymap.plugin = {};
}
if (!window.siyuan.config.keymap.plugin[options.name]) {
window.siyuan.config.keymap.plugin[options.name] = {
[toolbarItem.name]: {
default: toolbarItem.hotkey,
custom: toolbarItem.hotkey,
}
};
}
if (!window.siyuan.config.keymap.plugin[options.name][toolbarItem.name]) {
window.siyuan.config.keymap.plugin[options.name][toolbarItem.name] = {
default: toolbarItem.hotkey,
custom: toolbarItem.hotkey,
};
}
});
}
public onload() {

View file

@ -64,7 +64,7 @@ export const saveExport = (option: IExportOptions) => {
wordDialog.destroy();
});
} else {
getExportPath(option);
getExportPath(option, false, true);
}
/// #endif
};
@ -441,7 +441,8 @@ const renderPDF = async (id: string) => {
const linkAddress = target.getAttribute("href");
if (linkAddress.startsWith("#")) {
// 导出预览模式点击块引转换后的脚注跳转不正确 https://github.com/siyuan-note/siyuan/issues/5700
previewElement.querySelector(linkAddress).scrollIntoView();
const hash = linkAddress.substring(1);
previewElement.querySelector('[data-node-id="' + hash + '"], [id="' + hash + '"]').scrollIntoView();
event.stopPropagation();
event.preventDefault();
return;

View file

@ -1653,8 +1653,10 @@ export class Gutter {
label: `${window.siyuan.languages.copy} ${window.siyuan.languages.headings1}`,
click() {
fetchPost("/api/block/getHeadingChildrenDOM", {id}, (response) => {
if (isInAndroid() || isInHarmony()) {
if (isInAndroid()) {
window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else if (isInHarmony()) {
window.JSHarmony.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else {
writeText(response.data + Constants.ZWSP);
}
@ -1667,8 +1669,10 @@ export class Gutter {
label: `${window.siyuan.languages.cut} ${window.siyuan.languages.headings1}`,
click() {
fetchPost("/api/block/getHeadingChildrenDOM", {id}, (response) => {
if (isInAndroid() || isInHarmony()) {
if (isInAndroid()) {
window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else if (isInHarmony()) {
window.JSHarmony.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else {
writeText(response.data + Constants.ZWSP);
}

View file

@ -12,7 +12,7 @@ import {MenuItem} from "../../menus/Menu";
import {openFileAttr,} from "../../menus/commonMenuItem";
import {Constants} from "../../constants";
import {matchHotKey} from "../util/hotKey";
import {isMac, readText, writeText} from "../util/compatibility";
import {isMac, readText} from "../util/compatibility";
import * as dayjs from "dayjs";
import {openFileById} from "../../editor/util";
import {setTitle} from "../../dialog/processSystem";
@ -25,6 +25,7 @@ import {hideTooltip} from "../../dialog/tooltip";
import {commonClick} from "../wysiwyg/commonClick";
import {openTitleMenu} from "./openTitleMenu";
import {electronUndo} from "../undo";
import {enableLuteMarkdownSyntax, restoreLuteMarkdownSyntax} from "../util/paste";
export class Title {
public element: HTMLElement;
@ -77,7 +78,9 @@ export class Title {
navigator.clipboard.readText().then(textPlain => {
// 对 HTML 标签进行内部转义,避免被 Lute 解析以后变为小写 https://github.com/siyuan-note/siyuan/issues/10620
textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;");
enableLuteMarkdownSyntax(protyle);
let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
restoreLuteMarkdownSyntax(protyle);
// 移除 ;;;lt;;; 和 ;;;gt;;; 转义及其包裹的内容
content = content.replace(/;;;lt;;;[^;]+;;;gt;;;/g, "");
document.execCommand("insertText", false, replaceFileName(content));
@ -229,7 +232,9 @@ export class Title {
click: async () => {
navigator.clipboard.readText().then(textPlain => {
textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;");
enableLuteMarkdownSyntax(protyle);
let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
restoreLuteMarkdownSyntax(protyle);
// 移除 ;;;lt;;; 和 ;;;gt;;; 转义及其包裹的内容
content = content.replace(/;;;lt;;;[^;]+;;;gt;;;/g, "");
document.execCommand("insertText", false, replaceFileName(content));

View file

@ -72,6 +72,12 @@ export class Protyle {
element: id,
options: mergedOptions,
block: {},
highlight: {
mark: new Highlight(),
markHL: new Highlight(),
ranges: [],
rangeIndex: 0,
}
};
this.protyle.hint = new Hint(this.protyle);

View file

@ -77,7 +77,8 @@ export class Preview {
const linkAddress = target.getAttribute("href");
if (linkAddress.startsWith("#")) {
// 导出预览模式点击块引转换后的脚注跳转不正确 https://github.com/siyuan-note/siyuan/issues/5700
previewElement.querySelector(linkAddress).scrollIntoView();
const hash = linkAddress.substring(1);
previewElement.querySelector('[data-node-id="' + hash + '"], [id="' + hash + '"]').scrollIntoView();
event.stopPropagation();
event.preventDefault();
break;

View file

@ -212,9 +212,9 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
if (!rowElement) {
return;
}
const type = getTypeByCellElement(target);
const cellType = getTypeByCellElement(target);
// TODO 点击单元格的时候, lineNumber 选中整行
if (type === "updated" || type === "created" || type === "lineNumber" || (type === "block" && !target.getAttribute("data-detached"))) {
if (cellType === "updated" || cellType === "created" || cellType === "lineNumber" || (cellType === "block" && !target.getAttribute("data-detached"))) {
selectRow(rowElement.querySelector(".av__firstcol"), "toggle");
} else {
scrollElement.querySelectorAll(".av__row--select").forEach(item => {
@ -229,7 +229,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
event.stopPropagation();
return true;
} else if (target.classList.contains("av__calc")) {
openCalcMenu(protyle, target);
openCalcMenu(protyle, target, undefined, event.clientX - 64);
event.preventDefault();
event.stopPropagation();
return true;

View file

@ -9,8 +9,12 @@ import {transaction} from "../../wysiwyg/transaction";
import {openMenuPanel} from "./openMenuPanel";
import {uploadFiles} from "../../upload";
import {openLink} from "../../../editor/openLink";
import {editAssetItem} from "./asset";
import {dragUpload, editAssetItem} from "./asset";
import {previewImage} from "../../preview/image";
/// #if !BROWSER
import {webUtils} from "electron";
/// #endif
import {isBrowser} from "../../../util/functions";
const genAVRollupHTML = (value: IAVCellValue) => {
let html = "";
@ -56,13 +60,13 @@ export const genAVValueHTML = (value: IAVCellValue) => {
let html = "";
switch (value.type) {
case "block":
html = `<div class="fn__flex-1">${value.block.content}</div>`;
html = `<div class="fn__flex-1" placeholder="${window.siyuan.languages.empty}">${value.block.content}</div>`;
break;
case "text":
html = `<textarea style="resize: vertical" rows="${value.text.content.split("\n").length}" class="b3-text-field b3-text-field--text fn__flex-1">${value.text.content}</textarea>`;
html = `<textarea style="resize: vertical" rows="${value.text.content.split("\n").length}" class="b3-text-field b3-text-field--text fn__flex-1" placeholder="${window.siyuan.languages.empty}">${value.text.content}</textarea>`;
break;
case "number":
html = `<input value="${value.number.isNotEmpty ? value.number.content : ""}" type="number" class="b3-text-field b3-text-field--text fn__flex-1">
html = `<input value="${value.number.isNotEmpty ? value.number.content : ""}" type="number" class="b3-text-field b3-text-field--text fn__flex-1" placeholder="${window.siyuan.languages.empty}">
<span class="fn__space"></span><span class="fn__flex-center ft__on-surface b3-tooltips__w b3-tooltips" aria-label="${window.siyuan.languages.format}">${value.number.formattedContent}</span><span class="fn__space"></span>`;
break;
case "mSelect":
@ -84,7 +88,7 @@ export const genAVValueHTML = (value: IAVCellValue) => {
});
break;
case "date":
html = `<span class="av__celltext" data-value='${JSON.stringify(value[value.type])}'>`;
html = `<span class="av__celltext" data-value='${JSON.stringify(value[value.type])}' placeholder="${window.siyuan.languages.empty}">`;
if (value[value.type] && value[value.type].isNotEmpty) {
html += dayjs(value[value.type].content).format(value[value.type].isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm");
}
@ -100,12 +104,12 @@ export const genAVValueHTML = (value: IAVCellValue) => {
}
break;
case "url":
html = `<input value="${value.url.content}" class="b3-text-field b3-text-field--text fn__flex-1">
html = `<input value="${value.url.content}" class="b3-text-field b3-text-field--text fn__flex-1" placeholder="${window.siyuan.languages.empty}">
<span class="fn__space"></span>
<a href="${value.url.content}" target="_blank" aria-label="${window.siyuan.languages.openBy}" class="block__icon block__icon--show fn__flex-center b3-tooltips__w b3-tooltips"><svg><use xlink:href="#iconLink"></use></svg></a>`;
break;
case "phone":
html = `<input value="${value.phone.content}" class="b3-text-field b3-text-field--text fn__flex-1">
html = `<input value="${value.phone.content}" class="b3-text-field b3-text-field--text fn__flex-1" placeholder="${window.siyuan.languages.empty}">
<span class="fn__space"></span>
<a href="tel:${value.phone.content}" target="_blank" aria-label="${window.siyuan.languages.openBy}" class="block__icon block__icon--show fn__flex-center b3-tooltips__w b3-tooltips"><svg><use xlink:href="#iconPhone"></use></svg></a>`;
break;
@ -113,10 +117,10 @@ export const genAVValueHTML = (value: IAVCellValue) => {
html = `<svg class="av__checkbox"><use xlink:href="#icon${value.checkbox.checked ? "Check" : "Uncheck"}"></use></svg>`;
break;
case "template":
html = `<div class="fn__flex-1">${value.template.content}</div>`;
html = `<div class="fn__flex-1" placeholder="${window.siyuan.languages.empty}">${value.template.content}</div>`;
break;
case "email":
html = `<input value="${value.email.content}" class="b3-text-field b3-text-field--text fn__flex-1">
html = `<input value="${value.email.content}" class="b3-text-field b3-text-field--text fn__flex-1" placeholder="${window.siyuan.languages.empty}">
<span class="fn__space"></span>
<a href="mailto:${value.email.content}" target="_blank" aria-label="${window.siyuan.languages.openBy}" class="block__icon block__icon--show fn__flex-center b3-tooltips__w b3-tooltips"><svg><use xlink:href="#iconEmail"></use></svg></a>`;
break;
@ -188,17 +192,14 @@ export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IPr
<span>${escapeHtml(item.key.name)}</span>
</div>
<div data-av-id="${table.avID}" data-col-id="${item.values[0].keyID}" data-block-id="${item.values[0].blockID}" data-id="${item.values[0].id}" data-type="${item.values[0].type}"
data-options="${item.key?.options ? escapeAttr(JSON.stringify(item.key.options)) : "[]"}"
class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"].includes(item.values[0].type) ? "" : " custom-attr__avvalue"}">
${genAVValueHTML(item.values[0])}
</div>
data-options="${item.key?.options ? escapeAttr(JSON.stringify(item.key.options)) : "[]"}"
${["text", "number", "date", "url", "phone", "template", "email"].includes(item.values[0].type) ? "" : `placeholder="${window.siyuan.languages.empty}"`}
class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone"].includes(item.values[0].type) ? "" : " custom-attr__avvalue"}${["block", "created", "updated"].includes(item.values[0].type) ? " custom-attr__avvalue--readonly" : ""}">${genAVValueHTML(item.values[0])}</div>
</div>`;
});
innerHTML += `<div class="fn__hr"></div>
<div class="fn__flex">
<div class="fn__space"></div><div class="fn__space"></div>
<button data-type="addColumn" class="b3-button b3-button--outline"><svg><use xlink:href="#iconAdd"></use></svg>${window.siyuan.languages.addAttr}</button>
</div><div class="fn__hr--b"></div>`;
<button data-type="addColumn" class="b3-button b3-button--cancel"><svg><use xlink:href="#iconAdd"></use></svg>${window.siyuan.languages.newCol}</button>
<div class="fn__hr--b"></div>`;
html += `<div data-av-id="${table.avID}" data-node-id="${id}" data-type="NodeAttributeView">${innerHTML}</div>`;
if (element.innerHTML) {
@ -224,9 +225,13 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"]
ghostElement.remove();
});
});
element.addEventListener("drop", () => {
element.addEventListener("drop", (event) => {
counter = 0;
window.siyuan.dragElement.style.opacity = "";
if (protyle.disabled) {
event.preventDefault();
event.stopPropagation();
return;
}
const targetElement = element.querySelector(".dragover__bottom, .dragover__top") as HTMLElement;
if (targetElement && dragBlockElement) {
const isBottom = targetElement.classList.contains("dragover__bottom");
@ -251,12 +256,38 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"]
}
}
targetElement.classList.remove("dragover__bottom", "dragover__top");
} else if (!window.siyuan.dragElement && event.dataTransfer.types[0] === "Files") {
const cellElement = element.querySelector(".custom-attr__avvalue--active") as HTMLElement;
if (cellElement) {
if (event.dataTransfer.types[0] === "Files" && !isBrowser()) {
const files: string[] = [];
for (let i = 0; i < event.dataTransfer.files.length; i++) {
files.push(webUtils.getPathForFile(event.dataTransfer.files[i]));
}
dragUpload(files, protyle, cellElement);
}
}
}
if (window.siyuan.dragElement) {
window.siyuan.dragElement.style.opacity = "";
window.siyuan.dragElement = undefined;
}
window.siyuan.dragElement = null;
});
element.addEventListener("dragover", (event: DragEvent) => {
const target = event.target as HTMLElement;
let targetElement = hasClosestByClassName(target, "av__row");
let targetElement: HTMLElement | false;
if (event.dataTransfer.types.includes("Files")) {
element.querySelectorAll(".custom-attr__avvalue--active").forEach((item: HTMLElement) => {
item.classList.remove("custom-attr__avvalue--active");
});
targetElement = hasClosestByClassName(target, "custom-attr__avvalue");
if (targetElement && targetElement.getAttribute("data-type") === "mAsset") {
targetElement.classList.add("custom-attr__avvalue--active");
event.preventDefault();
}
return;
}
targetElement = hasClosestByClassName(target, "av__row");
if (!targetElement) {
targetElement = hasClosestByClassName(document.elementFromPoint(event.clientX, event.clientY - 1), "av__row");
}

View file

@ -79,7 +79,7 @@ export const openCalcMenu = async (protyle: IProtyle, calcElement: HTMLElement,
data: IAV,
colId: string,
blockID: string
}) => {
}, x?: number) => {
let rowElement: HTMLElement | false;
let type;
let colId: string;
@ -403,7 +403,7 @@ export const openCalcMenu = async (protyle: IProtyle, calcElement: HTMLElement,
});
}
const calcRect = calcElement.getBoundingClientRect();
menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height});
menu.open({x: Math.max(x || 0, calcRect.left), y: calcRect.bottom, h: calcRect.height});
};
export const getCalcValue = (column: IAVColumn) => {

View file

@ -8,6 +8,7 @@ import {updateCellsValue} from "./cell";
import {updateAttrViewCellAnimation} from "./action";
import {focusBlock} from "../../util/selection";
import {setPosition} from "../../../util/setPosition";
import * as dayjs from "dayjs";
const genSearchList = (element: Element, keyword: string, avId?: string, excludes = true, cb?: () => void) => {
fetchPost("/api/av/searchAttributeView", {
@ -213,6 +214,11 @@ const genSelectItemHTML = (type: "selected" | "empty" | "unselect", id?: string,
<svg class="b3-menu__action"><use xlink:href="#iconMin"></use></svg>`;
}
if (type === "empty") {
if (id) {
return `<button class="b3-menu__item" data-type="setRelationCell">
<span class="b3-menu__label">${window.siyuan.languages.newRowInRelation.replace("${x}", text).replace("${y}", id)}</span>
</button>`;
}
return `<button class="b3-menu__item">
<span class="b3-menu__label">${window.siyuan.languages.emptyContent}</span>
</button>`;
@ -243,9 +249,10 @@ const filterItem = (menuElement: Element, cellElement: HTMLElement, keyword: str
html += genSelectItemHTML("unselect", item.block.id, item.isDetached, item.block.content || window.siyuan.languages.untitled);
}
});
menuElement.querySelector(".b3-menu__items").innerHTML = `${selectHTML || genSelectItemHTML("empty")}
menuElement.querySelector(".b3-menu__items").innerHTML = `${selectHTML}
<button class="b3-menu__separator"></button>
${html || genSelectItemHTML("empty")}`;
${html}
${keyword ? genSelectItemHTML("empty", keyword, undefined, menuElement.querySelector(".popover__block").outerHTML) : (html ? "" : genSelectItemHTML("empty"))}`;
menuElement.querySelector(".b3-menu__items .b3-menu__item:not(.fn__none)").classList.add("b3-menu__item--current");
});
};
@ -273,7 +280,7 @@ export const bindRelationEvent = (options: {
html += genSelectItemHTML("unselect", item.block.id, item.isDetached, item.block.content || window.siyuan.languages.untitled);
}
});
options.menuElement.querySelector(".b3-menu__items").innerHTML = `${selectHTML || genSelectItemHTML("empty")}
options.menuElement.querySelector(".b3-menu__items").innerHTML = `${selectHTML}
<button class="b3-menu__separator"></button>
${html || genSelectItemHTML("empty")}`;
const cellRect = options.cellElements[options.cellElements.length - 1].getBoundingClientRect();
@ -340,7 +347,7 @@ export const getRelationHTML = (data: IAV, cellElements?: HTMLElement[]) => {
};
export const setRelationCell = (protyle: IProtyle, nodeElement: HTMLElement, target: HTMLElement, cellElements: HTMLElement[]) => {
const menuElement = hasClosestByClassName(target, "b3-menu__items");
const menuElement = hasClosestByClassName(target, "b3-menu");
if (!menuElement) {
return;
}
@ -353,7 +360,7 @@ export const setRelationCell = (protyle: IProtyle, nodeElement: HTMLElement, tar
}
if (!nodeElement.contains(cellElements[0])) {
cellElements[0] = (nodeElement.querySelector(`.av__row[data-id="${rowElement.dataset.id}"] .av__cell[data-col-id="${cellElements[0].dataset.colId}"]`) ||
nodeElement.querySelector(`.fn__flex-1[data-col-id="${cellElements[0].dataset.colId}"]`) ) as HTMLElement;
nodeElement.querySelector(`.fn__flex-1[data-col-id="${cellElements[0].dataset.colId}"]`)) as HTMLElement;
}
const newValue: IAVCellRelationValue = {blockIDs: [], contents: []};
menuElement.querySelectorAll('[draggable="true"]').forEach(item => {
@ -371,8 +378,9 @@ export const setRelationCell = (protyle: IProtyle, nodeElement: HTMLElement, tar
if (target.classList.contains("b3-menu__item")) {
const targetId = target.getAttribute("data-id");
const separatorElement = menuElement.querySelector(".b3-menu__separator");
const searchValue = menuElement.querySelector("input").value;
if (target.getAttribute("draggable")) {
if (!separatorElement.nextElementSibling.getAttribute("data-id")) {
if (!separatorElement.nextElementSibling.getAttribute("data-id") && !searchValue) {
separatorElement.nextElementSibling.remove();
}
const removeIndex = newValue.blockIDs.indexOf(targetId);
@ -380,13 +388,7 @@ export const setRelationCell = (protyle: IProtyle, nodeElement: HTMLElement, tar
newValue.contents.splice(removeIndex, 1);
separatorElement.after(target);
target.outerHTML = genSelectItemHTML("unselect", targetId, !target.querySelector(".popover__block"), target.querySelector(".b3-menu__label").textContent);
if (!separatorElement.previousElementSibling) {
separatorElement.insertAdjacentHTML("beforebegin", genSelectItemHTML("empty"));
}
} else {
if (!separatorElement.previousElementSibling.getAttribute("data-id")) {
separatorElement.previousElementSibling.remove();
}
} else if (targetId) {
newValue.blockIDs.push(targetId);
newValue.contents.push({
type: "block",
@ -401,6 +403,35 @@ export const setRelationCell = (protyle: IProtyle, nodeElement: HTMLElement, tar
if (!separatorElement.nextElementSibling) {
separatorElement.insertAdjacentHTML("afterend", genSelectItemHTML("empty"));
}
} else {
const blockID = target.querySelector(".popover__block").getAttribute("data-id");
const content = target.querySelector("b").textContent;
const rowId = Lute.NewNodeID();
transaction(protyle, [{
action: "insertAttrViewBlock",
ignoreFillFilter: true,
avID: menuElement.firstElementChild.getAttribute("data-av-id"),
srcs: [{
id: rowId,
isDetached: true,
content
}],
blockID,
}, {
action: "doUpdateUpdated",
id: blockID,
data: dayjs().format("YYYYMMDDHHmmss"),
}]);
newValue.blockIDs.push(rowId);
newValue.contents.push({
type: "block",
block: {
id: rowId,
content
},
isDetached: true
});
separatorElement.insertAdjacentHTML("beforebegin", `<button data-id="${rowId}" data-type="setRelationCell" class="b3-menu__item" draggable="true">${genSelectItemHTML("selected", rowId, true, content)}</button>`);
}
menuElement.querySelector(".b3-menu__item--current")?.classList.remove("b3-menu__item--current");
menuElement.querySelector(".b3-menu__items .b3-menu__item:not(.fn__none)").classList.add("b3-menu__item--current");

View file

@ -18,7 +18,7 @@ export const flowchartRender = (element: Element, cdn = Constants.PROTYLE_CDN) =
if (flowchartElements.length === 0) {
return;
}
addScript(`${cdn}/js/flowchart.js/flowchart.min.js?v=0.0.0`, "protyleFlowchartScript").then(() => {
addScript(`${cdn}/js/flowchart.js/flowchart.min.js?v=1.18.0`, "protyleFlowchartScript").then(() => {
if (flowchartElements[0].firstElementChild.clientWidth === 0) {
const observer = new MutationObserver(() => {
initFlowchart(flowchartElements);

View file

@ -14,7 +14,7 @@ export const highlightRender = (element: Element, cdn = Constants.PROTYLE_CDN) =
// bazaar reademe
codeElements = element.querySelectorAll("pre code");
codeElements.forEach(item => {
item.parentElement.setAttribute("lineNumber", "false");
item.parentElement.setAttribute("linenumber", "false");
});
} else if (element.classList.contains("b3-typography")) {
// preview & export html markdown
@ -94,10 +94,12 @@ export const highlightRender = (element: Element, cdn = Constants.PROTYLE_CDN) =
block.firstElementChild.className = "protyle-linenumber__rows";
block.firstElementChild.setAttribute("contenteditable", "false");
lineNumberRender(block);
block.style.display = "";
} else {
block.firstElementChild.className = "fn__none";
block.firstElementChild.innerHTML = "";
hljsElement.style.paddingLeft = "";
block.style.display = "block";
}
}
hljsElement.innerHTML = window.hljs.highlight(
@ -141,7 +143,7 @@ width: ${codeElement.clientWidth}px;
white-space:${codeElement.style.whiteSpace};
word-break:${codeElement.style.wordBreak};
font-variant-ligatures:${codeElement.style.fontVariantLigatures};
box-sizing: border-box;position: absolute;padding-top:0 !important;padding-bottom:0 !important;min-height:auto !important;`);
max-height: none;box-sizing: border-box;position: absolute;padding-top:0 !important;padding-bottom:0 !important;min-height:auto !important;`);
lineNumberTemp.setAttribute("contenteditable", "true");
block.insertAdjacentElement("afterend", lineNumberTemp);
@ -162,4 +164,16 @@ box-sizing: border-box;position: absolute;padding-top:0 !important;padding-botto
lineNumberTemp.remove();
block.firstElementChild.innerHTML = lineNumberHTML;
// https://github.com/siyuan-note/siyuan/issues/12726
if (block.scrollHeight > block.clientHeight) {
if (getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);
if (block.contains(range.startContainer)) {
const brElement = document.createElement("br");
range.insertNode(brElement);
brElement.scrollIntoView({block: "nearest"});
brElement.remove();
}
}
}
};

View file

@ -0,0 +1,27 @@
export const searchMarkRender = (protyle: IProtyle, matchElements: NodeListOf<Element>) => {
if (matchElements.length === 0) {
return;
}
protyle.highlight.markHL.clear();
protyle.highlight.markHL.clear();
protyle.highlight.ranges = [];
matchElements.forEach((item, index) => {
const range = new Range();
if (item.getAttribute("data-type") === "search-mark") {
const contentElement = item.firstChild;
item.replaceWith(contentElement);
range.selectNodeContents(contentElement);
} else {
item.setAttribute("data-type", item.getAttribute("data-type").replace(" search-mark", "").replace("search-mark ", ""));
range.selectNodeContents(item);
}
if (index === protyle.highlight.rangeIndex) {
protyle.highlight.markHL.add(range);
} else {
protyle.highlight.mark.add(range);
}
protyle.highlight.ranges.push(range);
});
CSS.highlights.set("search-mark", protyle.highlight.mark);
CSS.highlights.set("search-mark-hl", protyle.highlight.markHL);
};

View file

@ -69,7 +69,16 @@ export class Toolbar {
/// #endif
this.toolbarHeight = 29;
protyle.app.plugins.forEach(item => {
options.toolbar = toolbarKeyToMenu(item.updateProtyleToolbar(options.toolbar));
const pluginToolbar = item.updateProtyleToolbar(options.toolbar);
pluginToolbar.forEach(toolbarItem => {
if (typeof toolbarItem === "string" || Constants.INLINE_TYPE.concat("|").includes(toolbarItem.name) || !toolbarItem.hotkey) {
return;
}
if (window.siyuan.config.keymap.plugin && window.siyuan.config.keymap.plugin[item.name] && window.siyuan.config.keymap.plugin[item.name][toolbarItem.name]) {
toolbarItem.hotkey = window.siyuan.config.keymap.plugin[item.name][toolbarItem.name].custom;
}
});
options.toolbar = toolbarKeyToMenu(pluginToolbar);
});
options.toolbar.forEach((menuItem: IMenuItem) => {
const itemElement = this.genItem(protyle, menuItem);
@ -81,7 +90,16 @@ export class Toolbar {
this.element.innerHTML = "";
protyle.options.toolbar = toolbarKeyToMenu(Constants.PROTYLE_TOOLBAR);
protyle.app.plugins.forEach(item => {
protyle.options.toolbar = toolbarKeyToMenu(item.updateProtyleToolbar(protyle.options.toolbar));
const pluginToolbar = item.updateProtyleToolbar(protyle.options.toolbar);
pluginToolbar.forEach(toolbarItem => {
if (typeof toolbarItem === "string" || Constants.INLINE_TYPE.concat("|").includes(toolbarItem.name) || !toolbarItem.hotkey) {
return;
}
if (window.siyuan.config.keymap.plugin && window.siyuan.config.keymap.plugin[item.name] && window.siyuan.config.keymap.plugin[item.name][toolbarItem.name]) {
toolbarItem.hotkey = window.siyuan.config.keymap.plugin[item.name][toolbarItem.name].custom;
}
});
protyle.options.toolbar = toolbarKeyToMenu(pluginToolbar);
});
protyle.options.toolbar.forEach((menuItem: IMenuItem) => {
const itemElement = this.genItem(protyle, menuItem);
@ -153,7 +171,7 @@ export class Toolbar {
this.toolbarHeight = this.element.clientHeight;
const y = rangePosition.top - this.toolbarHeight - 4;
this.element.setAttribute("data-inity", y + Constants.ZWSP + protyle.contentElement.scrollTop.toString());
setPosition(this.element, rangePosition.left - 52, Math.max(y, protyle.element.getBoundingClientRect().top));
setPosition(this.element, rangePosition.left - 52, Math.max(y, protyle.element.getBoundingClientRect().top + 30));
this.element.querySelectorAll(".protyle-toolbar__item--current").forEach(item => {
item.classList.remove("protyle-toolbar__item--current");
});
@ -291,7 +309,7 @@ export class Toolbar {
)) {
// 移除
if (type === "clear") {
toolbarElement.querySelectorAll('[data-type="em"],[data-type="u"],[data-type="s"],[data-type="mark"],[data-type="sup"],[data-type="sub"],[data-type="strong"]').forEach(item => {
toolbarElement.querySelectorAll('[data-type="strong"],[data-type="em"],[data-type="u"],[data-type="s"],[data-type="mark"],[data-type="sup"],[data-type="sub"],[data-type="kbd"],[data-type="mark"],[data-type="code"]').forEach(item => {
item.classList.remove("protyle-toolbar__item--current");
});
} else if (actionBtn) {

View file

@ -184,7 +184,7 @@ export const setPadding = (protyle: IProtyle) => {
if (window.siyuan.config.editor.displayBookmarkIcon) {
const editorAttrElement = document.getElementById("editorAttr");
if (editorAttrElement) {
editorAttrElement.innerHTML = `.protyle-wysiwyg--attr .b3-tooltips:after { max-width: ${protyle.wysiwyg.element.clientWidth - left - right}px; }`;
editorAttrElement.innerHTML = `.protyle-wysiwyg--attr .b3-tooltips::after { max-width: ${protyle.wysiwyg.element.clientWidth - left - right}px; }`;
}
}
const oldWidth = protyle.wysiwyg.element.getAttribute("data-realwidth");

View file

@ -21,16 +21,20 @@ export const openByMobile = (uri: string) => {
window.webkit.messageHandlers.openLink.postMessage("https://" + uri);
}
}
} else if (isInAndroid() || isInHarmony()) {
} else if (isInAndroid()) {
window.JSAndroid.openExternal(uri);
} else if (isInHarmony()) {
window.JSHarmony.openExternal(uri);
} else {
window.open(uri);
}
};
export const readText = () => {
if (isInAndroid() || isInHarmony()) {
if (isInAndroid()) {
return window.JSAndroid.readClipboard();
} else if (isInHarmony()) {
return window.JSHarmony.readClipboard();
}
return navigator.clipboard.readText();
};
@ -42,10 +46,14 @@ export const writeText = (text: string) => {
}
try {
// navigator.clipboard.writeText 抛出异常不进入 catch这里需要先处理移动端复制
if (isInAndroid() || isInHarmony()) {
if (isInAndroid()) {
window.JSAndroid.writeClipboard(text);
return;
}
if (isInHarmony()) {
window.JSHarmony.writeClipboard(text);
return;
}
if (isInIOS()) {
window.webkit.messageHandlers.setClipboard.postMessage(text);
return;
@ -54,8 +62,10 @@ export const writeText = (text: string) => {
} catch (e) {
if (isInIOS()) {
window.webkit.messageHandlers.setClipboard.postMessage(text);
} else if (isInAndroid() || isInHarmony()) {
} else if (isInAndroid()) {
window.JSAndroid.writeClipboard(text);
} else if (isInHarmony()) {
window.JSHarmony.writeClipboard(text);
} else {
const textElement = document.createElement("textarea");
textElement.value = text;
@ -137,8 +147,8 @@ export const isInIOS = () => {
};
export const isInHarmony = () => {
return window.siyuan.config.system.container === "harmony";
}
return window.siyuan.config.system.container === "harmony" && window.JSHarmony;
};
// MacWindows 快捷键展示
export const updateHotkeyTip = (hotkey: string) => {

View file

@ -5,6 +5,10 @@ export const destroy = (protyle: IProtyle) => {
return;
}
hideElements(["util"], protyle);
protyle.highlight.markHL.clear();
protyle.highlight.mark.clear();
protyle.highlight.ranges = [];
protyle.highlight.rangeIndex = 0;
protyle.observer?.disconnect();
protyle.observerLoad?.disconnect();
protyle.element.classList.remove("protyle");

View file

@ -31,6 +31,7 @@ import {zoomOut} from "../../menus/protyle";
/// #if !BROWSER
import {webUtils} from "electron";
/// #endif
import {addDragFill} from "../render/av/cell";
const moveToNew = (protyle: IProtyle, sourceElements: Element[], targetElement: Element, newSourceElement: Element,
isSameDoc: boolean, isBottom: boolean, isCopy: boolean) => {
@ -1070,7 +1071,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
} else if (event.dataTransfer.getData(Constants.SIYUAN_DROP_FILE)?.split("-").length > 1) {
// 文件树拖拽
const ids = event.dataTransfer.getData(Constants.SIYUAN_DROP_FILE).split(",");
if (event.altKey) {
if (!event.altKey) {
if (event.y > protyle.wysiwyg.element.lastElementChild.getBoundingClientRect().bottom) {
insertEmptyBlock(protyle, "afterend", protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id"));
} else {
@ -1179,6 +1180,10 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
} else {
paste(protyle, event);
}
protyle.wysiwyg.element.querySelectorAll(".av__cell--select, .av__cell--active").forEach(item => {
item.classList.remove("av__cell--select", "av__cell--active");
item.querySelector(".av__drag-fill")?.remove();
});
} else {
const cellElement = hasClosestByClassName(event.target, "av__cell");
if (cellElement) {
@ -1214,8 +1219,27 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
behavior: "smooth"
});
}
let targetElement: HTMLElement | false;
// 设置了的话 drop 就无法监听 shift/control event.dataTransfer.dropEffect = "move";
if (event.dataTransfer.types.includes("Files")) {
targetElement = hasClosestByClassName(event.target, "av__cell");
if (targetElement && targetElement.getAttribute("data-dtype") === "mAsset" &&
!targetElement.classList.contains("av__cell--header")) {
event.preventDefault(); // 不使用导致无法触发 drop
if (dragoverElement && targetElement.isSameNode(dragoverElement)) {
return;
}
const blockElement = hasClosestBlock(targetElement);
if (blockElement) {
protyle.wysiwyg.element.querySelectorAll(".av__cell--select, .av__cell--active").forEach(item => {
item.classList.remove("av__cell--select", "av__cell--active");
item.querySelector(".av__drag-fill")?.remove();
});
targetElement.classList.add("av__cell--select");
addDragFill(targetElement);
dragoverElement = targetElement;
}
}
// 使用 event.preventDefault(); 会导致无光标 https://github.com/siyuan-note/siyuan/issues/12857
return;
}
@ -1230,7 +1254,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
event.preventDefault();
return;
}
if (event.shiftKey || event.altKey) {
const fileTreeIds = (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_FILE) && window.siyuan.dragElement) ? window.siyuan.dragElement.innerText : "";
if (event.shiftKey || (event.altKey && fileTreeIds.indexOf("-") === -1)) {
const targetElement = hasClosestBlock(event.target);
if (targetElement) {
targetElement.classList.remove("dragover__top", "protyle-wysiwyg--select", "dragover__bottom", "dragover__left", "dragover__right");
@ -1242,7 +1267,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
}
// 编辑器内文字拖拽或资源文件拖拽或按住 alt/shift 拖拽反链图标进入编辑器时不能运行 event.preventDefault() 否则无光标; 需放在 !window.siyuan.dragElement 之后
event.preventDefault();
let targetElement = hasClosestByClassName(event.target, "av__row") || hasClosestByClassName(event.target, "av__row--util") || hasClosestBlock(event.target);
targetElement = hasClosestByClassName(event.target, "av__row") || hasClosestByClassName(event.target, "av__row--util") || hasClosestBlock(event.target);
const point = {x: event.clientX, y: event.clientY, className: ""};
// 超级块中有ab两个段落块移动到 ab 之间的间隙 targetElement 会变为超级块,需修正为 a
@ -1315,7 +1340,6 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
if (!targetElement) {
return;
}
const fileTreeIds = (event.dataTransfer.types.includes(Constants.SIYUAN_DROP_FILE) && window.siyuan.dragElement) ? window.siyuan.dragElement.innerText : "";
if (targetElement && dragoverElement && targetElement.isSameNode(dragoverElement)) {
// 性能优化,目标为同一个元素不再进行校验
const nodeRect = targetElement.getBoundingClientRect();
@ -1324,6 +1348,15 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
item.removeAttribute("select-start");
item.removeAttribute("select-end");
});
// 文档树拖拽限制
if (fileTreeIds.indexOf("-") > -1 && !targetElement.classList.contains("av__row") &&
!targetElement.classList.contains("av__row--util")) {
if (!event.altKey) {
return;
} else if (fileTreeIds.split(",").includes(protyle.block.rootID) && event.altKey) {
return;
}
}
if (targetElement.getAttribute("data-type") === "NodeAttributeView" && hasClosestByTag(event.target, "TD")) {
return;
}
@ -1332,7 +1365,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
addDragover(targetElement);
return;
}
if (targetElement.getAttribute("data-type") === "NodeListItem" || fileTreeIds.indexOf("-") > -1) {
// 忘记为什么要限定文档树的拖拽了,先放开 https://github.com/siyuan-note/siyuan/pull/13284#issuecomment-2503853135
if (targetElement.getAttribute("data-type") === "NodeListItem") {
if (event.clientY > nodeRect.top + nodeRect.height / 2) {
targetElement.classList.add("dragover__bottom");
addDragover(targetElement);
@ -1380,9 +1414,16 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
}
return;
}
if (fileTreeIds.indexOf("-") > -1) {
if (fileTreeIds.split(",").includes(protyle.block.rootID) && !targetElement.classList.contains("av__row")) {
if (fileTreeIds.split(",").includes(protyle.block.rootID) && !targetElement.classList.contains("av__row") &&
!targetElement.classList.contains("av__row--util") && event.altKey) {
dragoverElement = undefined;
editorElement.querySelectorAll(".dragover__left, .dragover__right, .dragover__bottom, .dragover__top, .dragover").forEach((item: HTMLElement) => {
item.classList.remove("dragover__top", "dragover__bottom", "dragover__left", "dragover__right", "dragover");
item.removeAttribute("select-start");
item.removeAttribute("select-end");
});
} else {
dragoverElement = targetElement;
}

View file

@ -298,6 +298,10 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
if (!isBlock &&
(isNodeCodeBlock || protyle.toolbar.getCurrentType(range).includes("code"))) {
range.deleteContents();
// 代码块需保持至少一个 \n https://github.com/siyuan-note/siyuan/pull/13271#issuecomment-2502672155
if (isNodeCodeBlock && getContenteditableElement(blockElement).textContent === "") {
html += "\n";
}
range.insertNode(document.createTextNode(html.replace(/\r\n|\r|\u2028|\u2029/g, "\n")));
range.collapse(false);
range.insertNode(document.createElement("wbr"));

View file

@ -190,21 +190,9 @@ export const pasteAsPlainText = async (protyle: IProtyle) => {
textPlain = textPlain.replace(/__@kbd@__/g, "<kbd>").replace(/__@\/kbd@__/g, "</kbd>");
textPlain = textPlain.replace(/__@u@__/g, "<u>").replace(/__@\/u@__/g, "</u>");
protyle.lute.SetInlineAsterisk(true);
protyle.lute.SetGFMStrikethrough(true);
protyle.lute.SetInlineMath(true);
protyle.lute.SetSub(true);
protyle.lute.SetSup(true);
protyle.lute.SetTag(true);
protyle.lute.SetInlineUnderscore(true);
enableLuteMarkdownSyntax(protyle);
const content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
protyle.lute.SetInlineAsterisk(window.siyuan.config.editor.markdown.inlineAsterisk);
protyle.lute.SetGFMStrikethrough(window.siyuan.config.editor.markdown.inlineStrikethrough);
protyle.lute.SetInlineMath(window.siyuan.config.editor.markdown.inlineMath);
protyle.lute.SetSub(window.siyuan.config.editor.markdown.inlineSub);
protyle.lute.SetSup(window.siyuan.config.editor.markdown.inlineSup);
protyle.lute.SetTag(window.siyuan.config.editor.markdown.inlineTag);
protyle.lute.SetInlineUnderscore(window.siyuan.config.editor.markdown.inlineUnderscore);
restoreLuteMarkdownSyntax(protyle);
// insertHTML 会进行内部反转义
insertHTML(content, protyle, false, false, true);
@ -213,6 +201,26 @@ export const pasteAsPlainText = async (protyle: IProtyle) => {
}
};
export const enableLuteMarkdownSyntax = (protyle: IProtyle) => {
protyle.lute.SetInlineAsterisk(true);
protyle.lute.SetGFMStrikethrough(true);
protyle.lute.SetInlineMath(true);
protyle.lute.SetSub(true);
protyle.lute.SetSup(true);
protyle.lute.SetTag(true);
protyle.lute.SetInlineUnderscore(true);
};
export const restoreLuteMarkdownSyntax = (protyle: IProtyle) => {
protyle.lute.SetInlineAsterisk(window.siyuan.config.editor.markdown.inlineAsterisk);
protyle.lute.SetGFMStrikethrough(window.siyuan.config.editor.markdown.inlineStrikethrough);
protyle.lute.SetInlineMath(window.siyuan.config.editor.markdown.inlineMath);
protyle.lute.SetSub(window.siyuan.config.editor.markdown.inlineSub);
protyle.lute.SetSup(window.siyuan.config.editor.markdown.inlineSup);
protyle.lute.SetTag(window.siyuan.config.editor.markdown.inlineTag);
protyle.lute.SetInlineUnderscore(window.siyuan.config.editor.markdown.inlineUnderscore);
};
export const pasteText = (protyle: IProtyle, textPlain: string, nodeElement: Element, toBlockDOM = true) => {
const range = getEditorRange(protyle.wysiwyg.element);
if (nodeElement.getAttribute("data-type") === "NodeCodeBlock") {
@ -452,9 +460,14 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
)) {
isHTML = false;
} else {
// 需注意 Edge 中的选不应识别为图片 https://github.com/siyuan-note/siyuan/issues/7021
// 需注意 Edge 中的选不应识别为图片 https://github.com/siyuan-note/siyuan/issues/7021
isHTML = true;
}
if (textPlain && "" !== textPlain.trim() && textHTML.startsWith("<span") && -1 < textHTML.indexOf("white-space: pre;")) {
// 豆包复制粘贴问题 https://github.com/siyuan-note/siyuan/issues/13265
isHTML = false;
}
}
if (isHTML) {
const tempElement = document.createElement("div");

View file

@ -4,6 +4,8 @@ import {getDocByScroll, saveScroll} from "../scroll/saveScroll";
import {renderBacklink} from "../wysiwyg/renderBacklink";
import {hasClosestByClassName} from "./hasClosest";
import {preventScroll} from "../scroll/preventScroll";
import {searchMarkRender} from "../render/searchMarkRender";
import {restoreLuteMarkdownSyntax} from "./paste";
export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?: boolean) => {
if (!protyle.preview.element.classList.contains("fn__none")) {
@ -27,13 +29,7 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
}
protyle.lute.SetProtyleMarkNetImg(window.siyuan.config.editor.displayNetImgMark);
protyle.lute.SetSpellcheck(window.siyuan.config.editor.spellcheck);
protyle.lute.SetInlineAsterisk(window.siyuan.config.editor.markdown.inlineAsterisk);
protyle.lute.SetInlineUnderscore(window.siyuan.config.editor.markdown.inlineUnderscore);
protyle.lute.SetSup(window.siyuan.config.editor.markdown.inlineSup);
protyle.lute.SetSub(window.siyuan.config.editor.markdown.inlineSub);
protyle.lute.SetTag(window.siyuan.config.editor.markdown.inlineTag);
protyle.lute.SetInlineMath(window.siyuan.config.editor.markdown.inlineMath);
protyle.lute.SetGFMStrikethrough(window.siyuan.config.editor.markdown.inlineStrikethrough);
restoreLuteMarkdownSyntax(protyle);
protyle.lute.SetGFMStrikethrough1(false);
addLoading(protyle);
if (protyle.options.backlinkData) {
@ -48,6 +44,7 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
}, response => {
protyle.options.backlinkData = isMention ? response.data.backmentions : response.data.backlinks;
renderBacklink(protyle, protyle.options.backlinkData);
searchMarkRender(protyle, protyle.wysiwyg.element.querySelectorAll('span[data-type~="search-mark"]'));
});
}
} else {
@ -56,7 +53,12 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
protyle,
focus,
scrollAttr: saveScroll(protyle, true) as IScrollAttr,
updateReadonly
updateReadonly,
cb () {
if (protyle.query?.key) {
searchMarkRender(protyle, protyle.wysiwyg.element.querySelectorAll('span[data-type~="search-mark"]'));
}
}
});
}
};

View file

@ -120,6 +120,7 @@ export const enter = (blockElement: HTMLElement, range: Range, protyle: IProtyle
editableElement.parentElement.removeAttribute("data-render");
highlightRender(blockElement);
updateTransaction(protyle, blockElement.getAttribute("data-node-id"), blockElement.outerHTML, oldHTML);
scrollCenter(protyle);
return true;
}

View file

@ -4,7 +4,8 @@ import {
hasClosestByAttribute,
hasClosestByClassName,
hasClosestByMatchTag,
hasTopClosestByClassName, isInEmbedBlock,
hasTopClosestByClassName,
isInEmbedBlock,
} from "../util/hasClosest";
import {
focusBlock,
@ -12,7 +13,8 @@ import {
focusByWbr,
focusSideBlock,
getEditorRange,
getSelectionOffset, setFirstNodeRange,
getSelectionOffset,
setFirstNodeRange,
setLastNodeRange,
} from "../util/selection";
import {Constants} from "../../constants";
@ -23,7 +25,8 @@ import {
contentMenu,
enterBack,
fileAnnotationRefMenu,
imgMenu, inlineMathMenu,
imgMenu,
inlineMathMenu,
linkMenu,
refMenu,
setFold,
@ -62,7 +65,7 @@ import {openGlobalSearch} from "../../search/util";
import {popSearch} from "../../mobile/menu/search";
/// #endif
import {BlockPanel} from "../../block/Panel";
import {isInIOS, isOnlyMeta, readText} from "../util/compatibility";
import {isInIOS, isMac, isOnlyMeta, readText} from "../util/compatibility";
import {MenuItem} from "../../menus/Menu";
import {fetchPost} from "../../util/fetch";
import {onGet} from "../util/onGet";
@ -668,14 +671,13 @@ export class WYSIWYG {
const dragHeight = dragElement.clientHeight;
documentSelf.onmousemove = (moveEvent: MouseEvent) => {
if (dragElement.tagName === "IMG") {
dragElement.parentElement.parentElement.style.width = "";
dragElement.style.height = "";
}
if (moveEvent.clientX > x - dragWidth + 8 && moveEvent.clientX < mostRight) {
if ((dragElement.tagName === "IMG" && !dragElement.parentElement.parentElement.style.minWidth && nodeElement.style.textAlign !== "center") || !isCenter) {
dragElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x)) + "px";
dragElement.parentElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x)) + "px";
} else {
dragElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * 2) + "px";
dragElement.parentElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * 2) + "px";
}
}
if (dragElement.tagName !== "IMG") {
@ -769,11 +771,11 @@ export class WYSIWYG {
}
// 多选节点
let x = event.clientX;
let clentX = event.clientX;
if (event.clientX > mostRight) {
x = mostRight;
clentX = mostRight;
} else if (event.clientX < mostLeft) {
x = mostLeft;
clentX = mostLeft;
}
const mostTop = rect.top + (protyle.options.render.breadcrumb ? protyle.breadcrumb.element.parentElement.clientHeight : 0);
@ -877,7 +879,7 @@ export class WYSIWYG {
let newLeft = 0;
let newWidth = 0;
let newHeight = 0;
if (moveEvent.clientX < x) {
if (moveEvent.clientX < clentX) {
if (moveEvent.clientX < mostLeft) {
// 向左越界
newLeft = mostLeft;
@ -885,16 +887,16 @@ export class WYSIWYG {
// 向左
newLeft = moveEvent.clientX;
}
newWidth = x - newLeft;
newWidth = clentX - newLeft;
} else {
if (moveEvent.clientX > mostRight) {
// 向右越界
newLeft = x;
newLeft = clentX;
newWidth = mostRight - newLeft;
} else {
// 向右
newLeft = x;
newWidth = moveEvent.clientX - x;
newLeft = clentX;
newWidth = moveEvent.clientX - clentX;
}
}
@ -2005,15 +2007,16 @@ export class WYSIWYG {
// 输入法测试点 https://github.com/siyuan-note/siyuan/issues/3027
let isComposition = false; // for iPhone
this.element.addEventListener("compositionstart", (event) => {
// 搜狗输入法划选输入后无 data https://github.com/siyuan-note/siyuan/issues/4672
isComposition = true;
// 微软双拼由于 focusByRange 导致无法输入文字,因此不再 keydown 中记录了,但 keyup 会记录拼音字符,因此使用 isComposition 阻止 keyup 记录。
// 但搜狗输入法选中后继续输入不走 keydownisComposition 阻止了 keyup 记录,因此需在此记录。
const range = getEditorRange(protyle.wysiwyg.element);
const nodeElement = hasClosestBlock(range.startContainer);
if (nodeElement && typeof protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] === "undefined") {
if (!isMac() && nodeElement) {
range.insertNode(document.createElement("wbr"));
protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] = nodeElement.outerHTML;
nodeElement.querySelector("wbr").remove();
}
isComposition = true;
event.stopPropagation();
});
@ -2085,22 +2088,28 @@ export class WYSIWYG {
this.element.addEventListener("keyup", (event) => {
const range = getEditorRange(this.element).cloneRange();
const nodeElement = hasClosestBlock(range.startContainer);
if (event.key !== "PageUp" && event.key !== "PageDown" && event.key !== "Home" && event.key !== "End" && event.key.indexOf("Arrow") === -1 &&
event.key !== "Alt" && event.key !== "Shift" && event.key !== "CapsLock" && event.key !== "Escape" && event.key !== "Meta" && !/^F\d{1,2}$/.test(event.key) &&
(!event.isComposing || (event.isComposing && range.toString() !== "")) // https://github.com/siyuan-note/siyuan/issues/4341
) {
// 搜狗输入法不走 keydown需重新记录历史状态
if (range.toString() === "" && // windows 下回车新建块输入abc选中 bc ctrl+m 后光标错误
nodeElement && typeof protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] === "undefined") {
if (event.key !== "PageUp" && event.key !== "PageDown" && event.key !== "Home" && event.key !== "End" &&
event.key.indexOf("Arrow") === -1 && event.key !== "Escape" && event.key !== "Shift" &&
event.key !== "Meta" && event.key !== "Alt" && event.key !== "Control" && event.key !== "CapsLock" &&
!event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey &&
!/^F\d{1,2}$/.test(event.key)) {
// 搜狗输入法不走 keydown没有选中字符后不走 compositionstart需重新记录历史状态
if (!isMac() && nodeElement &&
// 微软双拼 keyup 会记录拼音字符,因此在 compositionstart 记录
!isComposition &&
(typeof protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] === "undefined" || range.toString() !== "" || !this.preventKeyup)) {
range.insertNode(document.createElement("wbr"));
protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] = nodeElement.outerHTML;
nodeElement.querySelector("wbr").remove();
}
this.preventKeyup = false;
return;
}
// 需放在 lastHTMLs 后,否则 https://github.com/siyuan-note/siyuan/issues/4388
if (this.preventKeyup) {
this.preventKeyup = false;
return;
}

View file

@ -298,6 +298,7 @@ const updateInput = (html: string, protyle: IProtyle, id: string) => {
data: protyle.wysiwyg.lastHTMLs[id],
action: "update"
});
protyle.wysiwyg.lastHTMLs[id] = item.outerHTML;
} else {
let firstElement;
if (index === 0) {

View file

@ -166,15 +166,19 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
// 有可能输入 shift+. ,因此需要使用 event.key 来进行判断
if (event.key !== "PageUp" && event.key !== "PageDown" && event.key !== "Home" && event.key !== "End" && event.key.indexOf("Arrow") === -1 &&
event.key !== "Escape" && event.key !== "Shift" && event.key !== "Meta" && event.key !== "Alt" && event.key !== "Control" && event.key !== "CapsLock" &&
!isNotEditBlock(nodeElement) &&
!/^F\d{1,2}$/.test(event.key) && typeof protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] === "undefined") {
!isNotEditBlock(nodeElement) && !/^F\d{1,2}$/.test(event.key) &&
// 微软双拼使用 compositionstart否则 focusByRange 导致无法输入文字
event.key !== "Process") {
const cloneRange = range.cloneRange();
range.collapse(false);
range.insertNode(document.createElement("wbr"));
protyle.wysiwyg.lastHTMLs[nodeElement.getAttribute("data-node-id")] = nodeElement.outerHTML;
nodeElement.querySelector("wbr").remove();
// 光标位于引用结尾后 ctrl+b 偶尔会失效
range = cloneRange;
// 会导致 protyle.toolbar.range 和 range 不一致,先在有问题的地方重置一下 https://github.com/siyuan-note/siyuan/issues/10933
focusByRange(cloneRange);
protyle.toolbar.range = cloneRange;
protyle.wysiwyg.preventKeyup = true;
}
if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&

View file

@ -387,6 +387,8 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran
// 需先移除 removeElement否则 side 会选中 removeElement
removeElement.remove();
focusBlock(previousLastElement, undefined, false);
// https://github.com/siyuan-note/siyuan/issues/13254
undoOperations.splice(0, 1);
} else {
const previousLastEditElement = getContenteditableElement(previousLastElement);
if (editableElement && (editableElement.textContent !== "" || editableElement.querySelector(".emoji"))) {

View file

@ -1121,7 +1121,6 @@ export const transaction = (protyle: IProtyle, doOperations: IOperation[], undoO
protyle.transactionTime - time < Constants.TIMEOUT_INPUT) {
needDebounce = true;
}
protyle.wysiwyg.lastHTMLs = {};
if (undoOperations) {
if (window.siyuan.config.fileTree.openFilesUseCurrentTab && protyle.model) {
protyle.model.headElement.classList.remove("item--unupdate");

View file

@ -51,6 +51,7 @@ import {addClearButton} from "../util/addClearButton";
import {checkFold} from "../util/noRelyPCFunction";
import {getUnRefList, openSearchUnRef, unRefMoreMenu} from "./unRef";
import {getDefaultType} from "./getDefault";
import {searchMarkRender} from "../protyle/render/searchMarkRender";
export const toggleReplaceHistory = (searchElement: Element) => {
const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
@ -1159,6 +1160,28 @@ const renderNextSearchMark = (options: {
edit: Protyle,
target: Element,
}) => {
const contentRect = options.edit.protyle.contentElement.getBoundingClientRect();
if (CSS.highlights) {
options.edit.protyle.highlight.markHL.clear();
options.edit.protyle.highlight.mark.clear();
options.edit.protyle.highlight.rangeIndex++;
if (options.edit.protyle.highlight.rangeIndex >= options.edit.protyle.highlight.ranges.length) {
options.edit.protyle.highlight.rangeIndex = 0;
}
let rangeTop;
options.edit.protyle.highlight.ranges.forEach((item, index) => {
if (options.edit.protyle.highlight.rangeIndex === index) {
options.edit.protyle.highlight.markHL.add(item);
rangeTop = item.getBoundingClientRect().top;
} else {
options.edit.protyle.highlight.mark.add(item);
}
});
if (typeof rangeTop === "number") {
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + rangeTop - contentRect.top - contentRect.height / 2;
}
return;
}
let matchElement;
const allMatchElements = Array.from(options.edit.protyle.wysiwyg.element.querySelectorAll(`div[data-node-id="${options.id}"] span[data-type~="search-mark"]`));
allMatchElements.find((item, itemIndex) => {
@ -1173,7 +1196,6 @@ const renderNextSearchMark = (options: {
}
if (matchElement) {
matchElement.classList.add("search-mark--hl");
const contentRect = options.edit.protyle.contentElement.getBoundingClientRect();
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + matchElement.getBoundingClientRect().top - contentRect.top - contentRect.height / 2;
}
};
@ -1209,18 +1231,23 @@ export const getArticle = (options: {
updateReadonly: true,
data: getResponse,
protyle: options.edit.protyle,
action: zoomIn ? [Constants.CB_GET_ALL, Constants.CB_GET_HTML] : [Constants.CB_GET_HL, Constants.CB_GET_HTML],
action: zoomIn ? [Constants.CB_GET_ALL, Constants.CB_GET_HTML] : [Constants.CB_GET_HTML],
});
const matchElement = options.edit.protyle.wysiwyg.element.querySelector(`div[data-node-id="${options.id}"] span[data-type~="search-mark"]`);
if (matchElement) {
matchElement.classList.add("search-mark--hl");
const contentRect = options.edit.protyle.contentElement.getBoundingClientRect();
const matchRectTop = matchElement.getBoundingClientRect().top; // 需前置,否则代码高亮后会移除该元素
setTimeout(() => {
// 等待 scrollCenter 定位后再滚动
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + matchRectTop - contentRect.top - contentRect.height / 2;
});
const matchElements = options.edit.protyle.wysiwyg.element.querySelectorAll(`div[data-node-id="${options.id}"] span[data-type~="search-mark"]`);
if (matchElements.length === 0) {
return;
}
const contentRect = options.edit.protyle.contentElement.getBoundingClientRect();
let matchRectTop: number;
if (CSS.highlights) {
options.edit.protyle.highlight.rangeIndex = 0;
searchMarkRender(options.edit.protyle, matchElements);
matchRectTop = options.edit.protyle.highlight.ranges[0].getBoundingClientRect().top;
} else {
matchElements[0].classList.add("search-mark--hl");
matchRectTop = matchElements[0].getBoundingClientRect().top;
}
options.edit.protyle.contentElement.scrollTop = options.edit.protyle.contentElement.scrollTop + matchRectTop - contentRect.top - contentRect.height / 2;
});
});
});

View file

@ -107,8 +107,23 @@ type TAVFilterOperator =
| "Is relative to today"
| "Is true"
| "Is false"
declare module "blueimp-md5"
declare class Highlight {
constructor(...range: Range[]);
add(range: Range): void
clear(): void
forEach(callbackfn: (value: Range, key: number) => void): void;
}
declare namespace CSS {
const highlights: Map<string, Highlight>;
}
interface Window {
echarts: {
init(element: HTMLElement, theme?: string, options?: {
@ -178,6 +193,15 @@ interface Window {
readClipboard(): string
getBlockURL(): string
}
JSHarmony: {
openExternal(url: string): void
changeStatusBarColor(color: string, mode: number): void
writeClipboard(text: string): void
writeHTMLClipboard(text: string, html: string): void
writeImageClipboard(uri: string): void
readClipboard(): string
getBlockURL(): string
}
Protyle: import("../protyle/method").default

View file

@ -482,6 +482,12 @@ interface IProtyleOptions {
}
interface IProtyle {
highlight: {
mark: Highlight
markHL: Highlight
ranges: Range[]
rangeIndex: 0
}
getInstance: () => import("../protyle").Protyle,
observerLoad?: ResizeObserver,
observer?: ResizeObserver,

View file

@ -205,9 +205,9 @@ export const setInlineStyle = (set = true) => {
.b3-typography code:not(.hljs), .protyle-wysiwyg span[data-type~=code] { font-variant-ligatures: ${window.siyuan.config.editor.codeLigatures ? "normal" : "none"} }
.li > .protyle-action {height:${height + 8}px;line-height: ${height + 8}px}
.protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h1, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h2, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h3, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h4, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h5, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h6 {line-height:${height + 8}px;}
.protyle-wysiwyg [data-node-id].li > .protyle-action:after {height: ${window.siyuan.config.editor.fontSize}px;width: ${window.siyuan.config.editor.fontSize}px;margin:-${window.siyuan.config.editor.fontSize / 2}px 0 0 -${window.siyuan.config.editor.fontSize / 2}px}
.protyle-wysiwyg [data-node-id].li > .protyle-action::after {height: ${window.siyuan.config.editor.fontSize}px;width: ${window.siyuan.config.editor.fontSize}px;margin:-${window.siyuan.config.editor.fontSize / 2}px 0 0 -${window.siyuan.config.editor.fontSize / 2}px}
.protyle-wysiwyg [data-node-id].li > .protyle-action svg {height: ${Math.max(14, window.siyuan.config.editor.fontSize - 8)}px}
.protyle-wysiwyg [data-node-id].li:before {height: calc(100% - ${height + 8}px);top:${(height + 8)}px}
.protyle-wysiwyg [data-node-id].li::before {height: calc(100% - ${height + 8}px);top:${(height + 8)}px}
.protyle-wysiwyg [data-node-id] [spellcheck] {min-height:${height}px;}
.protyle-wysiwyg .p,
.protyle-wysiwyg .code-block .hljs,
@ -342,8 +342,10 @@ const updateMobileTheme = (OSTheme: string) => {
}
if (isInIOS()) {
window.webkit.messageHandlers.changeStatusBar.postMessage((backgroundColor || (mode === 0 ? "#fff" : "#1e1e1e")) + " " + mode);
} else if (isInAndroid() || isInHarmony()) {
} else if (isInAndroid()) {
window.JSAndroid.changeStatusBarColor(backgroundColor, mode);
} else if ( isInHarmony()) {
window.JSHarmony.changeStatusBarColor(backgroundColor, mode);
}
}, 500); // 移动端需要加载完才可以获取到颜色
}

View file

@ -1,5 +1,5 @@
import {hasClosestBlock, hasClosestByAttribute} from "../protyle/util/hasClosest";
import {getEditorRange} from "../protyle/util/selection";
import {focusByRange, getEditorRange} from "../protyle/util/selection";
export const bgFade = (element: Element) => {
element.classList.add("protyle-wysiwyg--hl");
@ -56,7 +56,8 @@ export const scrollCenter = (protyle: IProtyle, nodeElement?: Element, top = fal
(blockElement.querySelector(".av__row--header").getAttribute("style")?.indexOf("transform") > -1 || blockElement.querySelector(".av__row--footer").getAttribute("style")?.indexOf("transform") > -1)) {
return;
}
// 撤销时 br 插入删除会导致 rang 被修改 https://github.com/siyuan-note/siyuan/issues/12679
const cloneRange = range.cloneRange();
const br2Element = document.createElement("br");
range.insertNode(br2Element);
const editorElement = protyle.contentElement;
@ -71,6 +72,7 @@ export const scrollCenter = (protyle: IProtyle, nodeElement?: Element, top = fal
editorElement.scroll({top: scrollTop, behavior});
}
br2Element.remove();
focusByRange(cloneRange);
return;
}
}

View file

@ -416,7 +416,7 @@
const {ipcRenderer} = require('electron')
ipcRenderer.send('siyuan-quit', window.location.port)
} catch (e) {
if ((window.webkit && window.webkit.messageHandlers) || window.JSAndroid) {
if ((window.webkit && window.webkit.messageHandlers) || window.JSAndroid || window.JSHarmony) {
window.location.href = 'siyuan://api/system/exit'
} else {
window.location.reload()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ const INITIAL_CACHED_RESOURCES = [
"/stage/icon-large.png",
"/stage/icon.png",
"/stage/loading-pure.svg",
"/stage/build/fonts/JetBrainsMono-Regular.woff",
"/stage/build/fonts/JetBrainsMono-Regular.woff2",
"/stage/protyle/js/lute/lute.min.js",
"/stage/protyle/js/protyle-html.js"
];

View file

@ -76,10 +76,10 @@ module.exports = (env, argv) => {
],
},
{
test: /\.woff$/,
test: /\.woff2$/,
type: "asset/resource",
generator: {
filename: "../fonts/JetBrainsMono-Regular.woff",
filename: "../fonts/JetBrainsMono-Regular.woff2",
},
},
{

View file

@ -79,10 +79,10 @@ module.exports = (env, argv) => {
],
},
{
test: /\.woff$/,
test: /\.woff2$/,
type: "asset/resource",
generator: {
filename: "../fonts/JetBrainsMono-Regular.woff",
filename: "../fonts/JetBrainsMono-Regular.woff2",
},
},
{

Some files were not shown because too many files have changed in this diff Show more