dtelenkov hace 6 meses
padre
commit
0486f0dfab

+ 2 - 1
.obsidian/community-plugins.json

@@ -1,5 +1,6 @@
 [
   "habit-calendar",
   "dataview",
-  "obsidian-emoji-toolbar"
+  "obsidian-emoji-toolbar",
+  "fast-text-color"
 ]

+ 8 - 0
.obsidian/hotkeys.json

@@ -6,5 +6,13 @@
       ],
       "key": "E"
     }
+  ],
+  "fast-text-color:change-text-color": [
+    {
+      "modifiers": [
+        "Alt"
+      ],
+      "key": "C"
+    }
   ]
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 191 - 100
.obsidian/plugins/dataview/main.js


+ 2 - 1
.obsidian/plugins/dataview/manifest.json

@@ -1,10 +1,11 @@
 {
   "id": "dataview",
   "name": "Dataview",
-  "version": "0.5.64",
+  "version": "0.5.67",
   "minAppVersion": "0.13.11",
   "description": "Complex data views for the data-obsessed.",
   "author": "Michael Brenan <blacksmithgu@gmail.com>",
   "authorUrl": "https://github.com/blacksmithgu",
+  "helpUrl": "https://blacksmithgu.github.io/obsidian-dataview/",
   "isDesktopOnly": false
 }

+ 454 - 0
.obsidian/plugins/fast-text-color/data.json

@@ -0,0 +1,454 @@
+{
+  "themes": [
+    {
+      "colors": [
+        {
+          "color": "#cb1515",
+          "id": "red",
+          "keybind": "Е",
+          "italic": false,
+          "bold": true,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-red"
+        },
+        {
+          "color": "#2525d4",
+          "id": "blue",
+          "keybind": "B",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-blue"
+        },
+        {
+          "color": "#3cb371",
+          "id": "green",
+          "keybind": "\u001a",
+          "italic": false,
+          "bold": true,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-orange",
+          "className": "ftc-color-default-green"
+        },
+        {
+          "color": "#00ffff",
+          "id": "cyan",
+          "keybind": "C",
+          "italic": false,
+          "bold": true,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-cyan"
+        },
+        {
+          "color": "#ff00ff",
+          "id": "magenta",
+          "keybind": "M",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-magenta"
+        },
+        {
+          "color": "#ffff00",
+          "id": "yellow",
+          "keybind": "Y",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-yellow"
+        },
+        {
+          "color": "#000000",
+          "id": "black",
+          "keybind": "K",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": false,
+          "colorVariable": "--color-base-00",
+          "className": "ftc-color-default-black"
+        }
+      ],
+      "name": "default"
+    },
+    {
+      "colors": [
+        {
+          "color": "#000000",
+          "id": "red",
+          "keybind": "R",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-red",
+          "className": "ftc-color-builtin-red"
+        },
+        {
+          "color": "#000000",
+          "id": "orange",
+          "keybind": "O",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-orange",
+          "className": "ftc-color-builtin-orange"
+        },
+        {
+          "color": "#000000",
+          "id": "yellow",
+          "keybind": "Y",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-yellow",
+          "className": "ftc-color-builtin-yellow"
+        },
+        {
+          "color": "#000000",
+          "id": "green",
+          "keybind": "G",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-green",
+          "className": "ftc-color-builtin-green"
+        },
+        {
+          "color": "#000000",
+          "id": "cyan",
+          "keybind": "C",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-cyan",
+          "className": "ftc-color-builtin-cyan"
+        },
+        {
+          "color": "#000000",
+          "id": "blue",
+          "keybind": "B",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-blue",
+          "className": "ftc-color-builtin-blue"
+        },
+        {
+          "color": "#000000",
+          "id": "purple",
+          "keybind": "P",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-purple",
+          "className": "ftc-color-builtin-purple"
+        },
+        {
+          "color": "#000000",
+          "id": "pink",
+          "keybind": "I",
+          "italic": false,
+          "bold": false,
+          "cap_mode": {
+            "states": [
+              "normal",
+              "all_caps",
+              "small_caps"
+            ],
+            "state": "normal",
+            "index": 0
+          },
+          "line_mode": {
+            "states": [
+              "none",
+              "underline",
+              "overline",
+              "line-through"
+            ],
+            "state": "none",
+            "index": 0
+          },
+          "useCssColorVariable": true,
+          "colorVariable": "--color-pink",
+          "className": "ftc-color-builtin-pink"
+        }
+      ],
+      "name": "builtin"
+    }
+  ],
+  "themeIndex": 0,
+  "version": "3",
+  "interactiveDelimiters": true,
+  "useKeybindings": true,
+  "useNodeRebuilding": false
+}

+ 1261 - 0
.obsidian/plugins/fast-text-color/main.js

