Skip to content

Commit

Permalink
Add settings (#7)
Browse files Browse the repository at this point in the history
* Added setting names and defaults

* Added the settings tab file

* Registered the settings tab

* Added a setting to set the search result limit

* Added a setting to specify what content will be indexed in the search

* Added a setting for removing the block id from the block contents

* Added a setting for file name display in search results

* Added a setting for parsing markdown links in block contents

* Added the settings tab reference for parseLinks

* Added a setting for link format and if to use selection as display text

* Added a setting for using selected text as initial search query

* Semicolons

* Added tsdocs comments to BlockrefferSettings

Co-authored-by: Tyler Nieman <[email protected]>

* Fixed typo in comment

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the fileName setting

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the selectedTextAsSearch setting

Co-authored-by: Tyler Nieman <[email protected]>

* Made fileName a constant in the settings defaults

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the keepText setting

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the removeIdFromContent setting

Co-authored-by: Tyler Nieman <[email protected]>

* Handle fallback to default on empty format setting string and added invalid format indicator

* Restricted value to "base" | "path" for fileName

* Rephrased the description of the toSearch setting

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the toSearch setting

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased the description of the toSearch setting

Co-authored-by: Tyler Nieman <[email protected]>

* Rephrased name and description of format setting

* Changed all instances of link to backlink where appropriate

* Removed the ^block-id from item.content in getItemText

* Fixed typo in formatRegex

---------

Co-authored-by: Tyler Nieman <[email protected]>
  • Loading branch information
GuardKenzie and tyler-dot-earth authored Nov 17, 2024
1 parent 400975c commit dc4fb0b
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 13 deletions.
76 changes: 63 additions & 13 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ import {
TFile,
} from "obsidian";

import { BlockrefferSettings, DEFAULT_SETTINGS } from "settings/settings"
import { BlockrefferSettingTab } from "settings/settingsTab"

export default class Blockreffer extends Plugin {
settings: BlockrefferSettings;

async onload() {
this.loadSettings();

this.addCommand({
id: "open-block-search",
name: "Search blocks with references",
Expand Down Expand Up @@ -46,6 +53,8 @@ export default class Blockreffer extends Plugin {
}).open();
},
});

this.addSettingTab(new BlockrefferSettingTab(this.app, this));
}

onunload() {}
Expand Down Expand Up @@ -90,6 +99,14 @@ export default class Blockreffer extends Plugin {

return blockSuggestions;
}

async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}

async saveSettings() {
await this.saveData(this.settings);
}
}

