vault backup: 2026-01-06 17:28:27
This commit is contained in:
Vendored
+2
-1
@@ -18,5 +18,6 @@
|
|||||||
"easy-copy",
|
"easy-copy",
|
||||||
"anchor-display-text",
|
"anchor-display-text",
|
||||||
"calendar",
|
"calendar",
|
||||||
"periodic-notes"
|
"periodic-notes",
|
||||||
|
"spellcheck-toggler"
|
||||||
]
|
]
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"externalLinks": {
|
||||||
|
"behaviour": "global"
|
||||||
|
},
|
||||||
|
"internalLinks": {
|
||||||
|
"behaviour": "global"
|
||||||
|
},
|
||||||
|
"bareLinks": {
|
||||||
|
"behaviour": "global"
|
||||||
|
},
|
||||||
|
"htmlComments": {
|
||||||
|
"behaviour": "default"
|
||||||
|
},
|
||||||
|
"anyNode": {
|
||||||
|
"behaviour": "default"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"behaviour": "default"
|
||||||
|
},
|
||||||
|
"strong": {
|
||||||
|
"behaviour": "default"
|
||||||
|
},
|
||||||
|
"blockquote": {
|
||||||
|
"behaviour": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
+591
@@ -0,0 +1,591 @@
|
|||||||
|
/*
|
||||||
|
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: () => SpellcheckTogglerPlugin
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(main_exports);
|
||||||
|
|
||||||
|
// src/plugin.ts
|
||||||
|
var import_obsidian2 = require("obsidian");
|
||||||
|
|
||||||
|
// src/settings.ts
|
||||||
|
var import_obsidian = require("obsidian");
|
||||||
|
var SpellcheckBehaviourOptionDisplay = {
|
||||||
|
["default" /* DEFAULT */]: "Always spellcheck",
|
||||||
|
["frontmatter" /* FRONTMATTER */]: "Use frontmatter",
|
||||||
|
["global" /* GLOBAL */]: "Never spellcheck"
|
||||||
|
};
|
||||||
|
var defaultSettings = {
|
||||||
|
externalLinks: { behaviour: "global" /* GLOBAL */ },
|
||||||
|
internalLinks: { behaviour: "global" /* GLOBAL */ },
|
||||||
|
bareLinks: { behaviour: "global" /* GLOBAL */ },
|
||||||
|
htmlComments: { behaviour: "default" /* DEFAULT */ },
|
||||||
|
anyNode: { behaviour: "default" /* DEFAULT */ },
|
||||||
|
emphasis: { behaviour: "default" /* DEFAULT */ },
|
||||||
|
strong: { behaviour: "default" /* DEFAULT */ },
|
||||||
|
blockquote: { behaviour: "default" /* DEFAULT */ }
|
||||||
|
};
|
||||||
|
var SpellcheckTogglerSettingTab = class extends import_obsidian.PluginSettingTab {
|
||||||
|
constructor(app, plugin) {
|
||||||
|
super(app, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
display() {
|
||||||
|
let { containerEl } = this;
|
||||||
|
containerEl.empty();
|
||||||
|
const createSpellcheckOptionDisplay = (optionKey, name, description, targetFormat) => {
|
||||||
|
const settingContainer = containerEl.createDiv({
|
||||||
|
cls: "settings-container"
|
||||||
|
});
|
||||||
|
const headingSetting = new import_obsidian.Setting(settingContainer).setHeading().setName(name).setDesc(description);
|
||||||
|
if (targetFormat) {
|
||||||
|
const span = headingSetting.controlEl.createEl("span", {
|
||||||
|
text: `Targeted format: `,
|
||||||
|
cls: "setting-item-target-label"
|
||||||
|
});
|
||||||
|
span.createEl("code", {
|
||||||
|
text: targetFormat,
|
||||||
|
cls: "setting-item-target-label"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const frontmatterDrawer = settingContainer.createDiv({
|
||||||
|
cls: "frontmatter-drawer"
|
||||||
|
});
|
||||||
|
new import_obsidian.Setting(frontmatterDrawer).setName("Frontmatter override property").setDesc(
|
||||||
|
"Define the (boolean) frontmatter property which controls the spellcheck behaviour for a file."
|
||||||
|
).addText(
|
||||||
|
(text) => {
|
||||||
|
var _a;
|
||||||
|
return text.setValue(
|
||||||
|
(_a = this.plugin.settings[optionKey].frontmatterOverride) != null ? _a : ""
|
||||||
|
).onChange(
|
||||||
|
(frontmatterOverride) => this.plugin.saveSettings({
|
||||||
|
[optionKey]: {
|
||||||
|
...this.plugin.settings[optionKey],
|
||||||
|
frontmatterOverride: frontmatterOverride.length ? frontmatterOverride : void 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
new import_obsidian.Setting(frontmatterDrawer).setName("Fallback behavior").setDesc(
|
||||||
|
"Select the spellcheck fallback behavior for the node in files where the frontmatter property is absent."
|
||||||
|
).addDropdown((dropdown) => {
|
||||||
|
var _a;
|
||||||
|
const { frontmatter, ...filteredOptions } = SpellcheckBehaviourOptionDisplay;
|
||||||
|
dropdown.addOptions({ ...filteredOptions }).onChange((frontmatterFallback) => {
|
||||||
|
this.plugin.saveSettings({
|
||||||
|
[optionKey]: {
|
||||||
|
...this.plugin.settings[optionKey],
|
||||||
|
frontmatterFallback
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).setValue(
|
||||||
|
(_a = this.plugin.settings[optionKey].frontmatterFallback) != null ? _a : "default" /* DEFAULT */
|
||||||
|
);
|
||||||
|
});
|
||||||
|
frontmatterDrawer.toggleClass(
|
||||||
|
"hidden",
|
||||||
|
[
|
||||||
|
"default" /* DEFAULT */,
|
||||||
|
"global" /* GLOBAL */
|
||||||
|
].includes(this.plugin.settings[optionKey].behaviour)
|
||||||
|
);
|
||||||
|
new import_obsidian.Setting(settingContainer).setName("Spellchecking behaviour").addDropdown(
|
||||||
|
(dropdown) => dropdown.addOptions(SpellcheckBehaviourOptionDisplay).onChange((behaviour) => {
|
||||||
|
this.plugin.saveSettings({
|
||||||
|
[optionKey]: {
|
||||||
|
...this.plugin.settings[optionKey],
|
||||||
|
behaviour
|
||||||
|
}
|
||||||
|
});
|
||||||
|
frontmatterDrawer.toggleClass(
|
||||||
|
"hidden",
|
||||||
|
[
|
||||||
|
"default" /* DEFAULT */,
|
||||||
|
"global" /* GLOBAL */
|
||||||
|
].includes(
|
||||||
|
this.plugin.settings[optionKey].behaviour
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}).setValue(this.plugin.settings[optionKey].behaviour)
|
||||||
|
);
|
||||||
|
settingContainer.appendChild(frontmatterDrawer);
|
||||||
|
};
|
||||||
|
const legendContainer = containerEl.createDiv({
|
||||||
|
cls: "settings-container"
|
||||||
|
});
|
||||||
|
new import_obsidian.Setting(legendContainer).setHeading().setName("Spellcheck toggler settings").setDesc(
|
||||||
|
"Configure spellchecking options. The behaviour of a spellcheck option is defined as follows:"
|
||||||
|
);
|
||||||
|
const list = legendContainer.createEl("ul");
|
||||||
|
list.createEl("li", {
|
||||||
|
text: ` "Always spellcheck": the editor default behaviour will be applied (the plugin is not active for the option).`,
|
||||||
|
cls: "setting-item-target-label"
|
||||||
|
});
|
||||||
|
list.createEl("li", {
|
||||||
|
text: ` "Use frontmatter": use the defined frontmatter property to toggle spellchecking per file.`,
|
||||||
|
cls: "setting-item-target-label"
|
||||||
|
});
|
||||||
|
list.createEl("li", {
|
||||||
|
text: ` "Never spellcheck": do not use spellcheck in any file for the option.`,
|
||||||
|
cls: "setting-item-target-label"
|
||||||
|
});
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"externalLinks",
|
||||||
|
"Markdown links option",
|
||||||
|
"Toggle spellcheck underline for link text in any markdown link.",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"internalLinks",
|
||||||
|
"Wikilinks option",
|
||||||
|
"Toggle spellcheck underline for link text in any wikilink.",
|
||||||
|
"[[ link text ]]"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"bareLinks",
|
||||||
|
"Bare links option",
|
||||||
|
"Toggle spellcheck underline for text in any bare link.",
|
||||||
|
"[text]"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"htmlComments",
|
||||||
|
"Html comment option",
|
||||||
|
"Toggle spellcheck underline for any text inside an html comment block.",
|
||||||
|
"<-- text -->"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"blockquote",
|
||||||
|
"Blockquote node option",
|
||||||
|
"Toggle spellcheck for text inside block quotes.",
|
||||||
|
">text"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"emphasis",
|
||||||
|
"Italics (emphasis) node option",
|
||||||
|
"Toggle spellcheck for italics (emphasis) text.",
|
||||||
|
"*text*"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"strong",
|
||||||
|
"Bolded (strong) node option",
|
||||||
|
"Toggle spellcheck for bolded (strong) text.",
|
||||||
|
"**text**"
|
||||||
|
);
|
||||||
|
createSpellcheckOptionDisplay(
|
||||||
|
"anyNode",
|
||||||
|
"Per file option",
|
||||||
|
'Toggle spellcheck for an entire file. With "Never spellcheck", spellchecking is disabled for all files.',
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/spellchecks/html-comments.ts
|
||||||
|
var import_view2 = require("@codemirror/view");
|
||||||
|
|
||||||
|
// src/spellchecks/apply-spellcheck-plugin.ts
|
||||||
|
var import_view = require("@codemirror/view");
|
||||||
|
var import_state = require("@codemirror/state");
|
||||||
|
var import_language = require("@codemirror/language");
|
||||||
|
|
||||||
|
// src/context.ts
|
||||||
|
var spellcheckContext = {
|
||||||
|
file: null,
|
||||||
|
frontmatter: null,
|
||||||
|
settings: defaultSettings,
|
||||||
|
uniqueOverrideKeys: []
|
||||||
|
};
|
||||||
|
var updateSpellcheckContext = (partialContext) => {
|
||||||
|
if ("frontmatter" in partialContext) {
|
||||||
|
updateFrontmatterWithDifference(partialContext.frontmatter);
|
||||||
|
delete partialContext["frontmatter"];
|
||||||
|
}
|
||||||
|
if ("settings" in partialContext) {
|
||||||
|
spellcheckContext.uniqueOverrideKeys = Object.values(
|
||||||
|
partialContext.settings
|
||||||
|
).reduce((set, option) => {
|
||||||
|
const override = option.frontmatterOverride;
|
||||||
|
if (override !== void 0)
|
||||||
|
set.push(override);
|
||||||
|
return set;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
spellcheckContext = { ...spellcheckContext, ...partialContext };
|
||||||
|
};
|
||||||
|
var updateFrontmatterWithDifference = (frontmatter) => {
|
||||||
|
if (frontmatter === null) {
|
||||||
|
spellcheckContext.frontmatter = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const frontmatterSpellcheckKeys = Object.keys(frontmatter).filter(
|
||||||
|
(k) => spellcheckContext.uniqueOverrideKeys.includes(k)
|
||||||
|
);
|
||||||
|
const filteredFrontmatter = frontmatterSpellcheckKeys.reduce((ffm, k) => {
|
||||||
|
ffm[k] = frontmatter[k];
|
||||||
|
return ffm;
|
||||||
|
}, {});
|
||||||
|
if (spellcheckContext.frontmatter === null || Object.keys(spellcheckContext.frontmatter).length !== frontmatterSpellcheckKeys.length) {
|
||||||
|
spellcheckContext.frontmatter = filteredFrontmatter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const key of frontmatterSpellcheckKeys) {
|
||||||
|
if (key in spellcheckContext.frontmatter && spellcheckContext.frontmatter[key] === frontmatter[key])
|
||||||
|
continue;
|
||||||
|
spellcheckContext.frontmatter = filteredFrontmatter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
var getSpellcheckContextProperty = (key) => spellcheckContext[key];
|
||||||
|
|
||||||
|
// src/spellchecks/apply-spellcheck-plugin.ts
|
||||||
|
var ApplySpellcheckAttributePluginValue = class {
|
||||||
|
constructor(view) {
|
||||||
|
this.decorations = this.buildDecorations(view);
|
||||||
|
}
|
||||||
|
update(update) {
|
||||||
|
if (!update.docChanged && !update.viewportChanged)
|
||||||
|
return;
|
||||||
|
this.decorations = this.buildDecorations(update.view);
|
||||||
|
}
|
||||||
|
buildDecorations(view) {
|
||||||
|
const builder = new import_state.RangeSetBuilder();
|
||||||
|
const markSpellcheckFalse = import_view.Decoration.mark({
|
||||||
|
attributes: { spellcheck: "false" }
|
||||||
|
});
|
||||||
|
const adds = [];
|
||||||
|
const enter = (node) => {
|
||||||
|
var _a;
|
||||||
|
if ((_a = this.isNodeEligible) == null ? void 0 : _a.call(this, node))
|
||||||
|
adds.push({ from: node.from, to: node.to });
|
||||||
|
};
|
||||||
|
for (let { from, to } of view.visibleRanges)
|
||||||
|
(0, import_language.syntaxTree)(view.state).iterate({
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
enter
|
||||||
|
});
|
||||||
|
adds.sort((a, b) => a.from - b.from);
|
||||||
|
for (const { from, to } of adds)
|
||||||
|
builder.add(from, to, markSpellcheckFalse);
|
||||||
|
return builder.finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var checkNodeEligibility = (settingsKey) => {
|
||||||
|
const frontmatter = getSpellcheckContextProperty("frontmatter");
|
||||||
|
switch (getSpellcheckContextProperty("settings")[settingsKey].behaviour) {
|
||||||
|
case "default" /* DEFAULT */:
|
||||||
|
return false;
|
||||||
|
case "global" /* GLOBAL */:
|
||||||
|
return true;
|
||||||
|
case "frontmatter" /* FRONTMATTER */:
|
||||||
|
const override = getSpellcheckContextProperty("settings")[settingsKey].frontmatterOverride;
|
||||||
|
const isOverrideInFrontmatter = frontmatter !== null && override !== void 0 && override in frontmatter;
|
||||||
|
const fallback = getSpellcheckContextProperty("settings")[settingsKey].frontmatterFallback;
|
||||||
|
const isOverrideFalse = isOverrideInFrontmatter && frontmatter[override] === false;
|
||||||
|
const isFallbackDisable = !isOverrideInFrontmatter && fallback === "global" /* GLOBAL */;
|
||||||
|
return isOverrideFalse || isFallbackDisable;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/spellchecks/html-comments.ts
|
||||||
|
var HtmlCommentSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.startsWith("comment"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("htmlComments");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var htmlCommentSpellcheckPluginValue = import_view2.ViewPlugin.fromClass(
|
||||||
|
HtmlCommentSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/spellchecks/markdown-links.ts
|
||||||
|
var import_view3 = require("@codemirror/view");
|
||||||
|
var MarkdownLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (node.type.name.match(/^link|.*_link$/) === null || node.type.name.contains("hmd-barelink"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("externalLinks");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var markdownLinkSpellcheckViewPlugin = import_view3.ViewPlugin.fromClass(
|
||||||
|
MarkdownLinkSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/spellchecks/wiki-links.ts
|
||||||
|
var import_view4 = require("@codemirror/view");
|
||||||
|
var WikiLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.contains("hmd-internal-link"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("internalLinks");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var wikiLinkSpellcheckViewPlugin = import_view4.ViewPlugin.fromClass(
|
||||||
|
WikiLinkSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/spellchecks/emphasis.ts
|
||||||
|
var import_view5 = require("@codemirror/view");
|
||||||
|
var EmphasisSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.startsWith("em"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("emphasis");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var emphasisSpellcheckPluginValue = import_view5.ViewPlugin.fromClass(
|
||||||
|
EmphasisSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/spellchecks/strong.ts
|
||||||
|
var import_view6 = require("@codemirror/view");
|
||||||
|
var StrongSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.startsWith("strong"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("strong");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var strongSpellcheckPluginValue = import_view6.ViewPlugin.fromClass(
|
||||||
|
StrongSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/migration/index.ts
|
||||||
|
var validateAndMigrateSettings = (settings) => {
|
||||||
|
if (settings === null)
|
||||||
|
return {};
|
||||||
|
const keys1_1_0ToKeys1_2_0 = {
|
||||||
|
spellcheckExternalLinks: "externalLinks",
|
||||||
|
spellcheckInternalLinks: "internalLinks",
|
||||||
|
spellcheckHtmlComments: "htmlComments"
|
||||||
|
};
|
||||||
|
for (const [srcKey, destKey] of Object.entries(keys1_1_0ToKeys1_2_0)) {
|
||||||
|
if (srcKey in settings && typeof settings[srcKey] === "boolean") {
|
||||||
|
settings[destKey] = {
|
||||||
|
behaviour: settings[srcKey] ? "default" /* DEFAULT */ : "global" /* GLOBAL */
|
||||||
|
};
|
||||||
|
delete settings[srcKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const [spellcheckKey, spellcheckOption] of Object.entries(settings)) {
|
||||||
|
const behaviour = spellcheckOption["behaviour"];
|
||||||
|
if (["opt-in", "opt-out"].includes(behaviour)) {
|
||||||
|
settings[spellcheckKey] = {
|
||||||
|
behaviour: "frontmatter" /* FRONTMATTER */,
|
||||||
|
frontmatterOverride: spellcheckOption["frontmatterOverride"],
|
||||||
|
frontmatterFallback: behaviour === "opt-in" ? "default" /* DEFAULT */ : "global" /* GLOBAL */
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { ...settings };
|
||||||
|
};
|
||||||
|
|
||||||
|
// src/spellchecks/blockquote.ts
|
||||||
|
var import_view7 = require("@codemirror/view");
|
||||||
|
var BlockQuoteSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.startsWith("quote"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("blockquote");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var blockQuoteSpellcheckPluginValue = import_view7.ViewPlugin.fromClass(
|
||||||
|
BlockQuoteSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/spellchecks/barelink.ts
|
||||||
|
var import_view8 = require("@codemirror/view");
|
||||||
|
var BareLinkSpellcheckPluginValue = class extends ApplySpellcheckAttributePluginValue {
|
||||||
|
isNodeEligible(node) {
|
||||||
|
if (!node.type.name.contains("hmd-barelink_link"))
|
||||||
|
return false;
|
||||||
|
return checkNodeEligibility("bareLinks");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var bareLinkSpellcheckPluginValue = import_view8.ViewPlugin.fromClass(
|
||||||
|
BareLinkSpellcheckPluginValue,
|
||||||
|
{
|
||||||
|
decorations: (pluginValue) => pluginValue.decorations
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// src/plugin.ts
|
||||||
|
var SpellcheckTogglerPlugin = class extends import_obsidian2.Plugin {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.editorExtensions = [];
|
||||||
|
}
|
||||||
|
async loadSettings() {
|
||||||
|
const userSettings = validateAndMigrateSettings(await this.loadData());
|
||||||
|
this.settings = { ...defaultSettings, ...userSettings };
|
||||||
|
this.saveData(this.settings);
|
||||||
|
updateSpellcheckContext({ settings: this.settings });
|
||||||
|
}
|
||||||
|
async saveSettings(settings) {
|
||||||
|
this.settings = { ...this.settings, ...settings };
|
||||||
|
await this.saveData(this.settings);
|
||||||
|
updateSpellcheckContext({ settings: this.settings });
|
||||||
|
this.refreshExtensions();
|
||||||
|
}
|
||||||
|
buildExtensions() {
|
||||||
|
this.editorExtensions.length = 0;
|
||||||
|
if (this.settings.internalLinks.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(wikiLinkSpellcheckViewPlugin);
|
||||||
|
if (this.settings.externalLinks.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(markdownLinkSpellcheckViewPlugin);
|
||||||
|
if (this.settings.bareLinks.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(bareLinkSpellcheckPluginValue);
|
||||||
|
if (this.settings.htmlComments.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(htmlCommentSpellcheckPluginValue);
|
||||||
|
if (this.settings.blockquote.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(blockQuoteSpellcheckPluginValue);
|
||||||
|
if (this.settings.emphasis.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(emphasisSpellcheckPluginValue);
|
||||||
|
if (this.settings.strong.behaviour !== "default" /* DEFAULT */)
|
||||||
|
this.editorExtensions.push(strongSpellcheckPluginValue);
|
||||||
|
}
|
||||||
|
refreshExtensions() {
|
||||||
|
var _a, _b;
|
||||||
|
this.buildExtensions();
|
||||||
|
this.app.workspace.updateOptions();
|
||||||
|
(_b = (_a = this.app.workspace.activeEditor) == null ? void 0 : _a.editor) == null ? void 0 : _b.refresh();
|
||||||
|
}
|
||||||
|
handleSpellcheckAttribute() {
|
||||||
|
let globalSpellcheckFlag = true;
|
||||||
|
const anyNodeOption = getSpellcheckContextProperty("settings")["anyNode"];
|
||||||
|
switch (anyNodeOption.behaviour) {
|
||||||
|
case "global" /* GLOBAL */:
|
||||||
|
globalSpellcheckFlag = false;
|
||||||
|
break;
|
||||||
|
case "frontmatter" /* FRONTMATTER */:
|
||||||
|
const frontmatter = getSpellcheckContextProperty("frontmatter");
|
||||||
|
const isOverrideInFrontmatter = frontmatter !== null && anyNodeOption.frontmatterOverride !== void 0 && anyNodeOption.frontmatterOverride in frontmatter;
|
||||||
|
const isOverrideTrue = isOverrideInFrontmatter && frontmatter[anyNodeOption.frontmatterOverride] === true;
|
||||||
|
const isFallbackDefault = !isOverrideInFrontmatter && anyNodeOption.frontmatterFallback !== "global" /* GLOBAL */;
|
||||||
|
globalSpellcheckFlag = isOverrideTrue || isFallbackDefault;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const content = this.app.workspace.containerEl.querySelector(".cm-content");
|
||||||
|
const attributeObserver = new MutationObserver((_, observer) => {
|
||||||
|
content.setAttribute("spellcheck", String(globalSpellcheckFlag));
|
||||||
|
observer.disconnect();
|
||||||
|
});
|
||||||
|
content.setAttribute("spellcheck", String(globalSpellcheckFlag));
|
||||||
|
attributeObserver.observe(content, {
|
||||||
|
attributes: true,
|
||||||
|
attributeOldValue: true,
|
||||||
|
attributeFilter: ["spellcheck"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onFileOpen(file) {
|
||||||
|
var _a;
|
||||||
|
if (file === null)
|
||||||
|
return;
|
||||||
|
const metadata = this.app.metadataCache.getFileCache(file);
|
||||||
|
const frontmatter = (_a = metadata == null ? void 0 : metadata.frontmatter) != null ? _a : null;
|
||||||
|
updateSpellcheckContext({
|
||||||
|
file,
|
||||||
|
frontmatter
|
||||||
|
});
|
||||||
|
this.handleSpellcheckAttribute();
|
||||||
|
}
|
||||||
|
onFileModify(file) {
|
||||||
|
var _a;
|
||||||
|
if (file === null || ((_a = this.app.workspace.getActiveFile()) == null ? void 0 : _a.basename) !== file.basename)
|
||||||
|
return;
|
||||||
|
(async () => {
|
||||||
|
var _a2;
|
||||||
|
const content = await this.app.vault.cachedRead(file);
|
||||||
|
const frontmatterInfo = (0, import_obsidian2.getFrontMatterInfo)(content);
|
||||||
|
if (!frontmatterInfo.exists)
|
||||||
|
return;
|
||||||
|
const overrideKeys = getSpellcheckContextProperty("uniqueOverrideKeys");
|
||||||
|
const frontmatter = {};
|
||||||
|
for (const line of frontmatterInfo.frontmatter.split("\n")) {
|
||||||
|
const [property, value] = line.split(":").map((s) => s.trim());
|
||||||
|
if (value === void 0 || value.length === 0)
|
||||||
|
continue;
|
||||||
|
const parsedValue = value === "true" ? true : value === "false" ? false : void 0;
|
||||||
|
if (parsedValue !== void 0 && overrideKeys.includes(property))
|
||||||
|
frontmatter[property] = parsedValue;
|
||||||
|
}
|
||||||
|
const didDiffer = updateFrontmatterWithDifference(frontmatter);
|
||||||
|
if (!didDiffer)
|
||||||
|
return;
|
||||||
|
this.handleSpellcheckAttribute();
|
||||||
|
const editor = (_a2 = this.app.workspace.activeEditor) == null ? void 0 : _a2.editor;
|
||||||
|
if (!editor)
|
||||||
|
return;
|
||||||
|
editor.replaceRange(" ", editor.getCursor());
|
||||||
|
editor.undo();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
async onload() {
|
||||||
|
await this.loadSettings();
|
||||||
|
this.addSettingTab(new SpellcheckTogglerSettingTab(this.app, this));
|
||||||
|
this.buildExtensions();
|
||||||
|
this.registerEditorExtension(this.editorExtensions);
|
||||||
|
this.onFileOpen(this.app.workspace.getActiveFile());
|
||||||
|
this.onFileOpenEventRef = this.app.workspace.on(
|
||||||
|
"file-open",
|
||||||
|
this.onFileOpen.bind(this)
|
||||||
|
);
|
||||||
|
this.onFileModifyEventRef = this.app.vault.on(
|
||||||
|
"modify",
|
||||||
|
this.onFileModify.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
unload() {
|
||||||
|
this.app.workspace.offref(this.onFileOpenEventRef);
|
||||||
|
this.app.vault.offref(this.onFileModifyEventRef);
|
||||||
|
super.unload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* nosourcemap */
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"id": "spellcheck-toggler",
|
||||||
|
"name": "Spellcheck Toggler",
|
||||||
|
"version": "1.4.3",
|
||||||
|
"minAppVersion": "1.5.3",
|
||||||
|
"description": "Toggle spellchecking for types of text blocks in the editing view.",
|
||||||
|
"author": "Julian Szachowicz",
|
||||||
|
"authorUrl": "https://github.com/julzerinos",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
.settings-container {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item {
|
||||||
|
border-top: 0px;
|
||||||
|
padding-top: .75rem;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-container:has(.setting-item-heading):not(:nth-of-type(1)) {
|
||||||
|
border-top: 1px solid var(--background-modifier-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item-heading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item-target-label {
|
||||||
|
font-weight: var(--font-normal);
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: var(--font-ui-smaller);
|
||||||
|
padding-top: var(--size-4-1);
|
||||||
|
line-height: var(--line-height-tight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frontmatter-drawer {
|
||||||
|
padding: 1rem;
|
||||||
|
margin-top: .5rem;
|
||||||
|
background-color: var(--color-base-25);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
+86
-1
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id:
|
id:
|
||||||
aliases: []
|
aliases: []
|
||||||
title: "2026-01-06"
|
title: 2026-01-06
|
||||||
tags:
|
tags:
|
||||||
- authorship/original
|
- authorship/original
|
||||||
- destiny/permanent
|
- destiny/permanent
|
||||||
@@ -17,3 +17,88 @@ tags:
|
|||||||
1. Person habitually engages in toxic behavior which they consciously believe to be benevolent
|
1. Person habitually engages in toxic behavior which they consciously believe to be benevolent
|
||||||
2. Person recognizes that when they stop engaging in said toxic behavior, others appreciate it
|
2. Person recognizes that when they stop engaging in said toxic behavior, others appreciate it
|
||||||
3. Person feels that they are doing a service by not engaging in said toxic behavior
|
3. Person feels that they are doing a service by not engaging in said toxic behavior
|
||||||
|
|
||||||
|
## 2026-01-06 10:00
|
||||||
|
|
||||||
|
Paraphrased Teams conversation with a peer
|
||||||
|
about [[distribution-designations#Terminations]].
|
||||||
|
Peer's messages are in block quotes.
|
||||||
|
|
||||||
|
### Content
|
||||||
|
|
||||||
|
> Good morning!
|
||||||
|
> Do you add branch terminations to panelboards?
|
||||||
|
> If so, how does your 'distribution' section looks?
|
||||||
|
|
||||||
|
Morning! Yes to the first question, ? to the second
|
||||||
|
|
||||||
|
> As all panelboards on a job don't have the same size/# of terminations,
|
||||||
|
> I assume you would have a plethora of same size boards in the job, with different terms.
|
||||||
|
> How do you list them?
|
||||||
|
|
||||||
|
| | Designation | Status | Quantity |
|
||||||
|
| --- | ----------------------------- | ------ | -------- |
|
||||||
|
| 1 | Generator - 350kW, Diesel | | 1 |
|
||||||
|
| 2 | Generator - 2000kW, Diesel | | 1 |
|
||||||
|
| 3 | ATS - 200A | | 2 |
|
||||||
|
| 4 | ATS - 250A | | 1 |
|
||||||
|
| 5 | ATS - 400A | | 2 |
|
||||||
|
| 6 | ATS - 600A | | 2 |
|
||||||
|
| 7 | ATS - 800A | | 1 |
|
||||||
|
| 8 | ATS - 1000A | | 1 |
|
||||||
|
| 9 | Panelboard - 50A, 1-Section | | 1 |
|
||||||
|
| 10 | Panelboard - 100A, 1-Section | | 18 |
|
||||||
|
| 11 | Panelboard - 125A, 1-Section | | 26 |
|
||||||
|
| 12 | Panelboard - 150A, 1-Section | | 2 |
|
||||||
|
| 13 | Panelboard - 225A, 1-Section | | 11 |
|
||||||
|
| 14 | Panelboard - 225A, 2-Section | | 5 |
|
||||||
|
| 15 | Panelboard - 400A, 1-Section | | 2 |
|
||||||
|
| 16 | Panelboard - 400A, 2-Section | | 3 |
|
||||||
|
| 17 | Panelboard - 400A, 3-Section | | 5 |
|
||||||
|
| 18 | Panelboard - 600A, 2-Section | | 1 |
|
||||||
|
| 19 | Panelboard - 800A, 1-Section | | 1 |
|
||||||
|
| 20 | Panelboard - 1200A, 1-Section | | 2 |
|
||||||
|
| 21 | Panelboard - 1200A, 2-Section | | 1 |
|
||||||
|
| 22 | Panelboard - 3000A, 1-Section | | 1 |
|
||||||
|
| 23 | CT Cabinet | | |
|
||||||
|
| 24 | Power Monitor | | 82 |
|
||||||
|
| 25 | SPD/TVSS | | 2 |
|
||||||
|
|
||||||
|
> Ah, so you just chuck in a lot # of terms per board and call it good?
|
||||||
|
|
||||||
|
Essentially.
|
||||||
|
Ben's direction was to pick a schedule on the upper end of terms for each size panel to be representative of the rest.
|
||||||
|
At my old place I would have made a designation for each panel,
|
||||||
|
I'm not upset to leave that behind.
|
||||||
|
I see no reason you couldn't just make each size once and keep it in a temp job.
|
||||||
|
I would, but I usually extract the schedules anyway so I just use the actual average.
|
||||||
|
|
||||||
|
> Thank you for that.
|
||||||
|
> Joel wagged his finger at me about missing terms this morning---
|
||||||
|
> I wanted to see how it's preferred.
|
||||||
|
> I was told terms are captured by feeders/mech connections
|
||||||
|
> and have never added them to panelboards.
|
||||||
|
>
|
||||||
|
> That would be the best way, finding the actual average.
|
||||||
|
|
||||||
|
The mech connection assemblies have the load side term,
|
||||||
|
the feeder assemblies have both sides,
|
||||||
|
the branch assemblies don't have either,
|
||||||
|
that's why he got you, I think.
|
||||||
|
|
||||||
|
I don't think my way is best unless you already have all the circuits in a big table for other reasons.
|
||||||
|
Lot of effort for a marginal increase in certainty above a heuristic like Ben's.
|
||||||
|
|
||||||
|
I'm working on a job Noah started now,
|
||||||
|
he made certain panels separate from what I assume is the average
|
||||||
|
and labeled them with the name of the panel.
|
||||||
|
If I had a job where some were significantly more full than others
|
||||||
|
I _might_ do something similar,
|
||||||
|
but I'd probably name them "... 1-Section, ~25% Fill"/"... 1-Section, ~75% Fill" instead.
|
||||||
|
But that's a lot of mental overhead.
|
||||||
|
|
||||||
|
## 2026-01-06 10:57
|
||||||
|
|
||||||
|
Tracking contractor growth by project square footage
|
||||||
|
rather than contract value dollars.
|
||||||
|
Account for market shifts and regional differences.
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
id:
|
||||||
|
aliases: []
|
||||||
|
title: Distribution Designations
|
||||||
|
tags:
|
||||||
|
- authorship/original
|
||||||
|
- destiny/permanent
|
||||||
|
- occupational/takeoff
|
||||||
|
- status/draft
|
||||||
|
- type/guide
|
||||||
|
---
|
||||||
|
# Distribution Designations
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
|
||||||
|
> [!example]
|
||||||
|
> ```
|
||||||
|
> Generator - 350kW, Diesel
|
||||||
|
> Generator - 2000kW, Diesel
|
||||||
|
> ATS - 200A
|
||||||
|
> ATS - 250A
|
||||||
|
> ATS - 400A
|
||||||
|
> ATS - 600A
|
||||||
|
> ATS - 800A
|
||||||
|
> ATS - 1000A
|
||||||
|
> Panelboard - 50A, 1-Section
|
||||||
|
> Panelboard - 100A, 1-Section
|
||||||
|
> Panelboard - 125A, 1-Section
|
||||||
|
> Panelboard - 150A, 1-Section
|
||||||
|
> Panelboard - 225A, 1-Section
|
||||||
|
> Panelboard - 225A, 2-Section
|
||||||
|
> Panelboard - 400A, 1-Section
|
||||||
|
> Panelboard - 400A, 2-Section
|
||||||
|
> Panelboard - 400A, 3-Section
|
||||||
|
> Panelboard - 600A, 2-Section
|
||||||
|
> Panelboard - 800A, 1-Section
|
||||||
|
> Panelboard - 1200A, 1-Section
|
||||||
|
> Panelboard - 1200A, 2-Section
|
||||||
|
> Panelboard - 3000A, 1-Section
|
||||||
|
> CT Cabinet
|
||||||
|
> Power Monitor
|
||||||
|
> SPD/TVSS
|
||||||
|
> ```
|
||||||
|
|
||||||
|
## Content
|
||||||
|
|
||||||
|
### Terminations
|
||||||
|
|
||||||
|
When building
|
||||||
|
* [[#Panelboards]]
|
||||||
|
* [[#Switchboards]]
|
||||||
|
add **branch terminations** according to an example from the schedules.
|
||||||
|
**Do not include feeder terminations.**
|
||||||
|
|
||||||
|
## By Equipment Type
|
||||||
|
|
||||||
|
> [!tip] When in Doubt
|
||||||
|
> If the equipment is not listed below,
|
||||||
|
> use a distribution panel of equal amps.
|
||||||
|
|
||||||
|
### CT Cabinets
|
||||||
|
|
||||||
|
???
|
||||||
|
|
||||||
|
### SPD's/TVSS's
|
||||||
|
|
||||||
|
> Name = "SPD"
|
||||||
|
|
||||||
|
Labor only.
|
||||||
|
|
||||||
|
Specific item is not important, but I use
|
||||||
|
`SPLITTERS / SOCKETS / CABINETS`/`METER SOCKETS & CABINETS`/`METERING CURRENT TRANSFORMER`
|
||||||
|
(Labor = 1.5hrs)
|
||||||
|
for consistency.
|
||||||
|
|
||||||
|
### Submeters/Power Monitors
|
||||||
|
|
||||||
|
> Name = "Power Monitor"
|
||||||
|
|
||||||
|
See [[switchgear#SPD's/TVSS's]]
|
||||||
|
|
||||||
|
### Switchboards
|
||||||
|
|
||||||
|
> Name = "Switchboard - 2000A, 4-Section"
|
||||||
|
|
||||||
|
### Panelboards
|
||||||
|
|
||||||
|
> Name = "Panelboard - 600A, 2-Section"
|
||||||
|
|
||||||
|
`DISTRIBUTION`/`DIST PANELS & UNIT LOAD CENTERS`/...
|
||||||
|
|
||||||
|
### Disconnects and Enclosed Circuit Breakers
|
||||||
|
|
||||||
|
`COMMON ASSEMBLIES`/`DISTRIBUTION`/`MANUAL DISCONNECTS`/...
|
||||||
|
|
||||||
|
### Generators
|
||||||
|
|
||||||
|
> Name = "Generator - 250kW, Diesel"
|
||||||
|
|
||||||
|
Add `DISTRIBUTION FITTINGS`/`GENERATOR SET UP`.
|
||||||
|
|
||||||
|
### Generator Connection Cabinets
|
||||||
|
|
||||||
|
> Name = "GCC - 200A"
|
||||||
|
|
||||||
|
Use a Distribution Panel of equal amps.
|
||||||
|
Or a transfer switch.
|
||||||
|
|
||||||
|
### Transfer Switches
|
||||||
|
|
||||||
|
> Name = "Transfer Switch - 400A"
|
||||||
|
|
||||||
|
#### Transfer Switches 1200A+
|
||||||
|
|
||||||
|
Use 1200A and add an additional `TRANSFER SWITCH` item
|
||||||
|
to make up the remaining amps.
|
||||||
|
|
||||||
|
### Meter Centers
|
||||||
|
|
||||||
|
> Name = "Meter Center - 800A, 16-Can"
|
||||||
|
|
||||||
|
`SWITCHGEAR & METER CENTERS`/`METER CENTERS`/`... METERING SECTION`
|
||||||
|
|
||||||
|
Adjust Factor 1 for meter stacks, delete zeroed items.
|
||||||
@@ -40,7 +40,7 @@ add `ITEM DATABASE`/`WIRING & SYSTEM DEVICES`/`FLOOR BOXES & FITTTINGS`/`GENERIC
|
|||||||
|
|
||||||
## Homeruns
|
## Homeruns
|
||||||
|
|
||||||
### Lighting
|
### Lighting Homeruns
|
||||||
|
|
||||||
* `Area` = "XX - Level XX Building"
|
* `Area` = "XX - Level XX Building"
|
||||||
* `Phase` = "Building - Back of House (BOH)"
|
* `Phase` = "Building - Back of House (BOH)"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ for use in [[fixtures-takeoff]].
|
|||||||
> [!example]
|
> [!example]
|
||||||
> `A - Surface (Pendant) = 2.0hrs - #12 MC+LV 20ft`
|
> `A - Surface (Pendant) = 2.0hrs - #12 MC+LV 20ft`
|
||||||
|
|
||||||
## Order
|
### Order
|
||||||
|
|
||||||
Use empty designations to separate phases.
|
Use empty designations to separate phases.
|
||||||
|
|
||||||
@@ -49,7 +49,9 @@ Use empty designations to separate phases.
|
|||||||
> ...
|
> ...
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
## Fixture Labor
|
## Content
|
||||||
|
|
||||||
|
### Fixture Labor
|
||||||
|
|
||||||
| Fixture Type | Labor |
|
| Fixture Type | Labor |
|
||||||
|:------------ | ----------:|
|
|:------------ | ----------:|
|
||||||
@@ -60,7 +62,7 @@ Use empty designations to separate phases.
|
|||||||
| Festoon | 2.0 hr/ea. |
|
| Festoon | 2.0 hr/ea. |
|
||||||
| All Others | 1.0 hr/ea. |
|
| All Others | 1.0 hr/ea. |
|
||||||
|
|
||||||
## Fixture Branch Length
|
### Fixture Branch Length
|
||||||
|
|
||||||
| Case | Standard Length |
|
| Case | Standard Length |
|
||||||
| --------------------- | --------------- |
|
| --------------------- | --------------- |
|
||||||
@@ -78,7 +80,7 @@ Use empty designations to separate phases.
|
|||||||
|
|
||||||
Reduce as appropriate.
|
Reduce as appropriate.
|
||||||
|
|
||||||
## Fixture Branch Wire size
|
### Fixture Branch Wire size
|
||||||
|
|
||||||
| Case | Wire Size |
|
| Case | Wire Size |
|
||||||
| -------------- | --------- |
|
| -------------- | --------- |
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ tags:
|
|||||||
# Fixtures Takeoff
|
# Fixtures Takeoff
|
||||||
|
|
||||||
This system is only for luminaires and their immediate branch wiring.
|
This system is only for luminaires and their immediate branch wiring.
|
||||||
See also [[lighting-controls-takeoff]] and [[electrical-takeoff]].
|
See also [[lighting-controls-takeoff]] and [[electrical-takeoff#Lighting Homeruns]].
|
||||||
|
|
||||||
[[fixture-designations]]
|
[[fixture-designations]]
|
||||||
|
|
||||||
|
|||||||
+29
-7
@@ -13,6 +13,24 @@ tags:
|
|||||||
|
|
||||||
This is the commentary companion to [[taleb_2001_fooled-by-randomness]].
|
This is the commentary companion to [[taleb_2001_fooled-by-randomness]].
|
||||||
|
|
||||||
|
## Review
|
||||||
|
|
||||||
|
This is a low-effort bestseller bait
|
||||||
|
on the order of the lucky fools it (rightly) criticizes.
|
||||||
|
The only difference is that Warren Buffet is a successful trader.
|
||||||
|
|
||||||
|
If you've read or are reading this book
|
||||||
|
and find yourself agreeing with any of its conclusions,
|
||||||
|
try _The Failure of Risk Management_ by Douglas W. Hubbard.
|
||||||
|
Hubbard dismantles Taleb's pessimism point by point,
|
||||||
|
and it's an excellent read besides.
|
||||||
|
|
||||||
|
One might be tempted to say
|
||||||
|
that the damage Taleb and this book have done
|
||||||
|
to risk management and adjacent fields is immeasurable,
|
||||||
|
but I'm confident a rigorous model could estimate the damage
|
||||||
|
to an acceptable level of certainty.
|
||||||
|
|
||||||
## Critiques
|
## Critiques
|
||||||
|
|
||||||
### Intellectual Insecurity
|
### Intellectual Insecurity
|
||||||
@@ -28,16 +46,20 @@ relying on the strength of Taleb's logic alone, by his own stating.
|
|||||||
|
|
||||||
Taleb argues this strategy is perfectly legitimate, which is _true_,
|
Taleb argues this strategy is perfectly legitimate, which is _true_,
|
||||||
but it does not follow that it makes for the most robust argument.
|
but it does not follow that it makes for the most robust argument.
|
||||||
In recent editions of the text, Taleb claims that his editors have implored him
|
In recent editions of the text, Taleb claims that his editors have _implored_ him
|
||||||
to provide figures, graphs, studies, etc. as---_he agrees_---would be expected
|
to provide figures, graphs, studies, etc. as---_he agrees_---would be expected
|
||||||
for any similar book on statistical phenomena, but he refuses.
|
for any similar book on statistical phenomena, but he refuses.
|
||||||
|
|
||||||
I don't find this approach charming at all,
|
I don't find this approach charming at all,
|
||||||
especially considering how critical Taleb is of demagogues.
|
especially considering how critical Taleb is of demagogues like Warren Buffet,
|
||||||
|
who could write that their success was foretold burning oracle bones
|
||||||
|
and the book would still be a bestseller.
|
||||||
|
_Fooled by Randomness_ fails to differentiate itself from such books,
|
||||||
|
except in that it was written by a mediocre trader.
|
||||||
|
|
||||||
Juxtaposing FbR with [[hubbard_2020_failure]],
|
Juxtaposing FbR with [[hubbard_2020_failure]],
|
||||||
which is a more traditional work of statistical thought,
|
which is a more traditional work of statistical thought---
|
||||||
well researched, and with a thorough bibliography,
|
well researched, and with a thorough bibliography---
|
||||||
Taleb's arguments are considerably less satisfying.
|
Taleb's arguments are considerably less satisfying.
|
||||||
When Hubbard is wrong, it's clear his interpretation is flawed in that instance,
|
When Hubbard is wrong, it's clear his interpretation is flawed in that instance,
|
||||||
when _Taleb_ is wrong, I question the foundation of all his arguments.
|
when _Taleb_ is wrong, I question the foundation of all his arguments.
|
||||||
@@ -91,7 +113,7 @@ much more so to dismiss the tests used to prove the validity of statistical meth
|
|||||||
### False Lucky Fools
|
### False Lucky Fools
|
||||||
|
|
||||||
Taleb repeatedly conflates legitimate lucky fools
|
Taleb repeatedly conflates legitimate lucky fools
|
||||||
with people with ideas he doesn't like.
|
and people with ideas he doesn't like.
|
||||||
|
|
||||||
> [[hubbard_2020_failure]]
|
> [[hubbard_2020_failure]]
|
||||||
> does a much better job of explaining "lucky fools"
|
> does a much better job of explaining "lucky fools"
|
||||||
@@ -101,7 +123,7 @@ with people with ideas he doesn't like.
|
|||||||
|
|
||||||
Taleb uses the story of Nero Tulip,
|
Taleb uses the story of Nero Tulip,
|
||||||
an incredibly cautious investor,
|
an incredibly cautious investor,
|
||||||
and his success over his risk-loving rival John
|
and his success over his risk-loving rival "John"
|
||||||
to promote the idea that modern quantitative methods
|
to promote the idea that modern quantitative methods
|
||||||
(as John is presumed to represent)
|
(as John is presumed to represent)
|
||||||
are inherently flawed.
|
are inherently flawed.
|
||||||
@@ -116,6 +138,6 @@ much less that he is practicing modern portfolio theory.
|
|||||||
If I mistake Taleb's intent,
|
If I mistake Taleb's intent,
|
||||||
and the story was only meant to convey
|
and the story was only meant to convey
|
||||||
that experienced, conscientious, and cautious decision-making
|
that experienced, conscientious, and cautious decision-making
|
||||||
can lead a person to success,
|
_can_ lead a person to success,
|
||||||
then I'm not sure who he's arguing against.
|
then I'm not sure who he's arguing against.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
id:
|
||||||
|
aliases: []
|
||||||
|
title: "Mike Holt's Illustrated Guide to Electrical Estimating"
|
||||||
|
tags: []
|
||||||
|
authors:
|
||||||
|
- Mike C. Holt
|
||||||
|
pages: 234
|
||||||
|
publisher: Mike Holt Enterprises
|
||||||
|
type: book
|
||||||
|
year: 2023
|
||||||
|
---
|
||||||
|
# Mike Holt's Illustrated Guide to Electrical Estimating
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: mike-holts-illustrated-guide-to-electrical-estimating
|
id: mike-holts-illustrated-guide-to-electrical-estimating
|
||||||
aliases: []
|
aliases: []
|
||||||
|
title: "_Mike Holt's Illustrated Guide to Electrical Estimating_"
|
||||||
tags:
|
tags:
|
||||||
- authorship/original
|
- authorship/original
|
||||||
- destiny/permanent
|
- destiny/permanent
|
||||||
@@ -8,44 +9,62 @@ tags:
|
|||||||
- topic/construction/electrical
|
- topic/construction/electrical
|
||||||
- topic/estimating
|
- topic/estimating
|
||||||
- type/media-commentary
|
- type/media-commentary
|
||||||
title: "_Mike Holt's Illustrated Guide to Electrical Estimating_"
|
|
||||||
---
|
---
|
||||||
# _Mike Holt's Illustrated Guide to Electrical Estimating_
|
# _Mike Holt's Illustrated Guide to Electrical Estimating_
|
||||||
|
|
||||||
```yaml
|
Commentary on [[holt_2023_estimating]].
|
||||||
authors:
|
|
||||||
- Mike C. Holt
|
|
||||||
year: 2023
|
|
||||||
title: "Mike Holt's Illustrated Guide to Electrical Estimating"
|
|
||||||
publisher: Mike Holt Enterprises
|
|
||||||
type: book
|
|
||||||
pages: 234
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pros
|
## Goodreads Review
|
||||||
|
|
||||||
* Attractive design
|
_Mike Holt's Illustrated Guide to Electrical Estimating_,
|
||||||
* Detailed color illustrations
|
like all of Holt's printed content I'm familiar with,
|
||||||
* Compelling topic organization and progression
|
is a masterclass in construction education presentation
|
||||||
|
featuring attractive design, and plenty of detailed illustrations.
|
||||||
|
The bones of a great estimating textbook are present,
|
||||||
|
it has a compelling topic organization and progression,
|
||||||
|
however the content does not deliver on the promise.
|
||||||
|
|
||||||
## Cons
|
The text treats estimating like an invariable set of procedures:
|
||||||
|
(1) get the documents
|
||||||
|
(2) do the takeoff
|
||||||
|
(3) do the closeout
|
||||||
|
(4) send the bid;
|
||||||
|
**if** there's ambiguity in the documents,
|
||||||
|
**then** send an RFI.
|
||||||
|
|
||||||
* No mention of RFQ process
|
The reality of the industry is far messier than Holt would have you believe.
|
||||||
|
|
||||||
* Many/most topics are grossly oversimplified
|
What do you do when RFI's go unanswered?
|
||||||
|
Drop the job?
|
||||||
|
|
||||||
* Tone is undeservedly authoritative and principled,
|
In fact, the text suggests that _all_ assumptions ==are bad==
|
||||||
refusing to acknowledge the questions of complexity
|
|
||||||
that the content itself begs
|
|
||||||
|
|
||||||
> "Never make assumptions"
|
I was compelled by my employer to purchase this book
|
||||||
> What happens when RFI's go unanswered?
|
along with several others of Holt's
|
||||||
|
as part of my apprenticeship curriculum.
|
||||||
|
I can't shake the feeling that this entry
|
||||||
|
was intended to pad out the course to four years.
|
||||||
|
|
||||||
## Best Suited For
|
## Goodreads Review Scratch
|
||||||
|
|
||||||
* Electricians with no prior estimating experience and no real need of detail
|
Holt's tone is undeservedly authoritative and principled.
|
||||||
|
|
||||||
|
It refuses to acknowledge the questions of complexity
|
||||||
|
that the content itself begs.
|
||||||
|
"Never make assumptions"
|
||||||
|
|
||||||
|
Many topics are grossly oversimplified,
|
||||||
|
or omitted entirely (subcontractor RFQ process)
|
||||||
|
|
||||||
|
This book is far too large in scope to lack the detail it does.
|
||||||
|
|
||||||
|
It feels designed for those unlikely to need or understand its topics,
|
||||||
|
except it is far too long for a layman's introduction.
|
||||||
|
|
||||||
|
If there will ever be a book to be what this one could not,
|
||||||
|
I don't think Holt would be the one to write it.
|
||||||
|
The group's content is very "teach to the book"
|
||||||
|
which is exactly what you want for contractor exams,
|
||||||
|
but not practical for estimating methodology.
|
||||||
|
|
||||||
## Overall
|
|
||||||
|
|
||||||
This book is far too large in scope to lack the detail it does. The curriculum
|
|
||||||
is clearly designed for those unlikely to need or understand its topics
|
|
||||||
|
|||||||
+14
-83
@@ -1,43 +1,22 @@
|
|||||||
---
|
---
|
||||||
id:
|
id:
|
||||||
aliases: []
|
aliases: []
|
||||||
|
title: Switchgear
|
||||||
tags:
|
tags:
|
||||||
- authorship/original
|
- authorship/original
|
||||||
- destiny/permanent
|
- destiny/permanent
|
||||||
- occupational/takeoff
|
- occupational/takeoff
|
||||||
- status/draft
|
- status/draft
|
||||||
- type/guide
|
- type/guide
|
||||||
title: Switchgear
|
|
||||||
---
|
---
|
||||||
# Switchgear
|
# Switchgear
|
||||||
|
|
||||||
> [!info]
|
> [!info]
|
||||||
> See [[distribution-equipment]].
|
> See [[distribution-equipment]].
|
||||||
|
|
||||||
1. Build Items in Distribution:
|
1. Build [[distribution-designations|designations]]
|
||||||
* Panelboards
|
|
||||||
* Switchboards
|
|
||||||
* Meter centers
|
|
||||||
* Generators
|
|
||||||
* Transfer switches
|
|
||||||
* Generator connection cabinets
|
|
||||||
* CT cabinets
|
|
||||||
* Power monitor
|
|
||||||
|
|
||||||
2. Takeoff Common Assemblies:
|
2. Takeoff riser scope, including designations and assemblies.
|
||||||
* XFMRs
|
|
||||||
* Disconnect switches
|
|
||||||
|
|
||||||
3. Takeoff Items in Item Database:
|
|
||||||
* Wireway (Trough/Gutter)
|
|
||||||
|
|
||||||
4. Takeoff Temp Assemblies:
|
|
||||||
* Fire Pump
|
|
||||||
* Fire Pump Controller
|
|
||||||
|
|
||||||
When building panelboards/switchboards,
|
|
||||||
add terminations according to an example from the schedules.
|
|
||||||
**Do not include feeder terminations.**
|
|
||||||
|
|
||||||
> [!important] Scope to Exclude
|
> [!important] Scope to Exclude
|
||||||
> * Tap Boxes
|
> * Tap Boxes
|
||||||
@@ -47,69 +26,21 @@ add terminations according to an example from the schedules.
|
|||||||
> * Grounding
|
> * Grounding
|
||||||
> * Elevator Room
|
> * Elevator Room
|
||||||
|
|
||||||
## By Equipment Type
|
## Takeoff
|
||||||
|
|
||||||
> [!tip] When in Doubt
|
* `Area` = _As shown_
|
||||||
> If the equipment is not listed below,
|
* `Phase` = "Switch Gear"
|
||||||
> use a distribution panel of equal amps.
|
* `System` = "SWG - Switchgear"
|
||||||
|
* `Bid Item` = "3 - Building"
|
||||||
|
|
||||||
### SPD's/TVSS's
|
### Transformers
|
||||||
|
|
||||||
> Name = "SPD"
|
1. `COMMON ASSEMBLIES`/`DISTRIBUTION`/`TRANSFORMERS`/...
|
||||||
|
|
||||||
Labor only.
|
### Disconnects
|
||||||
|
|
||||||
Specific item is not important, but I use
|
1. `COMMON ASSEMBLIES`/`DISTRIBUTION`/`MANUAL DISCONNECTS`/...
|
||||||
`SPLITTERS / SOCKETS / CABINETS`/`METER SOCKETS & CABINETS`/`METERING CURRENT TRANSFORMER`
|
|
||||||
(Labor = 1.5hrs)
|
|
||||||
for consistency.
|
|
||||||
|
|
||||||
### Submeters/Power Monitors
|
### Wireway
|
||||||
|
|
||||||
> Name = "Power Monitor"
|
1. `ITEM DATABASE`/???
|
||||||
|
|
||||||
See [[switchgear#SPD's/TVSS's]]
|
|
||||||
|
|
||||||
### Switchboards
|
|
||||||
|
|
||||||
> Name = "Switchboard - 2000A, 4-Section"
|
|
||||||
|
|
||||||
### Panelboards
|
|
||||||
|
|
||||||
> Name = "Panelboard - 600A, 2-Section"
|
|
||||||
|
|
||||||
`DISTRIBUTION`/`DIST PANELS & UNIT LOAD CENTERS`/...
|
|
||||||
|
|
||||||
### Disconnects and Enclosed Circuit Breakers
|
|
||||||
|
|
||||||
`COMMON ASSEMBLIES`/`DISTRIBUTION`/`MANUAL DISCONNECTS`/...
|
|
||||||
|
|
||||||
### Generators
|
|
||||||
|
|
||||||
> Name = "Generator - 250kW, Diesel"
|
|
||||||
|
|
||||||
Add `DISTRIBUTION FITTINGS`/`GENERATOR SET UP`.
|
|
||||||
|
|
||||||
### Generator Connection Cabinets
|
|
||||||
|
|
||||||
> Name = "GCC - 200A"
|
|
||||||
|
|
||||||
Use a Distribution Panel of equal amps.
|
|
||||||
Or a transfer switch.
|
|
||||||
|
|
||||||
### Transfer Switches
|
|
||||||
|
|
||||||
> Name = "Transfer Switch - 400A"
|
|
||||||
|
|
||||||
#### Transfer Switches 1200A+
|
|
||||||
|
|
||||||
Use 1200A and add an additional `TRANSFER SWITCH` item
|
|
||||||
to make up the remaining amps.
|
|
||||||
|
|
||||||
### Meter Centers
|
|
||||||
|
|
||||||
> Name = "Meter Center - 800A, 16-Can"
|
|
||||||
|
|
||||||
`SWITCHGEAR & METER CENTERS`/`METER CENTERS`/`... METERING SECTION`
|
|
||||||
|
|
||||||
Adjust Factor 1 for meter stacks, delete zeroed items.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user