/* 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 key2 of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key2) && key2 !== except) __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => MultiPropPlugin2 }); module.exports = __toCommonJS(main_exports); var import_obsidian7 = require("obsidian"); // src/AddPropModal.ts var import_obsidian2 = require("obsidian"); // node_modules/esm-env/dev-fallback.js var node_env = globalThis.process?.env?.NODE_ENV; var dev_fallback_default = node_env && !node_env.toLowerCase().startsWith("prod"); // node_modules/svelte/src/internal/shared/utils.js var is_array = Array.isArray; var index_of = Array.prototype.indexOf; var array_from = Array.from; var object_keys = Object.keys; var define_property = Object.defineProperty; var get_descriptor = Object.getOwnPropertyDescriptor; var get_descriptors = Object.getOwnPropertyDescriptors; var object_prototype = Object.prototype; var array_prototype = Array.prototype; var get_prototype_of = Object.getPrototypeOf; var is_extensible = Object.isExtensible; function run_all(arr) { for (var i = 0; i < arr.length; i++) { arr[i](); } } function deferred() { var resolve; var reject; var promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } function to_array(value, n) { if (Array.isArray(value)) { return value; } if (n === void 0 || !(Symbol.iterator in value)) { return Array.from(value); } const array = []; for (const element2 of value) { array.push(element2); if (array.length === n) break; } return array; } // node_modules/svelte/src/internal/client/constants.js var DERIVED = 1 << 1; var EFFECT = 1 << 2; var RENDER_EFFECT = 1 << 3; var MANAGED_EFFECT = 1 << 24; var BLOCK_EFFECT = 1 << 4; var BRANCH_EFFECT = 1 << 5; var ROOT_EFFECT = 1 << 6; var BOUNDARY_EFFECT = 1 << 7; var CONNECTED = 1 << 9; var CLEAN = 1 << 10; var DIRTY = 1 << 11; var MAYBE_DIRTY = 1 << 12; var INERT = 1 << 13; var DESTROYED = 1 << 14; var EFFECT_RAN = 1 << 15; var EFFECT_TRANSPARENT = 1 << 16; var EAGER_EFFECT = 1 << 17; var HEAD_EFFECT = 1 << 18; var EFFECT_PRESERVED = 1 << 19; var USER_EFFECT = 1 << 20; var EFFECT_OFFSCREEN = 1 << 25; var WAS_MARKED = 1 << 15; var REACTION_IS_UPDATING = 1 << 21; var ASYNC = 1 << 22; var ERROR_VALUE = 1 << 23; var STATE_SYMBOL = Symbol("$state"); var LEGACY_PROPS = Symbol("legacy props"); var LOADING_ATTR_SYMBOL = Symbol(""); var PROXY_PATH_SYMBOL = Symbol("proxy path"); var STALE_REACTION = new class StaleReactionError extends Error { name = "StaleReactionError"; message = "The reaction that called `getAbortSignal()` was re-run or destroyed"; }(); var TEXT_NODE = 3; var COMMENT_NODE = 8; // node_modules/svelte/src/internal/shared/errors.js function lifecycle_outside_component(name) { if (dev_fallback_default) { const error = new Error(`lifecycle_outside_component \`${name}(...)\` can only be used during component initialisation https://svelte.dev/e/lifecycle_outside_component`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/lifecycle_outside_component`); } } // node_modules/svelte/src/internal/client/errors.js function async_derived_orphan() { if (dev_fallback_default) { const error = new Error(`async_derived_orphan Cannot create a \`$derived(...)\` with an \`await\` expression outside of an effect tree https://svelte.dev/e/async_derived_orphan`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/async_derived_orphan`); } } function bind_invalid_checkbox_value() { if (dev_fallback_default) { const error = new Error(`bind_invalid_checkbox_value Using \`bind:value\` together with a checkbox input is not allowed. Use \`bind:checked\` instead https://svelte.dev/e/bind_invalid_checkbox_value`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/bind_invalid_checkbox_value`); } } function derived_references_self() { if (dev_fallback_default) { const error = new Error(`derived_references_self A derived value cannot reference itself recursively https://svelte.dev/e/derived_references_self`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/derived_references_self`); } } function effect_in_teardown(rune) { if (dev_fallback_default) { const error = new Error(`effect_in_teardown \`${rune}\` cannot be used inside an effect cleanup function https://svelte.dev/e/effect_in_teardown`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/effect_in_teardown`); } } function effect_in_unowned_derived() { if (dev_fallback_default) { const error = new Error(`effect_in_unowned_derived Effect cannot be created inside a \`$derived\` value that was not itself created inside an effect https://svelte.dev/e/effect_in_unowned_derived`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/effect_in_unowned_derived`); } } function effect_orphan(rune) { if (dev_fallback_default) { const error = new Error(`effect_orphan \`${rune}\` can only be used inside an effect (e.g. during component initialisation) https://svelte.dev/e/effect_orphan`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/effect_orphan`); } } function effect_update_depth_exceeded() { if (dev_fallback_default) { const error = new Error(`effect_update_depth_exceeded Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state https://svelte.dev/e/effect_update_depth_exceeded`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`); } } function hydration_failed() { if (dev_fallback_default) { const error = new Error(`hydration_failed Failed to hydrate the application https://svelte.dev/e/hydration_failed`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/hydration_failed`); } } function props_invalid_value(key2) { if (dev_fallback_default) { const error = new Error(`props_invalid_value Cannot do \`bind:${key2}={undefined}\` when \`${key2}\` has a fallback value https://svelte.dev/e/props_invalid_value`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/props_invalid_value`); } } function rune_outside_svelte(rune) { if (dev_fallback_default) { const error = new Error(`rune_outside_svelte The \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files https://svelte.dev/e/rune_outside_svelte`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/rune_outside_svelte`); } } function state_descriptors_fixed() { if (dev_fallback_default) { const error = new Error(`state_descriptors_fixed Property descriptors defined on \`$state\` objects must contain \`value\` and always be \`enumerable\`, \`configurable\` and \`writable\`. https://svelte.dev/e/state_descriptors_fixed`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/state_descriptors_fixed`); } } function state_prototype_fixed() { if (dev_fallback_default) { const error = new Error(`state_prototype_fixed Cannot set prototype of \`$state\` object https://svelte.dev/e/state_prototype_fixed`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/state_prototype_fixed`); } } function state_unsafe_mutation() { if (dev_fallback_default) { const error = new Error(`state_unsafe_mutation Updating state inside \`$derived(...)\`, \`$inspect(...)\` or a template expression is forbidden. If the value should not be reactive, declare it without \`$state\` https://svelte.dev/e/state_unsafe_mutation`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/state_unsafe_mutation`); } } function svelte_boundary_reset_onerror() { if (dev_fallback_default) { const error = new Error(`svelte_boundary_reset_onerror A \`\` \`reset\` function cannot be called while an error is still being handled https://svelte.dev/e/svelte_boundary_reset_onerror`); error.name = "Svelte error"; throw error; } else { throw new Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`); } } // node_modules/svelte/src/constants.js var EACH_ITEM_REACTIVE = 1; var EACH_INDEX_REACTIVE = 1 << 1; var EACH_IS_CONTROLLED = 1 << 2; var EACH_IS_ANIMATED = 1 << 3; var EACH_ITEM_IMMUTABLE = 1 << 4; var PROPS_IS_IMMUTABLE = 1; var PROPS_IS_RUNES = 1 << 1; var PROPS_IS_UPDATED = 1 << 2; var PROPS_IS_BINDABLE = 1 << 3; var PROPS_IS_LAZY_INITIAL = 1 << 4; var TRANSITION_OUT = 1 << 1; var TRANSITION_GLOBAL = 1 << 2; var TEMPLATE_FRAGMENT = 1; var TEMPLATE_USE_IMPORT_NODE = 1 << 1; var TEMPLATE_USE_SVG = 1 << 2; var TEMPLATE_USE_MATHML = 1 << 3; var HYDRATION_START = "["; var HYDRATION_START_ELSE = "[!"; var HYDRATION_END = "]"; var HYDRATION_ERROR = {}; var ELEMENT_PRESERVE_ATTRIBUTE_CASE = 1 << 1; var ELEMENT_IS_INPUT = 1 << 2; var UNINITIALIZED = Symbol(); var FILENAME = Symbol("filename"); var HMR = Symbol("hmr"); var NAMESPACE_HTML = "http://www.w3.org/1999/xhtml"; // node_modules/svelte/src/internal/client/warnings.js var bold = "font-weight: bold"; var normal = "font-weight: normal"; function await_waterfall(name, location) { if (dev_fallback_default) { console.warn(`%c[svelte] await_waterfall %cAn async derived, \`${name}\` (${location}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app https://svelte.dev/e/await_waterfall`, bold, normal); } else { console.warn(`https://svelte.dev/e/await_waterfall`); } } function hydration_attribute_changed(attribute, html2, value) { if (dev_fallback_default) { console.warn(`%c[svelte] hydration_attribute_changed %cThe \`${attribute}\` attribute on \`${html2}\` changed its value between server and client renders. The client value, \`${value}\`, will be ignored in favour of the server value https://svelte.dev/e/hydration_attribute_changed`, bold, normal); } else { console.warn(`https://svelte.dev/e/hydration_attribute_changed`); } } function hydration_mismatch(location) { if (dev_fallback_default) { console.warn( `%c[svelte] hydration_mismatch %c${location ? `Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${location}` : "Hydration failed because the initial UI does not match what was rendered on the server"} https://svelte.dev/e/hydration_mismatch`, bold, normal ); } else { console.warn(`https://svelte.dev/e/hydration_mismatch`); } } function lifecycle_double_unmount() { if (dev_fallback_default) { console.warn(`%c[svelte] lifecycle_double_unmount %cTried to unmount a component that was not mounted https://svelte.dev/e/lifecycle_double_unmount`, bold, normal); } else { console.warn(`https://svelte.dev/e/lifecycle_double_unmount`); } } function select_multiple_invalid_value() { if (dev_fallback_default) { console.warn(`%c[svelte] select_multiple_invalid_value %cThe \`value\` property of a \` `); var $$css = { hash: "svelte-1jh3cip", code: "input.svelte-1jh3cip {max-height:25px;overflow-x:auto;}select.svelte-1jh3cip {height:21px;}#name-input.svelte-1jh3cip {flex-grow:0;width:auto;}.modal-input-container.svelte-1jh3cip {width:95%;display:flex;flex-direction:row;align-items:center;gap:10px;margin-top:10px;}.btn-inactive.svelte-1jh3cip {cursor:not-allowed;pointer-events:none;opacity:0.7;}" }; function AddPropInput($$anchor, $$props) { push($$props, true); append_styles($$anchor, $$css); let totalInputs = prop($$props, "totalInputs", 11, 0), typeVal = prop($$props, "typeVal", 11, "text"), nameVal = prop($$props, "nameVal", 15, ""), valueVal = prop($$props, "valueVal", 15, ""); let inputEl = state(proxy(document.createElement("input"))); let valueEl = state(proxy(document.createElement("input"))); const options = { Text: "string", Number: "number", Checkbox: "checkbox", Date: "date", Datetime: "datetime-local" }; const convertProps = { text: "Text", multitext: "Text", tags: "Text", aliases: "Text", number: "Number", checkbox: "Checkbox", date: "Date", datetime: "Datetime" }; let optionVal = state(proxy(options[convertProps[typeVal()]])); onMount(() => __awaiter(void 0, void 0, void 0, function* () { yield tick(); get(inputEl).focus(); get(inputEl).select(); set( optionVal, options[convertProps[typeVal()]], //Load default type. true ); if (typeVal() !== "text") changeType(get(optionVal)); })); function changeType(type) { get(valueEl).type = type; } var div = root(); var a = child(div); a.__click = () => { if (totalInputs() <= 1) return; $$props.removeInput($$props.id); }; var select = sibling(a, 2); select.__change = () => changeType(get(optionVal)); each(select, 21, () => Object.keys(options), index, ($$anchor2, key2) => { var option = root_1(); var text2 = child(option, true); reset(option); var option_value = {}; template_effect(() => { set_text(text2, get(key2)); if (option_value !== (option_value = options[get(key2)])) { option.value = (option.__value = options[get(key2)]) ?? ""; } }); append($$anchor2, option); }); reset(select); var input = sibling(select, 2); remove_input_defaults(input); bind_this(input, ($$value) => set(inputEl, $$value), () => get(inputEl)); var input_1 = sibling(input, 2); remove_input_defaults(input_1); bind_this(input_1, ($$value) => set(valueEl, $$value), () => get(valueEl)); reset(div); template_effect(() => { set_class(a, 1, `btn-del ${totalInputs() <= 1 ? "btn-inactive" : ""}`, "svelte-1jh3cip"); set_attribute2(a, "tabindex", totalInputs() <= 1 ? -1 : 0); }); bind_select_value(select, () => get(optionVal), ($$value) => set(optionVal, $$value)); bind_value(input, nameVal); bind_value(input_1, valueVal); append($$anchor, div); pop(); } delegate(["click", "change"]); // src/helpers.ts function parseValue(input, type) { switch (type) { case "number": return Number(input.value); case "checkbox": return Boolean(input.checked); default: return input.value; } } function removeExtraCommas(str) { return str.replace(/^,*(.*?),*$/g, "$1").replace(/,{2,}/g, ","); } function cleanTags(str) { let cleanStr = str; for (let index2 in KNOWN_BAD_CHARACTERS) { cleanStr = cleanStr.replaceAll(KNOWN_BAD_CHARACTERS[index2], ""); } return cleanStr; } var KNOWN_BAD_CHARACTERS = [ "\u2012", "\u2013", "\u2014", "\u2015", "\u204F", "\u203D", "\u2018", "\u201A", "\u201B", "\u2039", "\u203A", "\u201C", "\u201D", "\u201E", "\u201F", "\u2045", "\u2046", "\u204B", "\u204E", "\u2051", "\u2044", "\u204A", "\u2030", "\u2031", "\u2052", "\u2020", "\u2021", "\u2022", "\u2023", "\u2043", "\u204C", "\u204D", "\u2032", "\u2035", "\u2038", "\u203B", "\u2050", "\u2041", "\u2042", "\u2016", "\u2011", "\u2033", "\u2034", "\u2057", "\u2036", "\u2037", "`", "^", "\u203E", "\u2017", "\u2053", ";", ":", "!", "\u203C", "\u2049", "?", "\u2048", "\u2047", ".", "\u2024", "\u2025", "\u2026", "'", '"', "(", ")", "[", "]", "{", "}", "@", "*", "&", "%", "\u2054", "+", "<", "=", ">", "|", "~", "$", "\u2055", "\u2056", "\u2058", "\u2059", "\u205A", "\u205B", "\u205C", "\u205D", "\u205E", "\u2E00", "\u2E01", "\u2E02", "\u2E03", "\u2E04", "\u2E05", "\u2E06", "\u2E07", "\u2E08", "\u2E09", "\u2E0A", "\u2E0B", "\u2E0C", "\u2E0D", "\u2E0E", "\u2E0F", "\u2E10", "\u2E11", "\u2E12", "\u2E13", "\u2E14", "\u2E15", "\u2E16", "\u2E17", "\u2E1C", "\u2E1D", " ", "#" ]; // src/AddPropForm.svelte var root_12 = from_html(``); var root2 = from_html(``); var $$css2 = { hash: "svelte-18exwij", code: ".modal-inputs-container.svelte-18exwij {height:200px;width:100%;overflow-y:scroll;border-radius:5px;border-style:solid;display:flex;flex-direction:column;align-items:center;}.modal-add-container.svelte-18exwij {margin-top:10px;}.alert-container.svelte-18exwij {display:flex;flex-direction:column;align-items:center;justify-content:center;margin-bottom:10px;background-color:red;font-weight:bold;}.suggested-props.svelte-18exwij {overflow-y:scroll;max-height:100px;}.hidden.svelte-18exwij {display:none;}" }; function AddPropForm($$anchor, $$props) { push($$props, true); append_styles($$anchor, $$css2); let overwrite = prop($$props, "overwrite", 15); let countInputs = 0; let formEl = state(proxy(document.createElement("form"))); let errorEl = state(proxy(document.createElement("div"))); let alertText = state("."); let inputEls = state(proxy([])); function onCheckboxChange() { overwrite(!overwrite()); $$props.changeBool(overwrite()); } onMount(() => { $$props.defaultProps.length > 0 ? addInputs($$props.defaultProps) : addInputs([{ type: "text", name: "", value: "" }]); }); function addInputs(inputs = [{ type: "text", name: "", value: "" }]) { let arr = []; for (let input of inputs) { countInputs++; arr.push({ id: countInputs, totalInputs: countInputs, typeDef: input.type, nameDef: input.name, valueDef: input.value }); } set(inputEls, [...get(inputEls), ...arr], true); } function removeInput(id) { return __awaiter(this, void 0, void 0, function* () { set(inputEls, get(inputEls).filter((input) => input.id !== id), true); yield tick(); let inputs = get(formEl).querySelectorAll("input"); if (!inputs) return; inputs[inputs.length - 2].focus(); }); } function addSuggested(prop2) { if (!get(inputEls).find((el) => el.nameDef === prop2.name)) { addInputs([{ type: prop2.widget, name: prop2.name, value: "" }]); } } function checkDuplicateNames() { let set2 = /* @__PURE__ */ new Set(); for (let input of get(inputEls)) set2.add(input.nameDef); if (set2.size < get(inputEls).length) return true; else return false; } function runError(errorText) { set(alertText, errorText, true); get( errorEl //Should I have this error message fade away? ).classList.remove("hidden"); } function onSubmit(e) { e.preventDefault(); if (checkDuplicateNames()) { runError("Duplicate property names are not allowed."); return; } let obj = /* @__PURE__ */ new Map(); let inputs = get(formEl).querySelectorAll('input[name^="name[]"]'); inputs.forEach((input) => { var _a; if (!(input.nextElementSibling instanceof HTMLInputElement)) return; if (!(input.previousElementSibling instanceof HTMLSelectElement)) return; if (!(input.previousElementSibling.children[0] instanceof HTMLOptionElement)) return; let name = input.value; if (name === "") { input.reportValidity(); return; } const selectEl = input.previousElementSibling; const htmlType = selectEl.value; const reverseOptions = { string: "text", number: "number", checkbox: "checkbox", date: "date", "datetime-local": "datetime" }; const obsidianType = (_a = reverseOptions[htmlType]) !== null && _a !== void 0 ? _a : "text"; let value = parseValue(input.nextElementSibling, input.nextElementSibling.type); if (typeof value === "string") { if (name === "tags") { value = cleanTags(value); } if (typeof value === "string" && value.includes(",")) { let str = removeExtraCommas(value); value = str.split($$props.delimiter); } } if (value === "") value = null; let propObj = { type: obsidianType, data: value, overwrite: false, delimiter: $$props.delimiter }; obj.set(name, propObj); }); if (obj.size < inputs.length) return; $$props.submission(obj); } var div = root2(); var div_1 = child(div); var div_2 = sibling(child(div_1), 2); var text2 = child(div_2, true); reset(div_2); reset(div_1); bind_this(div_1, ($$value) => set(errorEl, $$value), () => get(errorEl)); var div_3 = sibling(div_1, 4); each(div_3, 21, () => $$props.suggestedProps, index, ($$anchor2, prop2) => { var button = root_12(); button.__click = () => addSuggested(get(prop2)); var text_1 = child(button, true); reset(button); template_effect(() => set_text(text_1, get(prop2).name)); append($$anchor2, button); }); reset(div_3); var p = sibling(div_3, 4); var text_2 = child(p); reset(p); var form = sibling(p, 4); var label = child(form); var input_1 = child(label); remove_input_defaults(input_1); input_1.__change = onCheckboxChange; var text_3 = sibling(input_1, 1, true); text_3.nodeValue = "Overwrite existing properties"; reset(label); var div_4 = sibling(label, 2); each(div_4, 21, () => get(inputEls), (input) => input.id, ($$anchor2, input, $$index_1) => { AddPropInput($$anchor2, { get id() { return get(input).id; }, get totalInputs() { return get(inputEls).length; }, removeInput, get typeVal() { return get(input).typeDef; }, set typeVal($$value) { get(input).typeDef = $$value; }, get nameVal() { return get(input).nameDef; }, set nameVal($$value) { get(input).nameDef = $$value; }, get valueVal() { return get(input).valueDef; }, set valueVal($$value) { get(input).valueDef = $$value; } }); }); reset(div_4); var div_5 = sibling(div_4, 2); var button_1 = child(div_5); button_1.__click = () => addInputs([{ type: "text", name: "", value: "" }]); reset(div_5); next(2); reset(form); bind_this(form, ($$value) => set(formEl, $$value), () => get(formEl)); reset(div); template_effect(() => { set_text(text2, get(alertText)); set_text(text_2, `If you want to make a List property, use the Text data type and separate each value with a "${$$props.delimiter ?? ""}".`); set_checked(input_1, overwrite()); }); event("submit", form, onSubmit); append($$anchor, div); pop(); } delegate(["click", "change"]); // src/AddConfirmModal.ts var import_obsidian = require("obsidian"); // src/AddConfirmForm.svelte var root_13 = from_html(`
  • `); var root3 = from_html(`

    The following props will be added:

      Are you sure you wish to proceed?

      `); var $$css3 = { hash: "svelte-n0gky0", code: ".msg.svelte-n0gky0 {font-weight:bold;padding-bottom:10px;}" }; function AddConfirmForm($$anchor, $$props) { push($$props, true); append_styles($$anchor, $$css3); let overwrite = prop($$props, "overwrite", 3, true); let btnCancel = state(null); let msg = user_derived(() => overwrite() ? "Any pre-existing text props will have their values overwritten." : "Any pre-existing text props will have their values be appended to."); function onSubmit(e) { e.preventDefault(); $$props.submission(); } onMount(() => { get(btnCancel) === null || get(btnCancel) === void 0 ? void 0 : get(btnCancel).focus(); }); var div = root3(); var form = child(div); var p = child(form); var text2 = child(p, true); reset(p); var ul = sibling(p, 4); each(ul, 21, () => [...$$props.newProps], index, ($$anchor2, $$item) => { var $$array = user_derived(() => to_array(get($$item), 2)); let propName = () => get($$array)[0]; let prop2 = () => get($$array)[1]; var li = root_13(); var text_1 = child(li); reset(li); template_effect(() => set_text(text_1, `${propName() ?? ""}: ${prop2().data ?? ""}`)); append($$anchor2, li); }); reset(ul); var button = sibling(ul, 6); button.__click = function(...$$args) { $$props.cancel?.apply(this, $$args); }; bind_this(button, ($$value) => set(btnCancel, $$value), () => get(btnCancel)); reset(form); reset(div); template_effect(() => set_text(text2, get(msg))); event("submit", form, onSubmit); append($$anchor, div); pop(); } delegate(["click"]); // src/AddConfirmModal.ts var AddConfirmModal = class extends import_obsidian.Modal { constructor(app, props, overwrite, submission) { super(app); this.props = props; this.overwrite = overwrite; this.submission = submission; } onSubmit() { this.submission(); this.close(); } onCancel() { this.close(); } onOpen() { this.titleEl.createEl("h2", { text: "Add Properties" }); this.component = mount(AddConfirmForm, { target: this.contentEl, props: { newProps: this.props, overwrite: this.overwrite, submission: this.onSubmit.bind(this), cancel: this.onCancel.bind(this) } }); } }; // src/AddPropModal.ts var PropModal = class extends import_obsidian2.Modal { constructor(app, submission, overwrite, delimiter, defaultProps, changeBool, suggestedProps) { super(app); this.submission = submission; this.overwrite = overwrite; this.delimiter = delimiter; this.defaultProps = defaultProps; this.changeBool = changeBool; this.suggestedProps = suggestedProps; } //Run form submission if user clicks confirm. onConfirm() { this.submission(this.props); this.close(); } updateBool(bool) { this.overwrite = bool; this.changeBool(bool); } //Pull up confirmation form when user submits base form. onSubmit(props) { this.props = props; new AddConfirmModal( this.app, this.props, this.overwrite, this.onConfirm.bind(this) ).open(); } onOpen() { this.titleEl.createEl("h2", { text: "Add Properties" }); this.component = mount(AddPropForm, { target: this.contentEl, props: { submission: this.onSubmit.bind(this), overwrite: this.overwrite, delimiter: this.delimiter, defaultProps: this.defaultProps, changeBool: this.updateBool.bind(this), suggestedProps: this.suggestedProps } }); } }; // src/SettingTab.ts var import_obsidian3 = require("obsidian"); var SettingTab = class extends import_obsidian3.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { let { containerEl } = this; containerEl.empty(); new import_obsidian3.Setting(containerEl).setName("Overwrite existing text").setDesc( "When adding a property with a name that already exists, the text will overwrite the prop's existing value. If left disabled, the new value will be appended to the old as a List." ).addToggle((toggle) => { toggle.setValue(this.plugin.settings.overwrite); toggle.onChange(async (value) => { this.plugin.settings.overwrite = value; await this.plugin.saveSettings(); }); }); new import_obsidian3.Setting(containerEl).setName("Recursive Iteration").setDesc( "When toggled on, while looping through all files in a folder, you will also loop through any sub-folders." ).addToggle((toggle) => { toggle.setValue(this.plugin.settings.recursive); toggle.onChange(async (value) => { this.plugin.settings.recursive = value; await this.plugin.saveSettings(); }); }); new import_obsidian3.Setting(containerEl).setName("List Delimiter").setDesc( "Set delimiter to use when creating a list. Commas(,) are used by default." ).addText((text2) => { text2.setValue(this.plugin.settings.delimiter); text2.onChange(async (value) => { if (value.length > 1) { text2.setValue(value[0]); new import_obsidian3.Notice("Delimiter must be a single character."); return; } this.plugin.settings.delimiter = value; await this.plugin.saveSettings(); }); }); new import_obsidian3.Setting(containerEl).setName("Default Props File").setDesc( "Select a file with properties that you want to load into the Multi Properties form by default. Type in the full path of the desired file.(ex. Templates/PropFile 1)" ).addText((text2) => { text2.setValue(this.plugin.settings.defaultPropPath); text2.onChange(async (value) => { this.plugin.settings.defaultPropPath = value; await this.plugin.saveSettings(); }); }); } }; // src/RemoveModal.ts var import_obsidian5 = require("obsidian"); // src/RemovePropForm.svelte var root_14 = from_html(``); var root4 = from_html(`

      Select the properties you wish to remove from the file selection.

      `); var $$css4 = { hash: "svelte-1c8m26c", code: ".name-container.svelte-1c8m26c {display:flex;flex-direction:column;gap:5px;margin-top:10px;margin-bottom:20px;}.alert-container.svelte-1c8m26c {display:flex;flex-direction:column;align-items:center;justify-content:center;margin-bottom:10px;background-color:red;font-weight:bold;}.button-container.svelte-1c8m26c {display:flex;flex-direction:row;justify-content:space-between;}.hidden.svelte-1c8m26c {display:none;}" }; function RemovePropForm($$anchor, $$props) { push($$props, true); append_styles($$anchor, $$css4); let names = prop($$props, "names", 19, () => []); let errorEl = state(null); let alertText = state("."); let checkCount = state(0); let inputs = state(proxy([])); user_effect(() => { const sortedNames = [...names()].sort(); set(inputs, sortedNames.map((name) => ({ name, isChecked: false })), true); set(checkCount, 0); }); let isMaxChecked = user_derived(() => get(inputs).length > 0 && get(checkCount) >= get(inputs).length); function onCheckboxChange(event2) { let checked = event2.target.checked; checked ? update(checkCount) : update(checkCount, -1); } function toggleAll() { const shouldCheckAll = !get(isMaxChecked); set(inputs, get(inputs).map((input) => Object.assign(Object.assign({}, input), { isChecked: shouldCheckAll })), true); set(checkCount, shouldCheckAll ? get(inputs).length : 0, true); } function onSubmit(e) { e.preventDefault(); if (get(checkCount) === 0) { set(alertText, "Please select at least one property to remove."); get(errorEl) === null || get(errorEl) === void 0 ? void 0 : get(errorEl).classList.remove("hidden"); return; } let propNames = get(inputs).filter((input) => input.isChecked).map((input) => input.name); $$props.submission(propNames); } var div = root4(); var div_1 = child(div); var div_2 = sibling(child(div_1), 2); var text2 = child(div_2, true); reset(div_2); reset(div_1); bind_this(div_1, ($$value) => set(errorEl, $$value), () => get(errorEl)); var form = sibling(div_1, 4); var div_3 = child(form); each(div_3, 21, () => get(inputs), (input) => input.name, ($$anchor2, input, $$index) => { var label = root_14(); var input_1 = child(label); remove_input_defaults(input_1); input_1.__change = (event2) => onCheckboxChange(event2); var text_1 = sibling(input_1); reset(label); template_effect(() => set_text(text_1, ` ${get(input).name ?? ""}`)); bind_checked(input_1, () => get(input).isChecked, ($$value) => get(input).isChecked = $$value); append($$anchor2, label); }); reset(div_3); var div_4 = sibling(div_3, 2); var button = sibling(child(div_4), 2); button.__click = toggleAll; var text_2 = child(button, true); reset(button); reset(div_4); reset(form); reset(div); template_effect(() => { set_text(text2, get(alertText)); set_text(text_2, get(isMaxChecked) ? "Uncheck All" : "Check All"); }); event("submit", form, onSubmit); append($$anchor, div); pop(); } delegate(["change", "click"]); // src/RemoveConfirmModal.ts var import_obsidian4 = require("obsidian"); // src/RemoveConfirmForm.svelte var root_15 = from_html(`
    • `); var root5 = from_html(`

        Are you sure you wish to proceed?

        `); function RemoveConfirmForm($$anchor, $$props) { push($$props, true); let names = prop($$props, "names", 19, () => ["test", "test2"]); let btnCancel = state(null); let word = user_derived(() => names().length > 1 ? "properties" : "property"); function onSubmit(e) { e.preventDefault(); $$props.submission(); } onMount(() => { get(btnCancel) === null || get(btnCancel) === void 0 ? void 0 : get(btnCancel).focus(); }); var div = root5(); var form = child(div); var p = child(form); var text2 = child(p); reset(p); var ul = sibling(p, 2); each(ul, 21, names, index, ($$anchor2, name) => { var li = root_15(); var text_1 = child(li, true); reset(li); template_effect(() => set_text(text_1, get(name))); append($$anchor2, li); }); reset(ul); var button = sibling(ul, 6); button.__click = function(...$$args) { $$props.cancel?.apply(this, $$args); }; bind_this(button, ($$value) => set(btnCancel, $$value), () => get(btnCancel)); reset(form); reset(div); template_effect(() => set_text(text2, `The following ${get(word) ?? ""} will be removed:`)); event("submit", form, onSubmit); append($$anchor, div); pop(); } delegate(["click"]); // src/RemoveConfirmModal.ts var RemoveConfirmModal = class extends import_obsidian4.Modal { constructor(app, names, submission) { super(app); this.names = names; this.submission = submission; } onSubmit() { this.submission(); this.close(); } onCancel() { this.close(); } onOpen() { if (!this.names || this.names.length === 0) { new import_obsidian4.Notice("Please check at least one property to remove."); this.close(); } this.titleEl.createEl("h2", { text: "Remove Properties" }); this.component = mount(RemoveConfirmForm, { target: this.contentEl, props: { names: this.names, submission: this.onSubmit.bind(this), cancel: this.onCancel.bind(this) } }); } }; // src/RemoveModal.ts var RemoveModal = class extends import_obsidian5.Modal { constructor(app, names, submission) { if (!names || names.length === 0) { new import_obsidian5.Notice("No properties to remove"); return; } super(app); this.names = names; this.submission = submission; } onConfirm() { this.submission(this.props); this.close(); } onSubmit(props) { this.props = props; new RemoveConfirmModal( this.app, this.props, this.onConfirm.bind(this) ).open(); } onOpen() { this.titleEl.createEl("h2", { text: "Remove Properties" }); this.component = mount(RemovePropForm, { target: this.contentEl, props: { names: this.names, submission: this.onSubmit.bind(this) } }); } }; // src/frontmatter.ts var import_obsidian6 = require("obsidian"); async function addProperties(fileProcessor, file, props, overwrite, propCache) { await fileProcessor(file, (frontmatter) => { for (const [key2, value] of props) { if (key2 === "tags" && !frontmatter.hasOwnProperty("tags") && !Array.isArray(value.data)) { frontmatter[key2] = [value.data]; continue; } if (!frontmatter[key2] || overwrite) { frontmatter[key2] = value.data; continue; } let type1 = value.type; let type2 = propCache[key2.toLowerCase()].widget; if (canBeAppended(type1, type2)) { if (frontmatter[key2] === value.data) continue; if (!value.data) continue; let arr = mergeIntoArrays(frontmatter[key2], value.data); frontmatter[key2] = arr; continue; } else { frontmatter[key2] = value.data; continue; } } }); } async function addPropToSet(fileProcessor, set2, file) { await fileProcessor(file, (frontmatter) => { for (const key2 in frontmatter) { set2.add(key2); } }); return set2; } async function removeProperties(fileProcessor, file, props) { await fileProcessor(file, (frontmatter) => { for (const prop2 of props) { frontmatter[prop2] = void 0; } }); } function canBeAppended(str1, str2) { let arr = ["number", "date", "datetime", "checkbox"]; if (arr.includes(str1) || arr.includes(str2)) return false; return true; } function mergeIntoArrays(...args) { const arrays = args.map((arg) => Array.isArray(arg) ? arg : [arg]); const flattened = arrays.flat(); const unique = [...new Set(flattened)]; return unique; } // src/main.ts var defaultSettings = { overwrite: false, recursive: true, delimiter: ",", defaultPropPath: "" }; var MultiPropPlugin2 = class extends import_obsidian7.Plugin { async loadSettings() { this.settings = Object.assign({}, defaultSettings, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } async changeOverwrite(bool) { this.settings.overwrite = bool; await this.saveSettings(); } _getFilesFromTabGroup(leaf) { if (!leaf) { return []; } const files = []; const fileSet = /* @__PURE__ */ new Set(); const activeParent = leaf.parent; if (activeParent instanceof import_obsidian7.WorkspaceTabs) { this.app.workspace.iterateAllLeaves((l) => { if (l.parent === activeParent && l.view instanceof import_obsidian7.FileView) { const file = l.view.file; if (file && !fileSet.has(file.path)) { files.push(file); fileSet.add(file.path); } } }); } else { const activeWindowRoot = leaf.getRoot(); this.app.workspace.iterateAllLeaves((l) => { if (l.getRoot() === activeWindowRoot && l.view instanceof import_obsidian7.FileView) { const file = l.view.file; if (file && !fileSet.has(file.path)) { files.push(file); fileSet.add(file.path); } } }); } return files; } async onload() { await this.loadSettings(); this.addSettingTab(new SettingTab(this.app, this)); this.addCommand({ id: "add-props-to-current-note", name: "Add props to current note", callback: async () => { const file = this.app.workspace.getActiveFile(); if (!file) { new import_obsidian7.Notice("No active file to add properties to.", 4e3); return; } await this.createPropModal([file]); } }); this.registerEvent( this.app.workspace.on("file-menu", (menu, node) => { let title = ""; let obj; if (node instanceof import_obsidian7.TFile) { obj = [node]; title = "Add props to file."; } else { obj = node; title = "Add props to folder."; } menu.addItem((item) => { item.setIcon("archive").setTitle(title).onClick(() => this.createPropModal(obj)); }); }) ); this.addCommand({ id: "remove-props-from-current-note", name: "Remove props from current note", callback: async () => { const file = this.app.workspace.getActiveFile(); if (!file) { new import_obsidian7.Notice("No active file to remove properties from.", 4e3); return; } await this.createRemoveModal([file]); } }); this.registerEvent( this.app.workspace.on("file-menu", (menu, node) => { let title = ""; let obj; if (node instanceof import_obsidian7.TFile) { obj = [node]; title = "Remove props from file."; } else { obj = node; title = "Remove props from folder."; } menu.addItem((item) => { item.setIcon("archive").setTitle(title).onClick(() => this.createRemoveModal(obj)); }); }) ); this.addCommand({ id: "add-props-to-tab-group", name: "Add props to tabs in active tab group", callback: async () => { const files = this._getFilesFromTabGroup(this.app.workspace.activeLeaf); if (!files || !files.length) { new import_obsidian7.Notice( "No open tabs in the active tab group to add properties to.", 4e3 ); return; } await this.createPropModal(files); } }); this.registerEvent( this.app.workspace.on("tab-group-menu", (menu) => { const obj = this._getFilesFromTabGroup( this.app.workspace.getLeaf(false) ); menu.addItem((item) => { item.setIcon("archive").setTitle("Add props from all tabs").onClick(() => this.createPropModal(obj)); }); }) ); this.addCommand({ id: "remove-props-from-tab-group", name: "Remove props from tabs in active tab group", callback: async () => { const files = this._getFilesFromTabGroup( this.app.workspace.getLeaf(false) ); if (!files || !files.length) { new import_obsidian7.Notice( "No open tabs in the active tab group to remove properties from.", 4e3 ); return; } await this.createRemoveModal(files); } }); this.registerEvent( this.app.workspace.on("tab-group-menu", (menu) => { const obj = this._getFilesFromTabGroup( this.app.workspace.getLeaf(false) ); menu.addItem((item) => { item.setIcon("archive").setTitle("Remove props from all tabs").onClick(() => this.createRemoveModal(obj)); }); }) ); this.registerEvent( this.app.workspace.on("files-menu", (menu, nodes) => { let obj = nodes; menu.addItem((item) => { item.setIcon("archive").setTitle("Add props to selected files").onClick(() => this.createPropModal(obj)); }); }) ); this.registerEvent( this.app.workspace.on("files-menu", (menu, nodes) => { let obj = nodes; menu.addItem((item) => { item.setIcon("archive").setTitle("Remove props from selected files").onClick(async () => this.createRemoveModal(obj)); }); }) ); this.registerEvent( this.app.workspace.on("search:results-menu", (menu, leaf) => { menu.addItem((item) => { item.setIcon("archive").setTitle("Add props to search results").onClick(() => { let files = this.getFilesFromSearch(leaf); if (!files.length) { new import_obsidian7.Notice("No files to add properties to.", 4e3); return; } this.createPropModal(files); }); }); }) ); this.registerEvent( this.app.workspace.on("search:results-menu", (menu, leaf) => { menu.addItem((item) => { item.setIcon("archive").setTitle("Remove props from search results").onClick(async () => { let files = this.getFilesFromSearch(leaf); if (!files.length) { new import_obsidian7.Notice("No files to remove properties from.", 4e3); return; } this.createRemoveModal(files); }); }); }) ); } async getPropsFromFolder(folder, names) { for (let obj of folder.children) { if (obj instanceof import_obsidian7.TFile && obj.extension === "md") { names = await addPropToSet( this.app.fileManager.processFrontMatter.bind(this.app.fileManager), names, obj ); } if (obj instanceof import_obsidian7.TFolder) { if (this.settings.recursive) { await this.getPropsFromFolder(obj, names); } } } return [...names].sort(); } async getPropsFromFiles(files, names) { for (let file of files) { if (file instanceof import_obsidian7.TFile && file.extension === "md") { names = await addPropToSet( this.app.fileManager.processFrontMatter.bind(this.app.fileManager), names, file ); } } return [...names]; } /** Iterates through all files in a folder and runs callback on each file. */ async searchFolders(folder, callback) { for (let obj of folder.children) { if (obj instanceof import_obsidian7.TFolder) { if (this.settings.recursive) { await this.searchFolders(obj, callback); } } if (obj instanceof import_obsidian7.TFile && obj.extension === "md") { await callback(obj); } } } async searchFiles(files, callback) { for (let file of files) { if (file instanceof import_obsidian7.TFile && file.extension === "md") { await callback(file); } } } getFilesFromSearch(leaf) { let files = []; leaf.dom.vChildren.children.forEach((e) => { files.push(e.file); }); return files; } async createPropModal(iterable) { let iterateFunc; if (iterable instanceof import_obsidian7.TFolder) { const allFiles = []; this.searchFolders(iterable, async (f) => allFiles.push(f)); iterateFunc = async (props) => { await this.searchFolders( iterable, await this.addPropsCallback(props, allFiles.length) ); }; } else { iterateFunc = async (props) => this.searchFiles( iterable, await this.addPropsCallback(props, iterable.length) ); } let defaultProps; defaultProps = this.loadDefaultProps(); const allProps = this.getAllUsedProperties(); new PropModal( this.app, iterateFunc, this.settings.overwrite, this.settings.delimiter, defaultProps, this.changeOverwrite.bind(this), allProps ).open(); } getAllUsedProperties() { const allProps = this.app.metadataCache.getAllPropertyInfos(); return Object.values(allProps).sort( (a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()) ); } /** Create modal for removing properties. * Will call a different function depending on whether files or a folder is used. */ async createRemoveModal(iterable) { let names; let iterateFunc; if (iterable instanceof import_obsidian7.TFolder) { names = await this.getPropsFromFolder(iterable, /* @__PURE__ */ new Set()); const allFiles = []; this.searchFolders(iterable, async (f) => allFiles.push(f)); iterateFunc = (props) => this.searchFolders( iterable, this.removePropsCallback(props, allFiles.length) ); } else { names = await this.getPropsFromFiles(iterable, /* @__PURE__ */ new Set()); iterateFunc = (props) => this.searchFiles( iterable, this.removePropsCallback(props, iterable.length) ); } if (names.length === 0) { new import_obsidian7.Notice("No properties to remove", 4e3); return; } const sortedNames = [...names].sort( (a, b) => a.toLowerCase() > b.toLowerCase() ? 1 : -1 ); new RemoveModal(this.app, sortedNames, iterateFunc).open(); } /** Read through a given file and get name/value of props. * Revised from https://forum.obsidian.md/t/how-to-programmatically-access-a-files-properties-types/77826/4. */ readYamlProperties(file) { const metadata = this.app.metadataCache.getFileCache(file); const frontmatter = metadata?.frontmatter; if (!frontmatter) { new import_obsidian7.Notice("Not a valid Props template.", 4e3); return; } const allPropsWithType = this.app.metadataCache.getAllPropertyInfos(); let result = []; for (let [key2, value] of Object.entries(frontmatter)) { const keyLower = key2.toLowerCase(); const obj = { name: key2, value, type: allPropsWithType[keyLower].widget }; result.push(obj); } return result; } loadDefaultProps() { if (this.settings.defaultPropPath) { try { const file = this.app.vault.getAbstractFileByPath( `${this.settings.defaultPropPath}.md` ); let tmp = this.readYamlProperties(file); if (tmp === void 0) throw Error("Undefined path."); return tmp; } catch (e) { new import_obsidian7.Notice( `${e}. Check if you entered a valid path in the Default Props File setting.`, 1e4 ); } } return [{ name: "", value: "", type: "text" }]; } async addPropsCallback(props, totalFiles) { const statusBarItem = this.addStatusBarItem(); let count = 0; return async (file) => { await addProperties( this.app.fileManager.processFrontMatter.bind(this.app.fileManager), file, props, this.settings.overwrite, this.app.metadataCache.getAllPropertyInfos() ); count++; statusBarItem.setText( "Added props to " + count + "/" + totalFiles + " files" ); if (count === totalFiles) { setTimeout(() => { statusBarItem.remove(); }, 5e3); } }; } removePropsCallback(props, totalFiles) { const statusBarItem = this.addStatusBarItem(); let count = 0; return async (file) => { await removeProperties( this.app.fileManager.processFrontMatter.bind(this.app.fileManager), file, props ); count++; statusBarItem.setText( "Removed props from " + count + "/" + totalFiles + " files" ); if (count === totalFiles) { setTimeout(() => { statusBarItem.remove(); }, 5e3); } }; } }; /* nosourcemap */