interface BlockSuggestion {
Expand Down Expand Up @@ -121,7 +138,9 @@ class BlockSearchModal extends FuzzySuggestModal<BlockSuggestion> {
this.blocks = blocks;
this.action = action;
this.setPlaceholder("Search for ^referenced blocks...");
this.limit = 10; // TODO make configurable


this.limit = this.plugin.settings.searchLimit;

// TODO
// this.setInstructions([
Expand All @@ -136,21 +155,40 @@ class BlockSearchModal extends FuzzySuggestModal<BlockSuggestion> {
// ]);
}

onOpen() {
super.onOpen()

if (this.plugin.settings.selectedTextAsSearch == false) return;

const editor = this.app.workspace.getActiveViewOfType(MarkdownView)?.editor;
if (editor) {
this.inputEl.value = editor.getSelection();

// We need to trigger the input event to make the results update
this.inputEl.dispatchEvent(new Event("input"));
}
}

getItems(): BlockSuggestion[] {
return this.blocks;
}

// fuzzy-searchable content
getItemText(item: BlockSuggestion): string {
// TODO make this configurable maybe?
return item.content + item.file.path + item.id;
let toSearch = ""

if (this.plugin.settings.toSearch.content) toSearch += item.content.replace(`^${item.id}`, "").trim();
if (this.plugin.settings.toSearch.path ) toSearch += item.file.path;
if (this.plugin.settings.toSearch.id ) toSearch += item.id;

return toSearch;
}

renderSuggestion({ item }: FuzzyMatch<BlockSuggestion>, el: HTMLElement) {
// TODO make this optional
const contentWithoutId = item.content.replace(`^${item.id}`, "").trim(); // cases like https://github.com/tyler-dot-earth/obsidian-blockreffer/issues/5
const contentWithoutId = this.plugin.settings.removeIdFromContent
? item.content.replace(`^${item.id}`, "").trim() // cases like https://github.com/tyler-dot-earth/obsidian-blockreffer/issues/5
: item.content.trim();

// TODO make this optional
function unlinkfy(text: string): DocumentFragment {
const fragment = document.createDocumentFragment();
let lastIndex = 0;
Expand Down Expand Up @@ -180,18 +218,24 @@ class BlockSearchModal extends FuzzySuggestModal<BlockSuggestion> {

return fragment;
}

const sansLink = unlinkfy(contentWithoutId);
const withLink = document.createDocumentFragment()
.appendChild(document.createTextNode(contentWithoutId));

const suggestionBlockText = this.plugin.settings.parseLinks ? sansLink : withLink;

el.createDiv({ cls: "suggestion-content" }, (contentDiv) => {
contentDiv
.createDiv({
// text: sansLink,
cls: "blockreffer-suggestion-block-text",
})
.appendChild(sansLink);
.appendChild(suggestionBlockText);

const from = this.plugin.settings.fileName == "base"
? item.file.basename
: item.file.path;

// TODO setting for path vs basename
const from = item.file.basename;
contentDiv.createEl("small", {
text: `${from}#^${item.id}`,
cls: "blockreffer-suggestion-block-file",
Expand All @@ -204,10 +248,16 @@ class BlockSearchModal extends FuzzySuggestModal<BlockSuggestion> {
const editor =
this.app.workspace.getActiveViewOfType(MarkdownView)?.editor;
if (editor) {
const selection = editor.getSelection();
// Build the block
const link = this.plugin.settings.keepText && selection
? `[[${item.file.basename}#^${item.id}|${selection}]]`
: `[[${item.file.basename}#^${item.id}]]`;

const replacement = this.plugin.settings.format.replace("{backlink}", link);

// Embed the block using the ref
editor.replaceSelection(
`![[${item.file.basename}#^${item.id}]]`,
);
editor.replaceSelection(replacement);
}
}

Expand Down
51 changes: 51 additions & 0 deletions settings/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export interface BlockrefferSettings {
/** The format string for inserting a backlink.
* @example `!{link}` becomes `![[link]]
*/
format: string;

/** Whether the selected text should be retained as the link display text. */
keepText: boolean;

/** Whether links should be parsed using the `unlinkfy` method. */
parseLinks: boolean;

/** Uses the selected text as the initial search value. */
selectedTextAsSearch: boolean;

/** Specifies content that should be searched. */
toSearch: {
/** Whether to search within file content. */
content: boolean;

/** Whether to search for matches in the file path. */
path: boolean;

/** Whether to search for matches by file ID. */
id: boolean;
};

/** Maximum number of search results to display. */
searchLimit: number;

/** Whether to remove `^block-id` from the content. */
removeIdFromContent: boolean;

/** How the file name should be displayed: "path" for full path or "base" for name only. */
fileName: "path" | "base";
}

export const DEFAULT_SETTINGS: BlockrefferSettings = {
format: '!{backlink}',
keepText: false,
parseLinks: true,
selectedTextAsSearch: false,
toSearch: {
content: true,
path: true,
id: true
},
searchLimit: 10,
removeIdFromContent: true,
fileName: "base" as const,
}
172 changes: 172 additions & 0 deletions settings/settingsTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import {
PluginSettingTab,
Setting,
App
} from "obsidian";

import Blockreffer from "main";
import { DEFAULT_SETTINGS } from "./settings";

const formatRegex = /\{backlink\}/
const ERROR_COLOR = "var(--background-modifier-error)"

export class BlockrefferSettingTab extends PluginSettingTab {
plugin: Blockreffer;

constructor(app: App, plugin: Blockreffer) {
super(app, plugin);
this.plugin = plugin;
}

display(): void {
const {containerEl} = this;

containerEl.empty();

new Setting(containerEl)
.setHeading()
.setName("How do you want your backlink?");

new Setting(containerEl)
.setName('Backlink format')
.setDesc('How your backlink will be inserted into the document. Use {backlink} as a placeholder for the actual backlink.')
.addText(text => text
.setPlaceholder('!{backlink}')
.setValue(this.plugin.settings.format)
.onChange(async (value) => {
// Check if the field contains a {backlink}
if (formatRegex.test(value)) {
text.inputEl.style.borderColor = ""
}
else {
text.inputEl.style.borderColor = ERROR_COLOR
}

// Check if empty and reset to default if it is
if (value === "") this.plugin.settings.format = DEFAULT_SETTINGS.format;
else this.plugin.settings.format = value;

await this.plugin.saveSettings();
})
.then((text) => {
// Check for invalid format on open
if (!formatRegex.test(text.getValue())) {
text.inputEl.style.borderColor = ERROR_COLOR
}
})
);

new Setting(containerEl)
.setName("Use selected text as backlink display text")
.setDesc("Use selected text as the backlink alias (the bit that goes after the | symbol).")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.keepText)
.onChange(async (value) => {
this.plugin.settings.keepText = value;
await this.plugin.saveSettings();
})
);

/* === Search settings === */
new Setting(containerEl)
.setHeading()
.setName("Search settings");

new Setting(containerEl)
.setName("Parse links")
.setDesc("Should markdown links be displayed as just their display text in search results?")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.parseLinks)
.onChange(async (value) => {
this.plugin.settings.parseLinks = value;
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Remove block id from block content")
.setDesc("Do not display the ^block-id in search results. It will still be displayed beneath the block content.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.removeIdFromContent)
.onChange(async (value) => {
this.plugin.settings.removeIdFromContent = value;
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Use selected text as initial search")
.setDesc("If true, selected text will be used when you open the search box.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.selectedTextAsSearch)
.onChange(async (value) => {
this.plugin.settings.selectedTextAsSearch = value;
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Search limit")
.setDesc("The number of search results to display.")
.addSlider(slider => slider
.setLimits(1,50,1)
.setValue(this.plugin.settings.searchLimit)
.setDynamicTooltip()
.onChange(async (value) => {
this.plugin.settings.searchLimit = value
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("File name in result")
.setDesc("Show just the file's name or the/full/path.md in search results?")
.addDropdown(dropdown => dropdown
.addOption("base", "File name")
.addOption("path", "File path")
.setValue(this.plugin.settings.fileName)
.onChange(async (value: "base" | "path") => {
this.plugin.settings.fileName = value
await this.plugin.saveSettings()
})
);

/* === What to search === */
new Setting(containerEl)
.setName("What to search")
.setHeading();

new Setting(containerEl)
.setName("Block content")
.setDesc("Search text inside blocks.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.toSearch.content)
.onChange(async (value) => {
this.plugin.settings.toSearch.content = value
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("File path")
.setDesc("Search file path and name.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.toSearch.path)
.onChange(async (value) => {
this.plugin.settings.toSearch.path = value
await this.plugin.saveSettings();
})
);

new Setting(containerEl)
.setName("Block id")
.setDesc("Search ^block-ids.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.toSearch.id)
.onChange(async (value) => {
this.plugin.settings.toSearch.id = value
await this.plugin.saveSettings();
})
);
}
}

0 comments on commit dc4fb0b

Please sign in to comment.