@@ -0,0 +1,1261 @@
+/*
+THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
+if you want to view the source, please visit the github repository of this plugin
+*/
+
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __export = (target, all) => {
+  for (var name in all)
+    __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __copyProps = (to, from, except, desc) => {
+  if (from && typeof from === "object" || typeof from === "function") {
+    for (let key of __getOwnPropNames(from))
+      if (!__hasOwnProp.call(to, key) && key !== except)
+        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
+  }
+  return to;
+};
+var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
+
+// main.ts
+var main_exports = {};
+__export(main_exports, {
+  default: () => FastTextColorPlugin
+});
+module.exports = __toCommonJS(main_exports);
+var import_obsidian8 = require("obsidian");
+
+// src/FastTextColorSettings.ts
+var import_obsidian4 = require("obsidian");
+
+// src/color/TextColor.ts
+var TextColor = class {
+  /**
+   * Create a basic Text Color
+   *
+   * @param {string} color - [TODO:description]
+   * @param {string} id - the id or name of the color
+   * @param {string} themeName - the associated theme that this color belongs to
+   * @param {boolean} [italic] - italic text
+   * @param {boolean} [bold] - bold text
+   * @param {number} [cap_mode_index] - the index for the cap mode
+   * @param {number} [line_mode_index] - the index for the line mode
+   * @param {string} [keybind] - the associated keybind
+   * @param {string} colorVariable - the builtin Css color variable that this color uses.
+   */
+  constructor(color, id, themeName, italic = false, bold = false, cap_mode_index = 0, line_mode_index = 0, keybind = "", useCssColorVariable = false, colorVariable = "--color-base-00") {
+    this.color = color;
+    this.id = id;
+    this.keybind = keybind;
+    this.italic = italic;
+    this.bold = bold;
+    this.cap_mode = new CycleState(["normal", "all_caps", "small_caps"], cap_mode_index);
+    this.line_mode = new CycleState(["none", "underline", "overline", "line-through"], line_mode_index);
+    this.useCssColorVariable = useCssColorVariable;
+    this.colorVariable = colorVariable;
+    this.className = `${CSS_COLOR_PREFIX}${themeName}-${this.id}`;
+  }
+  getCssClass() {
+    return `.${CSS_COLOR_PREFIX}${this.id} { 
+				color : ${this.useCssColorVariable ? `var(${this.colorVariable})` : this.color}
+;
+				${this.italic ? "font-style: italic;\n" : ""}
+				${this.bold ? "font-weight: bold;\n" : ""}
+				${this.line_mode.state != "none" ? `text-decoration: ${this.line_mode.state};
+` : ""}
+				${this.cap_mode.state == "all_caps" ? "text-transform: uppercase;\n" : this.cap_mode.state == "small_caps" ? "font-variant: small-caps;\n" : ""}
+				${VAR_COLOR_PREFIX}${this.id} : ${this.color};
+			    }`;
+  }
+  /**
+   * get the inner css of the class for the color.
+   *
+   * @returns {string} the inner css.
+   */
+  getInnerCss() {
+    return `color : ${this.useCssColorVariable ? `var(${this.colorVariable})` : this.color};
+${this.italic ? "font-style: italic;\n" : ""}${this.bold ? "font-weight: bold;\n" : ""}${this.line_mode.state != "none" ? `text-decoration: ${this.line_mode.state};
+` : ""}${this.cap_mode.state == "all_caps" ? "text-transform: uppercase;\n" : this.cap_mode.state == "small_caps" ? "font-variant: small-caps;\n" : ""}`;
+  }
+  getCssInlineStyle() {
+    return `color : ${this.useCssColorVariable ? `var(${this.colorVariable})` : this.color}
+;
+				${this.italic ? "font-style: italic;" : ""}
+				${this.bold ? "font-weight: bold;" : ""}
+				${this.line_mode.state != "none" ? `text-decoration: ${this.line_mode.state};` : ""}
+				${this.cap_mode.state == "all_caps" ? "text-transform: uppercase;" : this.cap_mode.state == "small_caps" ? "font-variant: small-caps;" : ""}
+				`;
+  }
+};
+var CycleState = class {
+  constructor(states, index = 0) {
+    this.states = states;
+    if (states.length <= 0) {
+      this.state = "error";
+      return;
+    }
+    this.state = this.states[index];
+    this.index = index;
+  }
+  cycle() {
+    this.index = (this.index + 1) % this.states.length;
+    this.state = this.states[this.index];
+  }
+};
+
+// src/color/TextColorTheme.ts
+var TextColorTheme = class {
+  constructor(name, colors) {
+    this.colors = colors;
+    this.name = name;
+  }
+};
+
+// src/utils/ConfirmationModal.ts
+var import_obsidian = require("obsidian");
+var ConfirmationModal = class extends import_obsidian.Modal {
+  constructor(app, message, heading) {
+    super(app);
+    this.message = message;
+    this.heading = heading;
+    this.confirmed = false;
+    this.finished = false;
+  }
+  onOpen() {
+    const { contentEl } = this;
+    contentEl.createEl("h1", { text: this.heading });
+    contentEl.createDiv({ text: this.message });
+    new import_obsidian.Setting(contentEl).addButton((btn) => btn.setButtonText("OK").setCta().onClick(() => {
+      this.finished = true;
+      this.confirmed = true;
+    })).addButton((btn) => btn.setButtonText("Cancel").setCta().onClick(() => {
+      this.finished = true;
+    }));
+  }
+  onClose() {
+    let { contentEl } = this;
+    contentEl.empty();
+  }
+};
+async function confirmByModal(app, message = "", heading = "") {
+  let modal = new ConfirmationModal(app, message != "" ? message : "Are you sure?", heading != "" ? heading : "Confirm");
+  modal.open();
+  while (!modal.finished) {
+    await sleep(16);
+  }
+  let result = modal.confirmed;
+  modal.close();
+  return result;
+}
+
+// src/utils/CreateNewThemeModal.ts
+var import_obsidian2 = require("obsidian");
+var CreateNewThemeModal = class extends import_obsidian2.Modal {
+  constructor(app, settings) {
+    super(app);
+    this.settings = settings;
+    this.name = "newTheme";
+  }
+  onOpen() {
+    const { contentEl } = this;
+    contentEl.createEl("h1", { text: "Create new theme" });
+    new import_obsidian2.Setting(contentEl).setName(this.name).addText((txt) => {
+      txt.setValue(this.name).setPlaceholder("Theme name").onChange((value) => {
+        this.name = value;
+        this.evalNameErrors();
+      });
+    });
+    this.errorDiv = contentEl.createDiv();
+    this.errorDiv.addClass("ftc-theme-name-error");
+    new import_obsidian2.Setting(contentEl).addButton((btn) => {
+      btn.setButtonText("create").onClick((evt) => {
+        if (!this.evalNameErrors()) {
+          return;
+        }
+        addTheme(this.settings, this.name, DEFAULT_COLORS);
+        this.doOnSuccess();
+        this.close();
+      });
+    }).addButton((btn) => {
+      btn.setButtonText("cancel").onClick((evt) => {
+        this.close();
+      });
+    });
+  }
+  onClose() {
+    let { contentEl } = this;
+    contentEl.empty();
+  }
+  onSuccess(callback) {
+    this.doOnSuccess = callback;
+  }
+  evalNameErrors() {
+    if (this.settings.themes.some((theme) => {
+      return theme.name == this.name;
+    })) {
+      this.errorDiv.innerText = "a theme with this name already exists.";
+      return false;
+    }
+    if (this.name == "") {
+      this.errorDiv.innerText = "name can not be empty.";
+      return false;
+    }
+    this.errorDiv.innerText = "";
+    return true;
+  }
+};
+
+// src/utils/KeyBindModal.ts
+var import_obsidian3 = require("obsidian");
+var KeyBindModal = class extends import_obsidian3.Modal {
+  constructor(app) {
+    super(app);
+    this.finished = false;
+  }
+  onOpen() {
+    const { contentEl } = this;
+    contentEl.createEl("h1", { text: "Press any key" });
+    this.handler = this.handleKeypress.bind(this);
+    window.addEventListener("keypress", this.handler);
+    new import_obsidian3.Setting(contentEl).addButton((btn) => {
+      btn.setButtonText("Cancel").onClick((evt) => {
+        this.close();
+      });
+    });
+  }
+  onClose() {
+    let { contentEl } = this;
+    contentEl.empty();
+  }
+  handleKeypress(evt) {
+    this.result = evt.key.toUpperCase();
+    this.modalEl.removeEventListener("keypress", this.handler, true);
+    this.finished = true;
+  }
+};
+async function getKeyBindWithModal(app) {
+  let modal = new KeyBindModal(app);
+  modal.open();
+  while (!modal.finished) {
+    await sleep(16);
+  }
+  let result = modal.result;
+  modal.close();
+  return result;
+}
+
+// src/FastTextColorSettings.ts
+var CSS_COLOR_PREFIX = "ftc-color-";
+var VAR_COLOR_PREFIX = "--ftc-color-";
+var SETTINGS_VERSION = "3";
+var BUILTIN_COLORS = [
+  new TextColor("#000000", "red", "builtin", false, false, 0, 0, "R", true, "--color-red"),
+  new TextColor("#000000", "orange", "builtin", false, false, 0, 0, "O", true, "--color-orange"),
+  new TextColor("#000000", "yellow", "builtin", false, false, 0, 0, "Y", true, "--color-yellow"),
+  new TextColor("#000000", "green", "builtin", false, false, 0, 0, "G", true, "--color-green"),
+  new TextColor("#000000", "cyan", "builtin", false, false, 0, 0, "C", true, "--color-cyan"),
+  new TextColor("#000000", "blue", "builtin", false, false, 0, 0, "B", true, "--color-blue"),
+  new TextColor("#000000", "purple", "builtin", false, false, 0, 0, "P", true, "--color-purple"),
+  new TextColor("#000000", "pink", "builtin", false, false, 0, 0, "I", true, "--color-pink")
+];
+var DEFAULT_COLORS = [
+  new TextColor("#ff0000", `red`, "default", false, false, 0, 0, "R"),
+  new TextColor("#00ff00", `green`, "default", false, false, 0, 0, "G"),
+  new TextColor("#0000ff", `blue`, "default", false, false, 0, 0, "B"),
+  new TextColor("#00ffff", `cyan`, "default", false, false, 0, 0, "C"),
+  new TextColor("#ff00ff", `magenta`, "default", false, false, 0, 0, "M"),
+  new TextColor("#ffff00", `yellow`, "default", false, false, 0, 0, "Y"),
+  new TextColor("#000000", `black`, "default", false, false, 0, 0, "K")
+];
+var DEFAULT_SETTINGS = {
+  themes: [new TextColorTheme("default", DEFAULT_COLORS), new TextColorTheme("builtin", BUILTIN_COLORS)],
+  themeIndex: 0,
+  version: SETTINGS_VERSION,
+  interactiveDelimiters: true,
+  useKeybindings: true,
+  useNodeRebuilding: false
+};
+function getColors(settings, index = -1) {
+  if (index == -1) {
+    index = settings.themeIndex;
+  }
+  return settings.themes[index].colors;
+}
+function getCurrentTheme(settings, index = -1) {
+  if (index == -1) {
+    index = settings.themeIndex;
+  }
+  return settings.themes[index];
+}
+function addTheme(settings, name, colors = DEFAULT_COLORS) {
+  settings.themes.push(new TextColorTheme(name, colors));
+}
+function deleteTheme(settings, index = -1) {
+  if (settings.themes.length <= 1) {
+    return;
+  }
+  if (index == -1) {
+    index = settings.themeIndex;
+  }
+  settings.themes.remove(settings.themes[index]);
+  if (index <= settings.themeIndex) {
+    settings.themeIndex = Math.max(settings.themeIndex - 1, 0);
+  }
+}
+function updateSettings(settings) {
+  switch (settings.version) {
+    case "1":
+    case "2":
+      const colors = settings.colors.map((color) => {
+        return new TextColor(color.color, color.id, "default", color.italic, color.bold, color.cap_mode.index, color.line_mode.index, color.keybind);
+      });
+      const outSettings = {
+        themes: [new TextColorTheme("default", colors)],
+        themeIndex: 0,
+        version: SETTINGS_VERSION,
+        interactiveDelimiters: settings.interactiveDelimiters,
+        useKeybindings: true,
+        useNodeRebuilding: false
+      };
+      return outSettings;
+    default:
+      console.log(`There is not update method for Settings Version ${settings.version}!
+${settings}`);
+      return DEFAULT_SETTINGS;
+  }
+}
+var FastTextColorPluginSettingTab = class extends import_obsidian4.PluginSettingTab {
+  constructor(app, plugin) {
+    super(app, plugin);
+    this.plugin = plugin;
+    this.newId = "";
+    this.editThemeIndex = plugin.settings.themeIndex;
+  }
+  display() {
+    const { containerEl } = this;
+    const { settings } = this.plugin;
+    containerEl.empty();
+    new import_obsidian4.Setting(containerEl).setName("Colors").setHeading();
+    new import_obsidian4.Setting(containerEl).setName("Set active theme").setDesc("Set global active theme.").addDropdown((dd) => {
+      let count2 = 0;
+      settings.themes.forEach((theme) => {
+        dd.addOption(count2.toString(), theme.name);
+        count2++;
+      });
+      dd.setValue(settings.themeIndex.toString());
+      dd.onChange((value) => {
+        settings.themeIndex = +value;
+        this.plugin.saveSettings();
+        this.plugin.setCssVariables();
+        this.display();
+      });
+    });
+    new import_obsidian4.Setting(containerEl).setName("Edit themes").setDesc("Add new themes or edit existings ones.").setClass("ftc-settings-theme-header").addDropdown((dd) => {
+      let count2 = 0;
+      settings.themes.forEach((theme) => {
+        dd.addOption(count2.toString(), theme.name);
+        count2++;
+      });
+      dd.setValue(this.editThemeIndex.toString());
+      dd.onChange((value) => {
+        this.editThemeIndex = +value;
+        this.display();
+      });
+    }).addButton((btn) => {
+      btn.setIcon("plus").setTooltip("add new Theme").onClick((evt) => {
+        const modal = new CreateNewThemeModal(this.app, settings);
+        modal.onSuccess(() => {
+          this.plugin.saveSettings();
+          this.display();
+        });
+        modal.open();
+      });
+    }).addButton((btn) => {
+      btn.setIcon("trash").setTooltip("delete theme").onClick(async (evt) => {
+        if (await confirmByModal(this.app, `Are you sure?
+ The theme ${settings.themes[settings.themeIndex].name} will no longer be available. `)) {
+          deleteTheme(settings, this.editThemeIndex);
+          this.editThemeIndex = 0;
+          this.plugin.saveSettings();
+          this.display();
+        }
+      });
+    });
+    const themeColorsEl = containerEl.createDiv();
+    themeColorsEl.addClass("ftc-theme-colors");
+    let count = 1;
+    getColors(settings, this.editThemeIndex).forEach((color) => {
+      this.createColorSetting(themeColorsEl, color, count);
+      count++;
+    });
+    new import_obsidian4.Setting(containerEl).setName("Add new color to theme").setClass("ftc-settings-theme-footer").addText((txt) => {
+      txt.setValue(this.newId == "" ? (getColors(settings).length + 1).toString() : this.newId).onChange((value) => {
+        this.newId = value;
+      });
+    }).addButton((btn) => {
+      btn.setButtonText("+").onClick(async (evt) => {
+        let colors = getColors(settings, this.editThemeIndex);
+        if (colors.some((tColor) => {
+          return tColor.id == this.newId;
+        })) {
+          new import_obsidian4.Notice(`color with id ${this.newId} already exists!`);
+        }
+        let newColorName = this.newId == "" ? (colors.length + 1).toString() : this.newId;
+        colors.push(new TextColor("#ffffff", newColorName, getCurrentTheme(settings, this.editThemeIndex).name));
+        await this.plugin.saveSettings();
+        this.display();
+      });
+    });
+    new import_obsidian4.Setting(containerEl).setName("Other").setHeading();
+    new import_obsidian4.Setting(containerEl).setName("Interactive delimiters").setDesc("Use interactive delimiter to change colors inside the editor.").addToggle((tgl) => {
+      tgl.setValue(settings.interactiveDelimiters).onChange(async (value) => {
+        settings.interactiveDelimiters = value;
+        await this.plugin.saveSettings();
+      });
+    });
+    new import_obsidian4.Setting(containerEl).setName("Use keybindings and colormenu").setDesc("If enabled will allow you to use keybindings to activate colors from a custom colormenu.").addToggle((tgl) => {
+      tgl.setValue(settings.useKeybindings).onChange(async (value) => {
+        settings.useKeybindings = value;
+        await this.plugin.saveSettings();
+      });
+    });
+  }
+  /**
+   * Create a color row in the theme view 
+   *
+   * @param {HTMLElement} container - the root container of the element.
+   * @param {TextColor} tColor - the color to be used for display
+   * @param {number} count - the index of the color
+   */
+  createColorSetting(container, tColor, count) {
+    let nameFragment = new DocumentFragment();
+    let nameDiv = nameFragment.createDiv();
+    nameDiv.addClass("ftc-name-div");
+    const key = nameDiv.createDiv();
+    key.innerText = `${tColor.id}`;
+    const exampletext = nameDiv.createDiv();
+    exampletext.setAttr("style", tColor.getCssInlineStyle());
+    exampletext.innerText = `~={${tColor.id}}This is colored text=~`;
+    let saveAndApply = async () => {
+      await this.plugin.saveSettings();
+      this.plugin.setCssVariables();
+      exampletext.setAttr("style", tColor.getCssInlineStyle());
+    };
+    const setting = new import_obsidian4.Setting(container).setName(nameFragment).setClass("ftc-settings-item").addButton((btn) => {
+      btn.setButtonText(`${tColor.keybind}`.toUpperCase()).setTooltip("set keybinding").setClass("key-indicator").onClick(async (evt) => {
+        tColor.keybind = await getKeyBindWithModal(this.app);
+        btn.setButtonText(`${tColor.keybind}`);
+        await this.plugin.saveSettings();
+        this.plugin.setCssVariables();
+      });
+    }).addButton((btn) => {
+      btn.setButtonText("B").setTooltip("Bold").setClass("ftc-format-item").onClick(async (evt) => {
+        tColor.bold = !tColor.bold;
+        btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.bold);
+        btn.buttonEl.setCssStyles({ fontWeight: tColor.bold ? "bold" : "normal" });
+        saveAndApply();
+      });
+      btn.buttonEl.addClass("ftc-format-left");
+      btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.bold);
+      btn.buttonEl.setCssStyles({ fontWeight: tColor.bold ? "bold" : "normal" });
+    }).addButton((btn) => {
+      btn.setButtonText("I").setTooltip("Italic").setClass("ftc-format-item").onClick(async (evt) => {
+        tColor.italic = !tColor.italic;
+        btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.italic);
+        btn.buttonEl.setCssStyles({ fontStyle: tColor.italic ? "italic" : "normal" });
+        saveAndApply();
+      });
+      btn.buttonEl.addClass("ftc-format-middle");
+      btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.italic);
+      btn.buttonEl.setCssStyles({ fontStyle: tColor.italic ? "italic" : "normal" });
+    }).addButton((btn) => {
+      btn.setButtonText("U").setTooltip("Lining").setClass("ftc-format-item").onClick(async (evt) => {
+        tColor.line_mode.cycle();
+        btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.line_mode.state != "none");
+        btn.buttonEl.setCssStyles({ textDecoration: tColor.line_mode.state });
+        saveAndApply();
+      });
+      btn.buttonEl.addClass("ftc-format-middle");
+      btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.line_mode.state != "none");
+      btn.buttonEl.setCssStyles({ textDecoration: tColor.line_mode.state });
+    }).addButton((btn) => {
+      btn.setButtonText("Tt").setTooltip("Capitalization").setClass("ftc-format-item").onClick(async (evt) => {
+        tColor.cap_mode.cycle();
+        btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.cap_mode.state != "normal");
+        btn.buttonEl.toggleClass("ftc-uppercase", tColor.cap_mode.state == "all_caps");
+        btn.buttonEl.toggleClass("ftc-small-caps", tColor.cap_mode.state == "small_caps");
+        await this.plugin.saveSettings();
+        this.plugin.setCssVariables();
+        exampletext.setAttr("style", tColor.getCssInlineStyle());
+      });
+      btn.buttonEl.addClass("ftc-format-right");
+      btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.cap_mode.state != "normal");
+      btn.buttonEl.setCssStyles(
+        tColor.cap_mode.state == "all_caps" ? { textTransform: "uppercase" } : tColor.cap_mode.state == "small_caps" ? { fontVariant: "small_caps" } : {}
+      );
+    });
+    if (tColor.useCssColorVariable) {
+      setting.addDropdown((dd) => {
+        dd.addOptions({
+          "--color-red": "red",
+          "--color-orange": "orange",
+          "--color-yellow": "yellow",
+          "--color-green": "green",
+          "--color-cyan": "cyan",
+          "--color-blue": "blue",
+          "--color-purple": "purple",
+          "--color-pink": "pink"
+          // "--color-blue" : "50",
+          // "--color-blue" : "60",
+          // "--color-blue" : "70",
+          // "--color-base-100": "100",
+        }).setValue(tColor.colorVariable).onChange((value) => {
+          tColor.colorVariable = value;
+          saveAndApply();
+        });
+      });
+    } else {
+      setting.addColorPicker((cb) => {
+        cb.setValue(tColor.color).onChange(async (value) => {
+          tColor.color = value;
+          saveAndApply();
+        });
+      });
+    }
+    setting.addButton((btn) => {
+      btn.setTooltip("use builtin obsidian colors").setClass("ftc-format-item-small").onClick(async (evt) => {
+        tColor.useCssColorVariable = !tColor.useCssColorVariable;
+        btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.useCssColorVariable);
+        saveAndApply();
+        this.display();
+      });
+      btn.buttonEl.toggleClass("ftc-format-item-enabled", tColor.useCssColorVariable);
+    }).addButton((btn) => {
+      btn.setIcon("chevron-up").setTooltip("move item up").setClass("ftc-move-btn-left").onClick(async (evt) => {
+        moveColor(count - 1, -1, this.plugin.settings);
+        await this.plugin.saveSettings();
+        this.display();
+      });
+    }).addButton((btn) => {
+      btn.setIcon("chevron-down").setTooltip("move item down").setClass("ftc-move-btn-right").onClick(async (evt) => {
+        moveColor(count - 1, 1, this.plugin.settings);
+        await this.plugin.saveSettings();
+        this.display();
+      });
+    }).addButton((btn) => {
+      btn.setIcon("trash").setTooltip("delete color").setClass("ftc-move-btn-right").onClick(async (evt) => {
+        if (await confirmByModal(
+          this.app,
+          `Colored section whith the id "${tColor.id}" will no longer be colored until you add another color with that id.`,
+          `Delete color: ${tColor.id}`
+        )) {
+          getColors(this.plugin.settings).remove(tColor);
+        }
+        await this.plugin.saveSettings();
+        this.display();
+      });
+    });
+  }
+};
+function moveColor(index, direction, settings) {
+  if (direction < 0 && index == 0 || direction > 0 && index == getColors(settings).length - 1) {
+    return;
+  }
+  let temp = getColors(settings)[index + direction];
+  getColors(settings)[index + direction] = getColors(settings)[index];
+  getColors(settings)[index] = temp;
+}
+
+// src/rendering/TextColorViewPlugin.ts
+var import_state3 = require("@codemirror/state");
+var import_view3 = require("@codemirror/view");
+
+// src/rendering/TextColorStateField.ts
+var import_state = require("@codemirror/state");
+
+// src/rendering/language/textColorLanguageParser.js
+var import_lr = require("@lezer/lr");
+var parser = import_lr.LRParser.deserialize({
+  version: 14,
+  states: "%dQQOPOOOcOQO'#C_OqOPO'#C^O!SOPO'#CmOOOO'#Co'#CoQQOPOOOOOO'#Ca'#CaO!eOQO,59UOOOO,58y,58yOOOO,59U,59UO!pOQO'#C_OOOO'#Cp'#CpO!xOPO'#CeOOOO'#Cf'#CfO#ZOPO'#CqO#lOPO'#CdO#lOPO'#CdO#zOPO'#C^OOOO,58x,58xOOOO'#Cr'#CrO$SOPO,59XOOOO,59X,59XOOOO-E6m-E6mOOOO,58{,58{OOOO1G.p1G.pO$eOQO'#CaOOOO-E6n-E6nOOOO,59],59]OOOO-E6o-E6oOOOO,59O,59OO#lOPO,59OOOOO-E6p-E6pOOOO1G.s1G.sOOOO1G.j1G.j",
+  stateData: "$m~OSPOZSO[SObROhSO~OUVOVUO_XO`XO~OSYOZ]O[]O]]OhZO~OSPOZcO[cObeOhcO~OVgO_hO`hO~OUiOVUO~OhZOSXXZXX[XX]XX~OhZOSeXZeX[eX]eX~OSYOZ]O[]O]]O~OSYOhZO~OSPOZcO[cObpOhcO~OVgO~OSZ~",
+  goto: "#lgPPhwP!UPP!Y!^!ePPP!oPP!wP!{#R#Z#fSSOTY^Q_`anTcRdWQORTdZaQ_`anTWPYTbQaS`QaRk^QXQSm_`RqnSSOTTcRdTSOTQTORfTU[Q^aRj[S_QaSl_nRn`QdRRod",
+  nodeNames: "\u26A0 TextColor Expression TcLeft LMarker Description Color InnerMarker TcRight Text REnd RMarker ENDLN EOF Unfinished ColorEOF ColorWS CodeSection CODE",
+  maxTerm: 24,
+  skippedNodes: [0],
+  repeatNodeCount: 4,
+  tokenData: "%f~RcXY!^YZ!c]^!^pq!^qr!^rs!^s!_!^!_!`!p!`#O!^#O#P!}#P#S!^#S#T$q#T#r!^#r#s$v#s;'S!^;'S;=`%Z<%l~!^~O!^~~%a~!cOh~~!hPh~YZ!k~!pO[~~!uPh~#r#s!x~!}OZ~~#SXh~rs!^!P!Q!^#O#P!^#U#V!^#Y#Z!^#b#c!^#f#g!^#h#i!^#i#j#o~#rR!Q![#{!c!i#{#T#Z#{~$OR!Q![$X!c!i$X#T#Z$X~$[R!Q![$e!c!i$e#T#Z$e~$hR!Q![!^!c!i!^#T#Z!^~$vOb~~${Ph~!_!`%O~%RP#o#p%U~%ZOS~~%^P;=`<%l!^~%fO]~",
+  tokenizers: [1, new import_lr.LocalTokenGroup("!X~R[X^wpqw#q#r|#y#zw$f$gw#BY#BZw$IS$I_w$I|$JOw$JT$JUw$KV$KWw&FU&FVw~~!R~|O`~~!ROV~~!WO_~~", 54, 6)],
+  topRules: { "TextColor": [0, 1] },
+  tokenPrec: 164
+});
+
+// src/rendering/language/textColorLanguage.ts
+var import_language = require("@codemirror/language");
+var textColorLanguage = import_language.LRLanguage.define({
+  name: "textColorLanguage",
+  parser: parser.configure({})
+});
+
+// src/rendering/TextColorStateField.ts
+var import_common = require("@lezer/common");
+var import_language2 = require("@codemirror/language");
+var textColorParserField = import_state.StateField.define({
+  create(state) {
+    const parsedTree = textColorLanguage.parser.parse(state.doc.toString());
+    return {
+      tree: parsedTree,
+      fragment: import_common.TreeFragment.addTree(parsedTree)
+    };
+  },
+  update(value, transaction) {
+    if (!transaction.docChanged) {
+      return value;
+    }
+    const changed_ranges = [];
+    transaction.changes.iterChangedRanges(
+      (from, to, fromB, toB) => changed_ranges.push({ fromA: from, toA: to, fromB, toB })
+    );
+    let fragments = import_common.TreeFragment.applyChanges(value.fragment, changed_ranges);
+    const tree = textColorLanguage.parser.parse(new import_language2.DocInput(transaction.state.doc), fragments);
+    fragments = import_common.TreeFragment.addTree(tree, fragments);
+    return { tree, fragment: fragments };
+  }
+});
+
+// src/widgets/MarkerWidget.ts
+var import_view = require("@codemirror/view");
+var MarkerWidget = class extends import_view.WidgetType {
+  constructor() {
+    super();
+  }
+  toDOM(view) {
+    const div = document.createElement("span");
+    return div;
+  }
+};
+
+// src/widgets/ColorWidget.ts
+var import_view2 = require("@codemirror/view");
+var import_obsidian5 = require("obsidian");
+
+// src/SettingsFacet.ts
+var import_state2 = require("@codemirror/state");
+var settingsFacet = import_state2.Facet.define(
+  {
+    combine: (inputs) => {
+      if (inputs.length <= 0) {
+        return DEFAULT_SETTINGS;
+      }
+      return inputs[inputs.length - 1];
+    }
+  }
+);
+
+// src/widgets/ColorWidget.ts
+var ColorWidget = class extends import_view2.WidgetType {
+  constructor(id, from, to, expressionTo, themeName) {
+    super();
+    this.id = id;
+    this.from = from;
+    this.to = to;
+    this.expressionTo = expressionTo;
+    this.themeName = themeName;
+  }
+  toDOM(view) {
+    const div = document.createElement("span");
+    div.addClass(`${CSS_COLOR_PREFIX}${this.themeName}-${this.id}`);
+    div.addClass("ftc-color-delimiter");
+    div.innerText = "\u2B24";
+    const settings = view.state.facet(settingsFacet);
+    div.onclick = (event) => {
+      if (this.menu != null) {
+      }
+      view.dispatch({
+        selection: {
+          anchor: this.from,
+          head: this.to
+        }
+      });
+    };
+    div.onmouseover = (event) => {
+      if (this.menu != null) {
+        return;
+      }
+      this.menu = new import_obsidian5.Menu();
+      getColors(settings).forEach((tColor) => {
+        this.menu.addItem((item) => {
+          item.setTitle(tColor.id).onClick((evt) => {
+            view.dispatch({
+              changes: {
+                from: this.from,
+                to: this.to,
+                insert: tColor.id
+              }
+            });
+          }).setIcon("palette");
+          item.dom.addClass(tColor.className);
+        });
+      });
+      this.menu.addItem((item) => {
+        item.setTitle("Remove").setIcon("ban").onClick((evt) => {
+          view.dispatch({
+            changes: [
+              {
+                from: this.from - 3,
+                to: this.to + 1,
+                insert: ""
+              },
+              {
+                from: this.expressionTo - 2,
+                to: this.expressionTo,
+                insert: ""
+              }
+            ]
+          });
+        });
+      });
+      const rect = div.getBoundingClientRect();
+      this.menu.showAtPosition({ x: rect.left, y: rect.bottom });
+    };
+    return div;
+  }
+};
+
+// src/rendering/TextColorViewPlugin.ts
+var import_obsidian6 = require("obsidian");
+var TextColorViewPlugin = class {
+  constructor(view) {
+    this.decorations = this.buildDecorations(view);
+  }
+  update(update) {
+    var _a;
+    if (!isLivePreview(update.state)) {
+      if (this.decorations.size > 0) {
+        this.decorations = new import_state3.RangeSetBuilder().finish();
+      }
+      this.notLivePreview = true;
+      return;
+    }
+    if (this.notLivePreview) {
+      this.notLivePreview = false;
+      this.decorations = this.buildDecorations(update.view);
+      return;
+    }
+    const selectionChanged = update.selectionSet && !((_a = update.view.plugin(import_obsidian6.livePreviewState)) == null ? void 0 : _a.mousedown);
+    if (update.docChanged || update.viewportChanged || selectionChanged) {
+      this.decorations = this.buildDecorations(update.view);
+    }
+  }
+  destroy() {
+  }
+  buildDecorations(view) {
+    const builder = new import_state3.RangeSetBuilder();
+    for (let { from, to } of view.visibleRanges) {
+      view.state.field(textColorParserField).tree.iterate({
+        from,
+        to,
+        enter(node) {
+          if (node.type.name == "TextColor") {
+            return true;
+          }
+          if (node.type.name != "Expression") {
+            return false;
+          }
+          handleExpression(node, builder, view.state);
+          return false;
+        }
+      });
+    }
+    return builder.finish();
+  }
+};
+function isLivePreview(state) {
+  return state.field(import_obsidian6.editorLivePreviewField).valueOf();
+}
+function handleExpression(ExpressionNode, builder, state) {
+  const from = ExpressionNode.from;
+  let colorStack = [];
+  const stateFrom = state.selection.main.from;
+  const stateTo = state.selection.main.to;
+  const settings = state.facet(settingsFacet);
+  const frontmatterTheme = getThemeFromFrontmatter(state);
+  const themeName = frontmatterTheme == "" ? getCurrentTheme(settings).name : frontmatterTheme;
+  ExpressionNode.node.toTree().iterate({
+    // toTree allocates a tree, this might be a point of optimization. TODO optimization
+    enter(node) {
+      var _a, _b, _c, _d;
+      switch (node.type.name) {
+        case "RMarker":
+          let inside = (_a = colorStack.pop()) == null ? void 0 : _a.inside;
+          if (inside) {
+            return true;
+          }
+          builder.add(node.from + from, node.to + from, import_view3.Decoration.replace({ widget: new MarkerWidget(), block: false }));
+          return true;
+        case "EOF":
+        case "ENDLN":
+          (_b = colorStack.pop()) == null ? void 0 : _b.inside;
+          return true;
+        case "TcLeft":
+          if ((_c = colorStack.last()) == null ? void 0 : _c.inside) {
+            return true;
+          }
+          builder.add(node.from + from, node.to + from, import_view3.Decoration.replace({ widget: new MarkerWidget(), block: false }));
+          return true;
+        case "Color":
+          let color = state.sliceDoc(from + node.from, from + node.to);
+          colorStack[colorStack.length - 1].color = color;
+          if (((_d = colorStack.last()) == null ? void 0 : _d.inside) && settings.interactiveDelimiters) {
+            if (stateFrom <= from + node.to && stateTo >= from + node.from) {
+              return true;
+            }
+            const widget = new ColorWidget(color, node.from + from, node.to + from, ExpressionNode.to, themeName);
+            builder.add(node.from + from, node.to + from, import_view3.Decoration.replace({ widget, block: false }));
+          }
+          return true;
+        case "Text":
+          builder.add(node.from + from, node.to + from, import_view3.Decoration.mark({ class: `${CSS_COLOR_PREFIX}${themeName}-${colorStack[colorStack.length - 1].color}` }));
+          return false;
+        case "Expression":
+          colorStack.push({ color: "", inside: stateFrom <= from + node.to && stateTo >= from + node.from });
+          return true;
+        default:
+          break;
+      }
+    }
+  });
+}
+function getThemeFromFrontmatter(state) {
+  var _a;
+  const editorInfo = state.field(import_obsidian6.editorInfoField);
+  const file = editorInfo.file;
+  if (!file) {
+    return "";
+  }
+  const frontmatter = (_a = editorInfo.app.metadataCache.getFileCache(file)) == null ? void 0 : _a.frontmatter;
+  if (!frontmatter) {
+    return "";
+  }
+  const name = frontmatter["ftcTheme"];
+  return name ? name : "";
+}
+var pluginSpec = {
+  decorations: (value) => value.decorations
+};
+var textColorViewPlugin = import_view3.ViewPlugin.fromClass(
+  TextColorViewPlugin,
+  pluginSpec
+);
+
+// src/utils/regularExpressions.ts
+var PREFIX = /\~\=\{\S+\}/g;
+var SUFFIX = /\=\~/g;
+
+// src/rendering/TextColorPostProcessor.ts
+var textColorPostProcessor = (el, context, settings) => {
+  if (!el.innerHTML.match(PREFIX)) {
+    return;
+  }
+  let themeName = context.frontmatter ? context.frontmatter["ftcTheme"] : null;
+  themeName = themeName ? themeName : getCurrentTheme(settings).name;
+  const emergencyCopy = el.cloneNode(true);
+  try {
+    rebuildNode(el, themeName);
+  } catch (e) {
+    console.error(`fatal in rebuildNode: ${e}`);
+    el.childNodes.forEach((c) => {
+      var _a;
+      (_a = c.parentNode) == null ? void 0 : _a.removeChild(c);
+    });
+    emergencyCopy.childNodes.forEach((c) => {
+      el.appendChild(c);
+    });
+  }
+  return;
+};
+function rebuildNode(node, themeName, level = 0, nodeStack = []) {
+  var _a, _b, _c, _d;
+  if (node.nodeName == "CODE") {
+    return node;
+  }
+  if (level > 1e3) {
+    console.error("fatal: reached depth 1000 in recursion");
+  }
+  let lastLength = node.childNodes.length;
+  for (let i = 0; i < node.childNodes.length; i++) {
+    lastLength = node.childNodes.length;
+    let childNode = node.childNodes.item(i);
+    const text = childNode.nodeValue;
+    if (nodeStack.last() != void 0 && nodeStack.last() != childNode && !(childNode.compareDocumentPosition(nodeStack.last()) & Node.DOCUMENT_POSITION_CONTAINS)) {
+      (_a = childNode.parentNode) == null ? void 0 : _a.removeChild(childNode);
+      (_b = nodeStack.last()) == null ? void 0 : _b.appendChild(childNode);
+      if (lastLength > node.childNodes.length) {
+        i -= lastLength - node.childNodes.length;
+      }
+    }
+    if (childNode.nodeType != Node.TEXT_NODE) {
+      childNode = rebuildNode(childNode, themeName, level + 1, nodeStack);
+      continue;
+    }
+    if (text == null || text == "") {
+      continue;
+    }
+    let prefix = GetFirstMatch(text, PREFIX);
+    let suffix = GetFirstMatch(text, SUFFIX);
+    if (prefix == null && suffix == null) {
+      continue;
+    }
+    let nextPrefixPosition = prefix != null ? prefix.index : Number.POSITIVE_INFINITY;
+    let nextSuffixPosition = suffix != null ? suffix.index : Number.POSITIVE_INFINITY;
+    if (nextPrefixPosition == nextSuffixPosition) {
+      console.error(`fatal: nextPrefixPosition and nextSuffixPosition are the same but not infinity!!: ${nextPrefixPosition}`);
+      return node;
+    }
+    if (nextPrefixPosition < nextSuffixPosition) {
+      prefix = prefix;
+      let textBeforeDelim2 = text.slice(0, nextPrefixPosition);
+      let textAfterDelim2 = text.slice(prefix.end);
+      let prefixContent = prefix.value;
+      let color = prefixContent.slice(3, prefixContent.length - 1);
+      let colorSpan = document.createElement("span");
+      colorSpan.addClass(`${CSS_COLOR_PREFIX}${themeName}-${color}`);
+      childNode.nodeValue = textBeforeDelim2;
+      (_c = childNode.parentNode) == null ? void 0 : _c.insertAfter(colorSpan, childNode);
+      let newNode2 = document.createTextNode(textAfterDelim2);
+      colorSpan.appendChild(newNode2);
+      nodeStack.push(colorSpan);
+      continue;
+    }
+    let textBeforeDelim = text.slice(0, nextSuffixPosition);
+    let textAfterDelim = text.slice(suffix.end);
+    childNode.nodeValue = textBeforeDelim;
+    let prevNode = nodeStack.pop();
+    let newNode = document.createTextNode(textAfterDelim);
+    (_d = prevNode.parentNode) == null ? void 0 : _d.insertAfter(newNode, prevNode);
+    continue;
+  }
+  return node;
+}
+function GetFirstMatch(text, regex) {
+  const regexCopy = new RegExp(regex.source, "g");
+  const matches = [];
+  let m = regexCopy.exec(text);
+  if (m !== null) {
+    return {
+      index: m.index,
+      value: m[0],
+      end: m.index + m[0].length
+    };
+  }
+  return null;
+}
+
+// main.ts
+var import_state4 = require("@codemirror/state");
+var import_view4 = require("@codemirror/view");
+
+// src/color/TextColorFunctions.ts
+function applyColor(tColor, editor) {
+  let prefix = `~={${tColor.id}}`;
+  let suffix = `=~`;
+  if (!editor.somethingSelected()) {
+    editor.replaceSelection(prefix);
+    let pos = editor.getCursor();
+    editor.replaceSelection(suffix);
+    editor.setCursor(pos);
+    return;
+  }
+  let selected = editor.getSelection();
+  let coloredText = `${prefix}${selected}${suffix}`;
+  editor.replaceSelection(coloredText);
+}
+function removeColor(editor, view) {
+  var _a, _b;
+  const tree = view.state.field(textColorParserField).tree;
+  let node = tree.resolveInner(view.state.selection.main.head);
+  while (node.parent != null) {
+    if (node.type.name != "Expression") {
+      node = node.parent;
+      continue;
+    }
+    const TcLeft = node.getChild("TcLeft");
+    const Rmarker = (_b = (_a = node.getChild("TcRight")) == null ? void 0 : _a.getChild("REnd")) == null ? void 0 : _b.getChild("RMarker");
+    view.dispatch({
+      changes: [
+        {
+          from: TcLeft ? TcLeft.from : 0,
+          to: TcLeft ? TcLeft.to : 0,
+          insert: ""
+        },
+        {
+          from: Rmarker ? Rmarker.from : 0,
+          to: Rmarker ? Rmarker.to : 0,
+          insert: ""
+        }
+      ]
+    });
+    return;
+  }
+  return;
+}
+
+// src/utils/ColorSuggestModal.ts
+var import_obsidian7 = require("obsidian");
+var ColorSuggestModal = class extends import_obsidian7.SuggestModal {
+  constructor(app, colors, editor) {
+    super(app);
+    this.colors = colors;
+    this.editor = editor;
+  }
+  getSuggestions(query) {
+    return this.colors.filter((tColor) => tColor.id.startsWith(query) || tColor.keybind == query);
+  }
+  renderSuggestion(tColor, el) {
+    let div = el.createDiv();
+    div.innerText = tColor.id;
+    div.setAttr("style", tColor.getCssInlineStyle());
+  }
+  onChooseSuggestion(tColor, evt) {
+    applyColor(tColor, this.editor);
+  }
+};
+
+// main.ts
+var MAX_MENU_ITEMS = 10;
+var FastTextColorPlugin = class extends import_obsidian8.Plugin {
+  async onload() {
+    await this.loadSettings();
+    this.registerEditorExtension(textColorParserField);
+    this.registerEditorExtension(textColorViewPlugin);
+    this.registerMarkdownPostProcessor((el, ctx) => {
+      textColorPostProcessor(el, ctx, this.settings);
+    }, -1e3);
+    this.registerMarkdownPostProcessor((el, ctx) => {
+      textColorPostProcessor(el, ctx, this.settings);
+    }, 1e3);
+    this.settingsCompartment = new import_state4.Compartment();
+    this.settingsExtension = this.settingsCompartment.of(settingsFacet.of(this.settings));
+    this.registerEditorExtension(this.settingsExtension);
+    this.registerEditorExtension(
+      import_state4.Prec.high(
+        import_view4.keymap.of([
+          {
+            key: "Tab",
+            run: (editorView) => this.jumpOut(editorView)
+          }
+        ])
+      )
+    );
+    this.addCommand({
+      id: "change-text-color",
+      name: "Change text color",
+      editorCallback: (editor) => {
+        this.openColorMenu(editor);
+      }
+    });
+    this.addCommand({
+      id: "remove-text-color",
+      name: "Remove text color",
+      editorCallback: (editor, view) => {
+        const editorView = view.editor.cm;
+        removeColor(editor, editorView);
+      }
+    });
+    this.registerEvent(
+      this.app.workspace.on("editor-menu", (menu, editor, view) => {
+        if (editor.getSelection() == "") {
+          return;
+        }
+        menu.addItem((item) => {
+          item.setSection("selection").setTitle("Color").setIcon("palette");
+          const submenu = item.setSubmenu();
+          getColors(this.settings).forEach((tColor) => {
+            submenu.addItem((subitem) => {
+              subitem.setTitle(tColor.id).setIcon("circle").onClick((evt) => {
+                applyColor(tColor, editor);
+              });
+              subitem.dom.addClass(tColor.className);
+              subitem.iconEl.addClass(tColor.className);
+            });
+          });
+        });
+      })
+    );
+    this.addSettingTab(new FastTextColorPluginSettingTab(this.app, this));
+    this.setCssVariables();
+  }
+  onunload() {
+    this.styleElement.remove();
+    this.closeColorMenu();
+  }
+  async loadSettings() {
+    const rawSettings = await this.loadData();
+    if (rawSettings && +rawSettings.version < +SETTINGS_VERSION) {
+      console.log("outdated Settings! Trying to update.");
+      this.settings = updateSettings(rawSettings);
+      await this.saveData(this.settings);
+      return;
+    }
+    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
+    for (let j = 0; j < this.settings.themes.length; j++) {
+      const colors = getColors(this.settings, j);
+      for (let i = 0; i < colors.length; i++) {
+        let obj = colors[i];
+        colors[i] = new TextColor(obj.color, obj.id, this.settings.themes[j].name, obj.italic, obj.bold, obj.cap_mode.index, obj.line_mode.index, obj.keybind, obj.useCssColorVariable, obj.colorVariable);
+      }
+    }
+  }
+  async saveSettings() {
+    var _a;
+    await this.saveData(this.settings);
+    const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView);
+    const editorView = (_a = view == null ? void 0 : view.editor) == null ? void 0 : _a.cm;
+    if (editorView == null) {
+      return;
+    }
+    editorView.dispatch({
+      effects: this.settingsCompartment.reconfigure(settingsFacet.of(this.settings))
+    });
+  }
+  // create and open the color menu
+  /**
+   * opens the color menu and pushed the scope onto the keybindings.
+   *
+   * @param {Editor} editor - [TODO:description]
+   */
+  openColorMenu(editor) {
+    var _a;
+    if (!this.settings.useKeybindings) {
+      let modal = new ColorSuggestModal(this.app, getColors(this.settings), editor);
+      modal.open();
+      return;
+    }
+    if (this.colorMenu != null) {
+      return;
+    }
+    this.colorMenu = createDiv();
+    if (!this.colorMenu) {
+      new import_obsidian8.Notice("could not create Colormenu!");
+      return;
+    }
+    let attributes = `bottom: 8.25em; grid-template-columns: ${"1fr ".repeat(getColors(this.settings).length)}`;
+    this.colorMenu.setAttribute("style", attributes);
+    this.colorMenu.setAttribute("id", "fast-color-menu");
+    this.colorMenu.addClass("fast-color-menu");
+    (_a = document.body.querySelector(".mod-vertical.mod-root")) == null ? void 0 : _a.insertAdjacentElement("afterbegin", this.colorMenu);
+    for (let i = 0; i < Math.min(getColors(this.settings).length, MAX_MENU_ITEMS); i++) {
+      this.createColorItem(this.colorMenu, getColors(this.settings)[i], i + 1, editor);
+    }
+    this.colorMenu.setAttribute("style", `left: calc(50% - ${this.colorMenu.offsetWidth}px / 2); ${attributes}`);
+    if (!this.settings.useKeybindings) {
+      return;
+    }
+    this.constructScope(editor);
+    this.app.keymap.pushScope(this.scope);
+  }
+  closeColorMenu() {
+    if (this.colorMenu) {
+      this.colorMenu.remove();
+      this.colorMenu = null;
+    }
+    this.app.keymap.popScope(this.scope);
+  }
+  constructScope(editor) {
+    this.scope = new import_obsidian8.Scope();
+    let { scope } = this;
+    for (let i = 0; i < getColors(this.settings).length; i++) {
+      const tColor = getColors(this.settings)[i];
+      scope.register([], tColor.keybind, (event) => {
+        if (event.isComposing) {
+          return true;
+        }
+        applyColor(tColor, editor);
+        this.closeColorMenu();
+        return false;
+      });
+    }
+    scope.register([], "Escape", (event) => {
+      if (event.isComposing) {
+        return true;
+      }
+      this.closeColorMenu();
+      return false;
+    });
+    scope.register([], "Delete", (event) => {
+      if (event.isComposing) {
+        return true;
+      }
+      this.closeColorMenu();
+      return false;
+    });
+    scope.register([], "Backspace", (event) => {
+      if (event.isComposing) {
+        return true;
+      }
+      this.closeColorMenu();
+      return false;
+    });
+  }
+  /**
+   * Move the cursor behind the next end marker.
+   *
+   * @param {EditorView} editorView
+   * @returns {boolean} true if jump possible.
+   */
+  jumpOut(editorView) {
+    var _a;
+    const state = editorView.state;
+    const tree = state.field(textColorParserField).tree;
+    const editor = (_a = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView)) == null ? void 0 : _a.editor;
+    if (!editor) {
+      return false;
+    }
+    let inner = tree.resolve(state.selection.main.head);
+    if (inner.type.name == "Text" && inner.parent != null) {
+      inner = inner.parent;
+    }
+    if (inner.type.name != "TcRight") {
+      return false;
+    }
+    editor.setCursor(editor.offsetToPos(inner.to));
+    return true;
+  }
+  createColorItem(menu, tColor, counter, editor) {
+    new import_obsidian8.ButtonComponent(menu).setButtonText(`${tColor.keybind}`).setClass("fast-color-menu-item").onClick(() => {
+      let n = new import_obsidian8.Notice("activated color");
+      n.noticeEl.setAttr("style", `background-color: ${tColor.color}`);
+      applyColor(tColor, editor);
+      this.closeColorMenu();
+    }).buttonEl.setAttr("style", `background-color: ${tColor.color}`);
+  }
+  /**
+   * creates the stylesheet needed for the colors in the root of the document.
+   * A different set of classes is created for each theme.
+   *
+   */
+  setCssVariables() {
+    if (!this.styleElement) {
+      const root = document.querySelector(":root");
+      if (!root) {
+        return;
+      }
+      this.styleElement = root.createEl("style");
+      this.styleElement.id = "fast-text-color-stylesheet";
+    }
+    this.styleElement.innerText = "";
+    for (let i = 0; i < this.settings.themes.length; i++) {
+      getColors(this.settings, i).forEach((tColor) => {
+        const theme = this.settings.themes[i];
+        const className = `.${CSS_COLOR_PREFIX}${theme.name}-${tColor.id}`;
+        let cssClass = `${className} {
+${tColor.getInnerCss()}}`;
+        this.styleElement.innerText += cssClass + "\n";
+      });
+    }
+  }
+};

