Skip to content

Commit e6f2664

Browse files
committed
✨ Fancy fonts for tasks
1 parent c97bcf0 commit e6f2664

File tree

4 files changed

+227
-84
lines changed

4 files changed

+227
-84
lines changed

src/@types/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface TaskSnippetConfig extends SnippetConfig {
1616
hideColorPicker?: boolean;
1717
styleUncheckedTask?: boolean;
1818
uncheckedTask?: TaskSettings;
19+
cssFontImport?: string;
1920
}
2021

2122
export interface TaskSettings {
@@ -43,6 +44,7 @@ export interface CheckboxSettings extends ColoredElement, FormattedElement {
4344

4445
export interface TaskListItemSettings extends ColoredElement, FormattedElement {
4546
syncTaskColor?: boolean;
47+
syncTaskFont?: boolean;
4648
}
4749

4850
export interface ColoredElement {
@@ -61,6 +63,7 @@ export interface FormattedElement {
6163
export interface TextSettings {
6264
bold?: boolean;
6365
italics?: boolean;
66+
font?: string;
6467
fontSize?: number;
6568
fontWeight?: number;
6669
strikethrough?: boolean;

src/snippetor-CreateCheckboxesModal.ts

Lines changed: 195 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Modal,
66
Setting,
77
SliderComponent,
8+
TextComponent,
89
ToggleComponent,
910
} from "obsidian";
1011
import type {
@@ -51,6 +52,7 @@ class CreateCheckboxesModal extends Modal {
5152
elements: ConstructedElements;
5253
helper: ModalHelper;
5354
snippetor: Snippetor;
55+
style: HTMLStyleElement;
5456

5557
constructor(
5658
app: App,
@@ -77,6 +79,11 @@ class CreateCheckboxesModal extends Modal {
7779

7880
onOpen(): void {
7981
this.titleEl.createSpan({ text: "Snippetor: Tasks" });
82+
this.style = document.createElement("style");
83+
this.style.replaceChildren(
84+
document.createTextNode(this.cfg.cssFontImport)
85+
);
86+
document.getElementsByTagName("head")[0].appendChild(this.style);
8087

8188
const content = this.contentEl.createDiv(
8289
"snippetor-content markdown-preview-view"
@@ -151,9 +158,27 @@ class CreateCheckboxesModal extends Modal {
151158
}
152159
});
153160
});
161+
162+
new Setting(content)
163+
.setName("Import (CSS) additional fonts")
164+
.setDesc(
165+
"Cut/paste a CSS @import statement to add an additional font to your snippet. Only do this if you don't have the font you want already installed from another snippet."
166+
)
167+
.addTextArea((t) =>
168+
t.setValue(this.cfg.cssFontImport).onChange((v) => {
169+
const redraw = v != this.cfg.cssFontImport;
170+
this.cfg.cssFontImport = v;
171+
if (redraw) {
172+
this.style.replaceChildren(
173+
document.createTextNode(this.cfg.cssFontImport)
174+
);
175+
}
176+
})
177+
);
154178
}
155179

156180
finish(): void {
181+
document.getElementsByTagName("head")[0].removeChild(this.style);
157182
this.contentEl.empty();
158183
this.elements = {};
159184
// do not persist the transient cache
@@ -299,7 +324,13 @@ class CreateCheckboxesModal extends Modal {
299324
textEl.createSpan({ text: "example", cls: "example" });
300325

301326
// Section for settings
302-
const settings = itemEl.createDiv("snippetor-settings");
327+
const settings = itemEl.createEl("div", {
328+
cls: "snippetor-settings",
329+
attr: {
330+
style: `font-weight: normal; text-decoration: none; font-size: ${this.elements.defaultFontSize}px`,
331+
},
332+
});
333+
303334
this.drawSettings(taskSettings, settings);
304335

305336
// Twistie: toggle display of more settings
@@ -464,6 +495,25 @@ class CreateCheckboxesModal extends Modal {
464495
},
465496
});
466497

498+
const chkboxGroup = settings.createSpan("snippetor-group decorated");
499+
chkboxGroup.createEl("label", {
500+
text: "Font:",
501+
attr: { for: `checkbox-font-${i}` },
502+
});
503+
new TextComponent(chkboxGroup)
504+
.setValue(
505+
ts.checkbox.format === undefined ||
506+
ts.checkbox.format.font === undefined
507+
? ""
508+
: ts.checkbox.format.font
509+
)
510+
.onChange((v) => {
511+
this.snippetor.initialize(ts, "checkbox", "format");
512+
ts.checkbox.format.font = v;
513+
this.applySettingsToCheckbox(ts);
514+
})
515+
.inputEl.addClass("snippetor-font-setting");
516+
467517
const sizeGroup = settings.createSpan("snippetor-group decorated");
468518
const sizeLabel = sizeGroup.createEl("label", {
469519
text: `[${initalValue}] size: `,
@@ -555,30 +605,109 @@ class CreateCheckboxesModal extends Modal {
555605
text: "Text: ",
556606
});
557607

558-
// Checkbox text formatting
608+
// List item text formatting
559609
const styleGroup = settings.createSpan("snippetor-group");
560610
this.helper
561-
.createBoldButton(styleGroup, ts.checkbox, (enabled) => {
611+
.createBoldButton(styleGroup, ts.li, (enabled) => {
562612
this.snippetor.initialize(ts, "li", "format");
563613
ts.li.format.bold = enabled;
564614
this.applySettingsToListItem(ts);
565615
})
566616
.buttonEl.addClass("no-padding");
567617
this.helper
568-
.createItalicButton(styleGroup, ts.checkbox, (enabled) => {
618+
.createItalicButton(styleGroup, ts.li, (enabled) => {
569619
this.snippetor.initialize(ts, "li", "format");
570620
ts.li.format.italics = enabled;
571621
this.applySettingsToListItem(ts);
572622
})
573623
.buttonEl.addClass("no-padding");
574624
this.helper
575-
.createStrikethroughButton(styleGroup, ts.checkbox, (enabled) => {
625+
.createStrikethroughButton(styleGroup, ts.li, (enabled) => {
576626
this.snippetor.initialize(ts, "li", "format");
577627
ts.li.format.strikethrough = enabled;
578628
this.applySettingsToListItem(ts);
579629
})
580630
.buttonEl.addClass("no-padding");
581631

632+
const sizeGroup = settings.createSpan("snippetor-group decorated");
633+
sizeGroup.createEl("label", {
634+
text: `Font size: `,
635+
attr: { for: "size-" + i },
636+
});
637+
const fontSize = new SliderComponent(sizeGroup)
638+
.setValue(
639+
ts.li.format === undefined ||
640+
ts.li.format.fontSize === undefined
641+
? this.elements.defaultFontSize
642+
: ts.li.format.fontSize
643+
)
644+
.setLimits(6, 30, 1)
645+
.setDynamicTooltip()
646+
.onChange((v) => {
647+
this.snippetor.initialize(ts, "li", "format");
648+
ts.li.format.fontSize = v;
649+
this.applySettingsToListItem(ts);
650+
});
651+
fontSize.sliderEl.name = "size-" + i;
652+
new ExtraButtonComponent(sizeGroup)
653+
.setIcon("reset")
654+
.setTooltip("Reset font size to default")
655+
.onClick(async () => {
656+
fontSize.setValue(this.elements.defaultFontSize);
657+
Reflect.deleteProperty(ts.checkbox.format, "fontSize");
658+
this.applySettingsToListItem(ts);
659+
})
660+
.extraSettingsEl.addClass("no-padding");
661+
662+
// Sync List item font?
663+
const useTaskFont = "🔡 = ☑︎";
664+
const useTextFont = "🔡 ≠ ☑︎";
665+
const textFontMode = this.helper.createToggleButton(
666+
settings,
667+
ts.li.syncTaskFont,
668+
(enabled) => {
669+
ts.li.syncTaskFont = enabled;
670+
textFontMode.buttonEl.setText(
671+
ts.li.syncTaskFont ? useTaskFont : useTextFont
672+
);
673+
this.applySettingsToListItem(ts);
674+
if (ts.li.syncTaskFont) {
675+
settings.addClass("hide-text-font");
676+
} else {
677+
settings.removeClass("hide-text-font");
678+
}
679+
}
680+
);
681+
textFontMode.buttonEl.addClass("toggle-sync-font");
682+
textFontMode.setTooltip("Toggle: Sync text with task font");
683+
textFontMode.setButtonText(
684+
ts.li.syncTaskFont ? useTaskFont : useTextFont
685+
);
686+
if (ts.li.syncTaskFont) {
687+
settings.addClass("hide-text-font");
688+
}
689+
// List Item font
690+
const liGroup = settings.createSpan(
691+
"snippetor-group decorated li-font"
692+
);
693+
liGroup.createEl("label", {
694+
text: "Font:",
695+
attr: { for: `li-font-${i}` },
696+
});
697+
this.snippetor.initialize(ts, "li", "format");
698+
const textFont = new TextComponent(liGroup)
699+
.setValue(
700+
ts.li.format === undefined || ts.li.format.font === undefined
701+
? ""
702+
: ts.li.format.font
703+
)
704+
.onChange((v) => {
705+
ts.li.format.font = v;
706+
this.applySettingsToListItem(ts);
707+
});
708+
textFont.inputEl.addClass("snippetor-font-setting");
709+
710+
// Sync List item color?
582711
const useTaskColors = "🎨 = ☑︎";
583712
const useTextColors = "🎨 ≠ ☑︎";
584713
const textColorMode = this.helper.createToggleButton(
@@ -602,10 +731,9 @@ class CreateCheckboxesModal extends Modal {
602731
textColorMode.setButtonText(
603732
ts.li.syncTaskColor ? useTaskColors : useTextColors
604733
);
605-
settings.addClass(
606-
ts.li.syncTaskColor ? "hide-text-colors" : "show-text-colors"
607-
);
608-
734+
if (ts.li.syncTaskColor) {
735+
settings.addClass("hide-text-colors");
736+
}
609737
// the checkbox foreground
610738
this.foregroundColorPicker(
611739
settings,
@@ -778,55 +906,77 @@ class CreateCheckboxesModal extends Modal {
778906
this.setListItemColors(taskSettings);
779907

780908
textEl.style.removeProperty("--snippetor-decoration");
781-
textEl.style.removeProperty("--snippetor-weight");
909+
textEl.style.removeProperty("--snippetor-font");
910+
textEl.style.removeProperty("--snippetor-font-size");
782911
textEl.style.removeProperty("--snippetor-text-style");
912+
textEl.style.removeProperty("--snippetor-weight");
913+
914+
let decoration = "none";
915+
let font = "var(--font-text)";
916+
let fontSize = this.elements.defaultFontSize + "px";
917+
let style = "normal";
918+
let weight = "500";
783919

784920
if (taskSettings.li.format) {
785921
if (taskSettings.li.format.strikethrough) {
786-
textEl.style.setProperty(
787-
"--snippetor-decoration",
788-
"line-through"
789-
);
790-
} else {
791-
textEl.style.setProperty("--snippetor-decoration", "none");
922+
decoration = "line-through";
792923
}
793924
if (taskSettings.li.format.bold) {
794-
textEl.style.setProperty("--snippetor-weight", "700");
795-
} else {
796-
textEl.style.setProperty("--snippetor-weight", "500");
925+
weight = "700";
797926
}
798927
if (taskSettings.li.format.italics) {
799-
textEl.style.setProperty("--snippetor-text-style", "italic");
800-
} else {
801-
textEl.style.setProperty("--snippetor-text-style", "normal");
928+
style = "italic";
802929
}
803-
} else {
804-
textEl.style.setProperty("--snippetor-decoration", "none");
805-
textEl.style.setProperty("--snippetor-weight", "500");
806-
textEl.style.setProperty("--snippetor-text-style", "normal");
807930
}
931+
932+
if (
933+
taskSettings.li.syncTaskFont &&
934+
taskSettings.checkbox.format &&
935+
taskSettings.checkbox.format.font
936+
) {
937+
font = taskSettings.checkbox.format.font;
938+
} else if (taskSettings.li.format && taskSettings.li.format.font) {
939+
font = taskSettings.li.format.font;
940+
}
941+
942+
if (taskSettings.li.format && taskSettings.li.format.fontSize) {
943+
fontSize = taskSettings.li.format.fontSize + "px";
944+
}
945+
946+
textEl.style.setProperty("--snippetor-decoration", decoration);
947+
textEl.style.setProperty("--snippetor-font", font);
948+
textEl.style.setProperty("--snippetor-font-size", fontSize);
949+
textEl.style.setProperty("--snippetor-text-style", style);
950+
textEl.style.setProperty("--snippetor-weight", weight);
808951
}
809952

810953
applySettingsToCheckbox(ts: TaskSettings): void {
811954
const checkbox = ts.cache.checkboxEl;
812955
checkbox.removeAttribute("data");
813956

957+
checkbox.style.removeProperty("--snippetor-font");
958+
checkbox.style.removeProperty("--snippetor-font-size");
959+
checkbox.style.removeProperty("--snippetor-left");
960+
checkbox.style.removeProperty("--snippetor-top");
961+
814962
const data = ts.checkbox.readModeData
815963
? ts.checkbox.readModeData
816964
: ts.data;
817965
checkbox.setAttribute("data", data);
818966

967+
let font = "var(--font-monospace)";
968+
let fontSize = this.elements.defaultFontSize + "px";
969+
970+
if (ts.checkbox.format && ts.checkbox.format.font) {
971+
font = ts.checkbox.format.font;
972+
}
819973
if (ts.checkbox.format && ts.checkbox.format.fontSize) {
820-
checkbox.style.setProperty(
821-
"--snippetor-font-size",
822-
ts.checkbox.format.fontSize + "px"
823-
);
824-
} else {
825-
checkbox.style.setProperty(
826-
"--snippetor-font-size",
827-
this.elements.defaultFontSize + "px"
828-
);
974+
fontSize = ts.checkbox.format.fontSize + "px";
829975
}
976+
977+
checkbox.style.setProperty("--snippetor-font", font);
978+
checkbox.style.setProperty("--snippetor-font-size", fontSize);
979+
830980
checkbox.style.setProperty(
831981
"--snippetor-top",
832982
(ts.checkbox.top ? ts.checkbox.top : 0) + "px"
@@ -835,6 +985,7 @@ class CreateCheckboxesModal extends Modal {
835985
"--snippetor-left",
836986
(ts.checkbox.left ? ts.checkbox.left : 0) + "px"
837987
);
988+
838989
checkbox.style.borderRadius =
839990
(this.cfg.borderRadius ? this.cfg.borderRadius : 0) + "%";
840991

@@ -876,29 +1027,16 @@ class CreateCheckboxesModal extends Modal {
8761027
checkboxEl.style.removeProperty("--snippetor-bg-color");
8771028
checkboxEl.style.removeProperty("--snippetor-border-color");
8781029

879-
if (fgColor === "inherit") {
880-
checkboxEl.style.setProperty(
881-
"--snippetor-fg-color",
882-
"var(--text-normal)"
883-
);
884-
} else {
885-
checkboxEl.style.setProperty("--snippetor-fg-color", fgColor);
886-
}
887-
888-
if (bgColor === "transparent") {
889-
checkboxEl.style.setProperty("--snippetor-bg-color", "transparent");
890-
} else {
891-
checkboxEl.style.setProperty("--snippetor-bg-color", bgColor);
892-
}
1030+
checkboxEl.style.setProperty(
1031+
"--snippetor-fg-color",
1032+
fgColor === "inherit" ? "var(--text-normal)" : fgColor
1033+
);
1034+
checkboxEl.style.setProperty("--snippetor-bg-color", bgColor);
8931035

894-
if (taskSettings.checkbox.hideBorder) {
895-
checkboxEl.style.setProperty(
896-
"--snippetor-border-color",
897-
"transparent"
898-
);
899-
} else {
900-
checkboxEl.style.setProperty("--snippetor-border-color", fgColor);
901-
}
1036+
checkboxEl.style.setProperty(
1037+
"--snippetor-border-color",
1038+
taskSettings.checkbox.hideBorder ? "transparent" : fgColor
1039+
);
9021040
}
9031041

9041042
verifyDataValue(input: HTMLInputElement) {

0 commit comments

Comments
 (0)