Skip to content

Commit b22931e

Browse files
author
Pseudonium
authored
Merge pull request #155 from Pseudonium/develop
Settings improvement and command
2 parents ce9bf26 + 9a56192 commit b22931e

8 files changed

Lines changed: 134 additions & 83 deletions

File tree

main.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export default class MyPlugin extends Plugin {
156156
new Notice('Scanning vault, check console for details...');
157157
console.info("Checking connection to Anki...")
158158
try {
159-
const test = await AnkiConnect.invoke('modelNames')
159+
await AnkiConnect.invoke('modelNames')
160160
}
161161
catch(e) {
162162
new Notice("Error, couldn't connect to Anki! Check console for error message.")
@@ -209,6 +209,14 @@ export default class MyPlugin extends Plugin {
209209
this.addRibbonIcon('anki', 'Obsidian_to_Anki - Scan Vault', async () => {
210210
await this.scanVault()
211211
})
212+
213+
this.addCommand({
214+
id: 'anki-scan-vault',
215+
name: 'Scan Vault',
216+
callback: async () => {
217+
await this.scanVault()
218+
}
219+
})
212220
}
213221

214222
async onunload() {

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "obsidian-to-anki-plugin",
33
"name": "Obsidian_to_Anki",
4-
"version": "3.3.4",
4+
"version": "3.3.5",
55
"minAppVersion": "0.9.20",
66
"description": "This is an Anki integration plugin! Designed for efficient bulk exporting.",
77
"author": "Pseudonium",

obsidian_to_anki.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,13 @@ def format(note_text, cloze=False):
459459
for code_match in inline_code_matches:
460460
note_text = note_text.replace(
461461
FormatConverter.INLINE_CODE_REPLACE,
462-
html.escape(code_match),
462+
code_match,
463463
1
464464
)
465465
for code_match in display_code_matches:
466466
note_text = note_text.replace(
467467
FormatConverter.DISPLAY_CODE_REPLACE,
468-
html.escape(code_match),
468+
code_match,
469469
1
470470
)
471471
note_text = FormatConverter.markdown_parse(note_text)
@@ -1702,7 +1702,6 @@ def requests_1(self):
17021702
def parse_requests_1(self, requests_1_response, tags):
17031703
response = requests_1_response
17041704
notes_ids = AnkiConnect.parse(response[0])
1705-
print(notes_ids)
17061705
cards_ids = AnkiConnect.parse(response[1])
17071706
for note_ids, file in zip(notes_ids, self.files):
17081707
file.note_ids = [

src/files-manager.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { ParsedSettings } from './interfaces/settings-interface'
33
import { App, TFile, CachedMetadata, FileSystemAdapter, Notice } from 'obsidian'
44
import { AllFile } from './file'
55
import * as AnkiConnect from './anki'
6-
import { bytesToBase64 } from 'byte-base64'
76
import { basename } from 'path'
87

98
interface addNoteResponse {

src/format.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ let converter: Converter = new Converter({
3232
extensions: [showdownHighlight]
3333
})
3434

35+
function escapeHtml(unsafe: string): string {
36+
return unsafe
37+
.replace(/&/g, "&")
38+
.replace(/</g, "&lt;")
39+
.replace(/>/g, "&gt;")
40+
.replace(/"/g, "&quot;")
41+
.replace(/'/g, "&#039;");
42+
}
43+
3544
export class FormatConverter {
3645

3746
file_cache: CachedMetadata
@@ -125,10 +134,10 @@ export class FormatConverter {
125134
return [note_text.replace(regexp, mask), matches]
126135
}
127136

128-
decensor(note_text: string, mask:string, replacements: string[]): string {
137+
decensor(note_text: string, mask:string, replacements: string[], escape: boolean): string {
129138
for (let replacement of replacements) {
130139
note_text = note_text.replace(
131-
mask, replacement
140+
mask, escape ? escapeHtml(replacement) : replacement
132141
)
133142
}
134143
return note_text
@@ -154,10 +163,10 @@ export class FormatConverter {
154163
note_text = this.formatLinks(note_text)
155164
//Special for formatting highlights now, but want to avoid any == in code
156165
note_text = note_text.replace(HIGHLIGHT_REGEXP, String.raw`<mark>$1</mark>`)
157-
note_text = this.decensor(note_text, DISPLAY_CODE_REPLACE, display_code_matches)
158-
note_text = this.decensor(note_text, INLINE_CODE_REPLACE, inline_code_matches)
166+
note_text = this.decensor(note_text, DISPLAY_CODE_REPLACE, display_code_matches, false)
167+
note_text = this.decensor(note_text, INLINE_CODE_REPLACE, inline_code_matches, false)
159168
note_text = converter.makeHtml(note_text)
160-
note_text = this.decensor(note_text, MATH_REPLACE, math_matches).trim()
169+
note_text = this.decensor(note_text, MATH_REPLACE, math_matches, true).trim()
161170
// Remove unnecessary paragraph tag
162171
if (note_text.startsWith(PARA_OPEN) && note_text.endsWith(PARA_CLOSE)) {
163172
note_text = note_text.slice(PARA_OPEN.length, -1 * PARA_CLOSE.length)

src/settings.ts

Lines changed: 101 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,105 @@ const defaultDescs = {
1414

1515
export class SettingsTab extends PluginSettingTab {
1616

17+
setup_custom_regexp(note_type: string, row_cells: HTMLCollection) {
18+
const plugin = (this as any).plugin
19+
let regexp_section = plugin.settings["CUSTOM_REGEXPS"]
20+
let custom_regexp = new Setting(row_cells[1] as HTMLElement)
21+
.addText(
22+
text => text.setValue(
23+
regexp_section.hasOwnProperty(note_type) ? regexp_section[note_type] : ""
24+
)
25+
.onChange((value) => {
26+
plugin.settings["CUSTOM_REGEXPS"][note_type] = value
27+
plugin.saveAllData()
28+
})
29+
)
30+
custom_regexp.settingEl = row_cells[1] as HTMLElement
31+
custom_regexp.infoEl.remove()
32+
custom_regexp.controlEl.className += " anki-center"
33+
}
34+
35+
setup_link_field(note_type: string, row_cells: HTMLCollection) {
36+
const plugin = (this as any).plugin
37+
let link_fields_section = plugin.settings.FILE_LINK_FIELDS
38+
let link_field = new Setting(row_cells[2] as HTMLElement)
39+
.addDropdown(
40+
async dropdown => {
41+
if (!(plugin.fields_dict[note_type])) {
42+
plugin.fields_dict = await plugin.loadFieldsDict()
43+
if (Object.keys(plugin.fields_dict).length != plugin.note_types.length) {
44+
new Notice('Need to connect to Anki to generate fields dictionary...')
45+
try {
46+
plugin.fields_dict = await plugin.generateFieldsDict()
47+
new Notice("Fields dictionary successfully generated!")
48+
}
49+
catch(e) {
50+
new Notice("Couldn't connect to Anki! Check console for error message.")
51+
return
52+
}
53+
}
54+
}
55+
const field_names = plugin.fields_dict[note_type]
56+
for (let field of field_names) {
57+
dropdown.addOption(field, field)
58+
}
59+
dropdown.setValue(
60+
link_fields_section.hasOwnProperty(note_type) ? link_fields_section[note_type] : field_names[0]
61+
)
62+
dropdown.onChange((value) => {
63+
plugin.settings.FILE_LINK_FIELDS[note_type] = value
64+
plugin.saveAllData()
65+
})
66+
}
67+
)
68+
link_field.settingEl = row_cells[2] as HTMLElement
69+
link_field.infoEl.remove()
70+
link_field.controlEl.className += " anki-center"
71+
}
72+
73+
setup_context_field(note_type: string, row_cells: HTMLCollection) {
74+
const plugin = (this as any).plugin
75+
let context_fields_section: Record<string, string> = plugin.settings.CONTEXT_FIELDS
76+
let context_field = new Setting(row_cells[3] as HTMLElement)
77+
.addDropdown(
78+
async dropdown => {
79+
const field_names = plugin.fields_dict[note_type]
80+
for (let field of field_names) {
81+
dropdown.addOption(field, field)
82+
}
83+
dropdown.setValue(
84+
context_fields_section.hasOwnProperty(note_type) ? context_fields_section[note_type] : field_names[0]
85+
)
86+
dropdown.onChange((value) => {
87+
plugin.settings.CONTEXT_FIELDS[note_type] = value
88+
plugin.saveAllData()
89+
})
90+
}
91+
)
92+
context_field.settingEl = row_cells[3] as HTMLElement
93+
context_field.infoEl.remove()
94+
context_field.controlEl.className += " anki-center"
95+
}
96+
1797
setup_table() {
1898
let {containerEl} = this;
1999
const plugin = (this as any).plugin
20100
containerEl.createEl('h3', {text: 'Note type settings'})
101+
let div = containerEl.createEl('div', {cls: "collapsible-item"})
102+
div.innerHTML = `
103+
<div class="collapsible-item-self"><div class="collapsible-item-collapse collapse-icon anki-rotated"><svg viewBox="0 0 100 100" width="8" height="8" class="right-triangle"><path fill="currentColor" stroke="currentColor" d="M94.9,20.8c-1.4-2.5-4.1-4.1-7.1-4.1H12.2c-3,0-5.7,1.6-7.1,4.1c-1.3,2.4-1.2,5.2,0.2,7.6L43.1,88c1.5,2.3,4,3.7,6.9,3.7 s5.4-1.4,6.9-3.7l37.8-59.6C96.1,26,96.2,23.2,94.9,20.8L94.9,20.8z"></path></svg></div><div class="collapsible-item-inner"></div><header >Note Type Table</header></div>
104+
`
105+
div.addEventListener('click', function () {
106+
this.classList.toggle("active")
107+
let icon = this.firstElementChild.firstElementChild as HTMLElement
108+
icon.classList.toggle("anki-rotated")
109+
let content = this.nextElementSibling as HTMLElement
110+
if (content.style.display === "block") {
111+
content.style.display = "none"
112+
} else {
113+
content.style.display = "block"
114+
}
115+
})
21116
let note_type_table = containerEl.createEl('table', {cls: "anki-settings-table"})
22117
let head = note_type_table.createTHead()
23118
let header_row = head.insertRow()
@@ -32,83 +127,18 @@ export class SettingsTab extends PluginSettingTab {
32127
}
33128
for (let note_type of plugin.note_types) {
34129
let row = main_body.insertRow()
130+
35131
row.insertCell()
36132
row.insertCell()
37133
row.insertCell()
38134
row.insertCell()
39-
let row_cells = row.children
40-
row_cells[0].innerHTML = note_type
41135

42-
let regexp_section = plugin.settings["CUSTOM_REGEXPS"]
43-
let custom_regexp = new Setting(row_cells[1] as HTMLElement)
44-
.addText(
45-
text => text.setValue(
46-
regexp_section.hasOwnProperty(note_type) ? regexp_section[note_type] : ""
47-
)
48-
.onChange((value) => {
49-
plugin.settings["CUSTOM_REGEXPS"][note_type] = value
50-
plugin.saveAllData()
51-
})
52-
)
53-
custom_regexp.settingEl = row_cells[1] as HTMLElement
54-
custom_regexp.infoEl.remove()
55-
custom_regexp.controlEl.className += " anki-center"
56-
57-
let link_fields_section = plugin.settings.FILE_LINK_FIELDS
58-
let link_field = new Setting(row_cells[2] as HTMLElement)
59-
.addDropdown(
60-
async dropdown => {
61-
if (!(plugin.fields_dict[note_type])) {
62-
plugin.fields_dict = await plugin.loadFieldsDict()
63-
if (Object.keys(plugin.fields_dict).length != plugin.note_types.length) {
64-
new Notice('Need to connect to Anki to generate fields dictionary...')
65-
try {
66-
plugin.fields_dict = await plugin.generateFieldsDict()
67-
new Notice("Fields dictionary successfully generated!")
68-
}
69-
catch(e) {
70-
new Notice("Couldn't connect to Anki! Check console for error message.")
71-
return
72-
}
73-
}
74-
}
75-
const field_names = plugin.fields_dict[note_type]
76-
for (let field of field_names) {
77-
dropdown.addOption(field, field)
78-
}
79-
dropdown.setValue(
80-
link_fields_section.hasOwnProperty(note_type) ? link_fields_section[note_type] : field_names[0]
81-
)
82-
dropdown.onChange((value) => {
83-
plugin.settings.FILE_LINK_FIELDS[note_type] = value
84-
plugin.saveAllData()
85-
})
86-
}
87-
)
88-
link_field.settingEl = row_cells[2] as HTMLElement
89-
link_field.infoEl.remove()
90-
link_field.controlEl.className += " anki-center"
136+
let row_cells = row.children
91137

92-
let context_fields_section: Record<string, string> = plugin.settings.CONTEXT_FIELDS
93-
let context_field = new Setting(row_cells[3] as HTMLElement)
94-
.addDropdown(
95-
async dropdown => {
96-
const field_names = plugin.fields_dict[note_type]
97-
for (let field of field_names) {
98-
dropdown.addOption(field, field)
99-
}
100-
dropdown.setValue(
101-
context_fields_section.hasOwnProperty(note_type) ? context_fields_section[note_type] : field_names[0]
102-
)
103-
dropdown.onChange((value) => {
104-
plugin.settings.CONTEXT_FIELDS[note_type] = value
105-
plugin.saveAllData()
106-
})
107-
}
108-
)
109-
context_field.settingEl = row_cells[3] as HTMLElement
110-
context_field.infoEl.remove()
111-
context_field.controlEl.className += " anki-center"
138+
row_cells[0].innerHTML = note_type
139+
this.setup_custom_regexp(note_type, row_cells)
140+
this.setup_link_field(note_type, row_cells)
141+
this.setup_context_field(note_type, row_cells)
112142
}
113143
}
114144

styles.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@
55

66
.anki-settings-table {
77
border-collapse: collapse;
8+
display: none;
89
}
910

1011
.anki-center {
1112
margin: auto;
1213
padding: 5px;
1314
padding-top: 30px;
14-
}
15+
}
16+
17+
.anki-rotated {
18+
transform: rotate(-90deg);
19+
}

versions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
{
3+
"3.3.5": "0.9.20",
34
"3.3.4": "0.9.20",
45
"3.3.3": "0.9.20",
56
"3.3.2": "0.9.20",

0 commit comments

Comments
 (0)