+ 11 - 0
.obsidian/plugins/fast-text-color/manifest.json

@@ -0,0 +1,11 @@
+{
+	"id": "fast-text-color",
+	"name": "Fast Text Color",
+	"version": "1.1.1",
+	"minAppVersion": "0.15.0",
+	"description": "Quickly apply fully integrated text coloring and formatting with a custom syntax and a keyboard-centric interface.",
+	"author": "Leon Holtmeier",
+	"authorUrl": "https://github.com/Superschnizel",
+	"fundingUrl": "https://ko-fi.com/superschnizel",
+	"isDesktopOnly": false
+}

+ 217 - 0
.obsidian/plugins/fast-text-color/styles.css

@@ -0,0 +1,217 @@
+/*
+
+The general structure of the menu is adapted from Chetachi's cMenu https://github.com/chetachiezikeuzor/cMenu-Plugin
+
+*/
+#fast-color-menu {
+  width: auto;
+  height: auto;
+  padding: 3px;
+  display: grid;
+  user-select: none;
+  border-radius: 6px;
+  position: absolute;
+  transition: 200ms ease;
+  min-width: fit-content;
+  justify-content: space-around;
+  z-index: var(--layer-status-bar);
+  /* box-shadow: 0px 3px 32px rgb(31 38 135 / 15%); */
+  border: 1px solid var(--background-modifier-border);
+  background-color: var(--background-primary); }
+  #fast-color-menu .fast-color-menu-item {
+    width: var(--size-4-8);
+    height: var(--size-4-8);
+    color: white;
+    margin: 2px;
+    border: none;
+    display: flex;
+    cursor: pointer;
+    padding: 5px 6px;
+    box-shadow: none;
+    margin-left: 3px;
+    margin-right: 3px;
+    position: relative;
+    border-radius: 3px;
+    font-size: initial !important;
+    background-color: var(--background-primary-alt);
+    text-shadow: 0 0 2px #000; }
+
+.fast-color-menu-item.number-icon {
+  color: white; }
+
+.menu.fast-color-menu {
+  /* min-width: 140px; */
+  /* max-width: 225px; */
+  /* max-height: 180px; */
+  display: flex;
+  width: fit-content;
+  height: fit-content;
+  padding-left: 0em;
+  padding: 0;
+  margin: 0 auto;
+  align-items: center;
+  border-radius: 6px;
+  font-size: 14px;
+  overflow-x: hidden;
+  position: fixed;
+  animation: fade 300ms ease-in-out;
+  background-color: var(--background-primary-alt);
+  box-shadow: 0px 3px 25px rgba(31, 38, 135, 0.1);
+  border: 1px solid var(--background-modifier-border); }
+  .menu.fast-color-menu .menu-item {
+    display: flex;
+    align-items: center;
+    padding: var(--size-4-2);
+    cursor: pointer;
+    font-size: 14px;
+    height: fit-content; }
+    .menu.fast-color-menu .menu-item .menu-item-icon {
+      display: inline-block;
+      width: var(--size-4-5);
+      height: var(--size-4-5);
+      background-color: aqua;
+      border-radius: var(--radius-s);
+      border: var(--border-width) solid var(--background-modifier-border); }
+    .menu.fast-color-menu .menu-item:last-of-type {
+      border-bottom: none; }
+
+/* SETTINGS  */
+.ftc-settings-theme-header {
+  border-radius: var(--radius-l) var(--radius-l) 0 0;
+  border: 2px solid var(--background-modifier-border);
+  border-bottom: none;
+  padding-left: var(--size-4-2);
+  padding-right: var(--size-4-2); }
+
+.ftc-theme-colors {
+  display: flex;
+  background-color: var(--background-primary-alt);
+  flex-direction: column;
+  padding-left: var(--size-4-4);
+  padding-right: var(--size-4-4);
+  padding-top: var(--size-4-2);
+  padding-bottom: var(--size-4-4);
+  border-left: 2px solid var(--background-modifier-border);
+  border-right: 2px solid var(--background-modifier-border);
+  justify-content: space-between; }
+
+.ftc-settings-theme-footer {
+  border-radius: 0 0 var(--radius-l) var(--radius-l);
+  border: 2px solid var(--background-modifier-border);
+  border-top: none;
+  padding-left: var(--size-4-2);
+  padding-right: var(--size-4-2); }
+
+.ftc-settings-item {
+  padding: var(--size-4-2) !important;
+  background-color: var(--background-primary);
+  border-radius: var(--radius-m);
+  border: 1px solid var(--background-modifier-border) !important;
+  margin-top: var(--size-4-2); }
+
+.ftc-format-item {
+  width: var(--size-4-6);
+  height: var(--size-4-6);
+  background-color: var(--interactive-normal); }
+
+.ftc-format-item-enabled {
+  /* width: var(--size-4-6); */
+  /* height: var(--size-4-6); */
+  background-color: var(--interactive-accent) !important; }
+
+.ftc-uppercase {
+  text-transform: uppercase; }
+
+.ftc-small-caps {
+  font-variant: small-caps; }
+
+.ftc-keybind-button {
+  width: var(--size-4-8);
+  height: var(--size-4-8); }
+
+.ftc-format-left {
+  border-radius: var(--radius-s) 0 0 var(--radius-s); }
+
+.ftc-format-middle {
+  border-radius: 0 0 0 0;
+  margin-left: calc(0px - var(--size-4-2)); }
+
+.ftc-format-right {
+  border-radius: 0 var(--radius-s) var(--radius-s) 0;
+  margin-left: calc(0px - var(--size-4-2)); }
+
+.ftc-format-item-small {
+  width: var(--size-4-4);
+  height: var(--size-4-4);
+  padding: 0;
+  /* background-color: var(--interactive-normal); */
+  background-color: red; }
+
+.ftc-format-bold {
+  font-weight: bold; }
+
+.ftc-format-italic {
+  font-style: italic; }
+
+.ftc-format-underline {
+  text-decoration: underline; }
+
+.ftc-format-overline {
+  text-decoration: overline; }
+
+.ftc-format-line-through {
+  text-decoration: line-through; }
+
+.key-indicator {
+  display: flex;
+  width: var(--size-4-8);
+  height: var(--size-4-8);
+  align-items: center;
+  justify-content: center;
+  border: 2px solid var(--background-modifier-border);
+  border-radius: 0.3em; }
+
+.ftc-name-div {
+  display: flex;
+  width: 100%;
+  justify-content: space-between;
+  align-items: center;
+  flex-direction: row; }
+
+.ftc-move-btn-left {
+  width: var(--size-4-6);
+  height: var(--size-4-6);
+  border-radius: var(--radius-s) 0 0 var(--radius-s);
+  padding: 0px; }
+
+.ftc-move-btn-right {
+  width: var(--size-4-6);
+  height: var(--size-4-6);
+  border-radius: 0 var(--radius-s) var(--radius-s) 0;
+  padding: 0px;
+  margin-left: calc(0px - var(--size-4-2)); }
+
+.ftc-theme-name-error {
+  height: var(--size-4-4);
+  width: 100%;
+  text-align: right;
+  color: red;
+  font-size: var(--font-ui-smaller); }
+
+/* color delimiter icon */
+.ftc-color-delimiter {
+  cursor: pointer;
+  padding-left: 2px;
+  padding-right: 2px; }
+
+/* https://github.com/animate-css/animate.css/blob/main/source/fading_entrances/fadeInLeft.css */
+@keyframes fadeInLeft {
+  from {
+    opacity: 0;
+    transform: translate3d(-100%, 0, 0); }
+  to {
+    opacity: 1;
+    transform: translate3d(0, 0, 0); } }
+
+.fadeInLeft {
+  animation-name: fadeInLeft; }

+ 25 - 11
.obsidian/workspace.json

@@ -13,13 +13,26 @@
             "state": {
               "type": "markdown",
               "state": {
-                "file": "hardcore web development/4. Linux.md",
+                "file": "todo/Задачи.md",
+                "mode": "source",
+                "source": false
+              }
+            }
+          },
+          {
+            "id": "0c28a730249ba7fa",
+            "type": "leaf",
+            "state": {
+              "type": "markdown",
+              "state": {
+                "file": "hardcore web development/11. SQL/1.md",
                 "mode": "source",
                 "source": false
               }
             }
           }
-        ]
+        ],
+        "currentTab": 1
       }
     ],
     "direction": "vertical"
@@ -85,7 +98,7 @@
             "state": {
               "type": "backlink",
               "state": {
-                "file": "hardcore web development/4. Linux.md",
+                "file": "hardcore web development/11. SQL/1.md",
                 "collapseAll": false,
                 "extraContext": false,
                 "sortOrder": "alphabetical",
@@ -124,16 +137,20 @@
       "markdown-importer:Импорт Markdown-файлов": false
     }
   },
-  "active": "6332c424f14ec4a2",
+  "active": "0c28a730249ba7fa",
   "lastOpenFiles": [
+    "todo/Задачи.md",
+    "hardcore web development/SQL.md",
+    "hardcore web development/11. SQL/1.md",
+    "hardcore web development/11. SQL",
+    "todo/Счета.md",
+    "todo/Разное.md",
+    "todo/Тренировки и занятия.md",
+    "hardcore web development/4. Linux.md",
     "hardcore web development/5-6-7 Internet.md",
     "linux/linux common.md",
     "linux/server.md",
-    "todo/Задачи.md",
-    "todo/Тренировки и занятия.md",
-    "todo/Счета.md",
     "common.md",
-    "todo/Разное.md",
     "configs/alex_wg.conf",
     "configs/alex_wg.conf.txt",
     "Python/common.md",
@@ -144,7 +161,6 @@
     "configs/dz_wg0.conf",
     "configs/gs_wg0.conf",
     "configs/gw_wg0.conf",
-    "hardcore web development/4. Linux.md",
     "keys/gs_publickey",
     "Greenstar/usb stm32.md",
     "proGit.md",
@@ -158,8 +174,6 @@
     "hardcore web development/Список литературы.md",
     "img/python_arch.png",
     "img/python_arch.htm",
-    "hardcore web development/SSH how to.md",
-    "c/c common.md",
     "wireless",
     "todo"
   ]

+ 88 - 0
configs/wg0.conf

@@ -0,0 +1,88 @@
+~={green}Пример хранения данных в текстовом файлу в формате ключ=значение:=~
+```
+название=Тихий Дон
+автор=Михаил Шолохов
+описание=Одно из наиболее значительных, масштабных и талантливых произведений русскоязычной литературы, принесшее автору Нобелевскую премию.
+обложка=https://cdn.rroom.io/17558b4d-59dd-4f8e-b2c7-51b0d7da5216.png
+```
+~={green}Пример хранения тех же данных в текстовом файле в формате JSON:=~
+```json
+{
+    "name": "Тихий Дон",
+    "author": "Михаил Шолохов",
+    "description": "Одно из наиболее значительных, масштабных и талантливых произведений русскоязычной литературы, принесшее автору Нобелевскую премию.",
+    "cover": "https://cdn.rroom.io/17558b4d-59dd-4f8e-b2c7-51b0d7da5216.png"
+}
+```
+~={green}Пример хранения тех же данных в текстовом файле в формате XML:=~
+```html
+<book>
+    <name>Тихий Дон</name>
+    <author>Михаил Шолохов</author>
+    <description>Одно из наиболее значительных, масштабных и талантливых произведений русскоязычной литературы, принесшее автору Нобелевскую премию.</description>
+    <cover>https://cdn.rroom.io/17558b4d-59dd-4f8e-b2c7-51b0d7da5216.png</cover>
+</book>
+```
+
+~={cyan}Упражнения=~
+
+```json
+{
+    "cities": [
+        {
+            "name": "Москва",
+            "population": 13149803,
+            "child_cities": [
+                {
+                    "name": "Зеленоград"
+                }
+            ]
+        },
+        {
+            "name": "Санкт-Петербург",
+            "population": 5597763
+        },
+        {
+            "name": "Кемпендяй",
+            "population": 357
+        },
+        {
+            "name": "Пеледуй",
+            "population": 3578
+        },
+        {
+            "name": "Чаплыгин"
+        }
+    ]
+}
+
+```
+
+```xml
+<cities>
+<city>
+<name>Москва</name>
+<population>13149803</population>
+<child_cities>
+<city>
+<name>Зеленоград</name>
+</city>
+</child_cities>
+</city>
+<city>
+<name>Санкт-Петербург</name>
+<population>5597763</population>
+</city>
+<city>
+<name>Кемпендяй</name>
+<population>357</population>
+</city>
+<city>
+<name>Пеледуй</name>
+<population>3578</population>
+</city>
+<city>
+<name>Чаплыгин</name>
+</city>
+</cities>
+```

+ 2 - 2
todo/Задачи.md

@@ -8,10 +8,10 @@
 - [ ] Починить пороги.
 - [ ] Разобраться с обувью.
 - [x] Запись к ортодонту. 
-- [ ] Записать Нину к терапевту.
+- [x] Записать Нину к терапевту.
 <h6>Задачи по датам</h6>
 - [x] 25 сентября в среду в 11-45 к ортодонту
-- [ ] 4 октября в среду в 14-00 к ортодонту
+- [ ] 4 октября в пятницу в 14-00 к ортодонту
 - [ ] Долг 10к 4-ого октября.
 <h6>Технические задачи</h6>
 - [ ] Разобраться с тунелированием.

+ 18 - 0
todo/Счета.md

@@ -1,5 +1,23 @@
 # 2024
 
+#### <font color = "MediumSeaGreen">Октябрь</font>
+##### <font color = "#1D8571">Коммунальные услуги</font>
+- [ ] Широкая электричество
+- [ ] Широкая платежка ()
+- [ ] Подрезково ()
+- [ ] Нина электричество + TKO ().
+
+##### <font color = "#1D8571">Передача показаний с 15-ого числа</font>
+- [ ] Широкая вода. хол, гор
+- [ ] Широкая электричество: передал показания через телефон  
+- [ ] Подрезково: хол , гор , эл  (Новый счетчик горячей воды, передал по старому )
+- [ ] Химки: 471 - , 473 - , 450 - , 402 - , эл -  
+- [ ] Планерная Нина электричество: 
+- [ ] Планерная Батя электричество: 
+##### <font color = "#1D8571">Дополнительно</font>
+- [ ] Отдать Нине (отдать )
+- [ ] Домашний интернет
+- [ ] Сотовый телефон ()
 #### <font color = "MediumSeaGreen">Сентябрь</font>
 ##### <font color = "#1D8571">Коммунальные услуги</font>
 - [x] Широкая электричество

+ 21 - 1
todo/Тренировки и занятия.md

@@ -87,7 +87,27 @@ renderHabitCalendar(this.container, dv, {
 },
 {
     date: '2024-09-23',
-    content: '🦵\r🇬🇧', 
+    content: '🦵\r🇬🇧\r😵', 
+},
+{
+    date: '2024-09-24',
+    content: '💪', 
+},
+{
+    date: '2024-09-25',
+    content: '🦵', 
+},
+{
+    date: '2024-09-26',
+    content: '🇬🇧', 
+},
+{
+    date: '2024-09-27',
+    content: '🦵\r😵', 
+},
+{
+    date: '2024-09-30',
+    content: '🦵\r🇬🇧\r😵', 
 },
   ]
 })

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio