Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/extensions/post-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { stripTypeAnnotation } from "../core/table-mutator";
import { toPlainText } from "../utils/link-renderer";
import { TableViewController } from "../services/table-view-controller";
import { TableViewRegistry } from "../services/table-view-registry";
import { SettingsService } from "../services/settings-service";
import { MarkdownTableData, MarkdownTableRow } from "../types";
import { isPrintMode } from "./print-mode";
import { TableRenderChild } from "./table-render-child";
Expand All @@ -13,14 +14,20 @@ const SKIP_CONTAINER_CLASSES = ["ms-notion-database-container", "ms-kanban-conta
export class TablePostProcessor {
private viewController: TableViewController;
private registry: TableViewRegistry;
private settingsService: SettingsService;

constructor(viewController: TableViewController, registry: TableViewRegistry) {
constructor(
viewController: TableViewController,
registry: TableViewRegistry,
settingsService: SettingsService
) {
this.viewController = viewController;
this.registry = registry;
this.settingsService = settingsService;
}

public process(el: HTMLElement, ctx: MarkdownPostProcessorContext): void {
if (isPrintMode(el)) {
if (isPrintMode(el) || !this.settingsService.getSettings().autoConvertMarkdownTables) {
return;
}

Expand Down
6 changes: 5 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export default class TableBasePlugin extends Plugin {

new CommandService(this).registerCommands();

const postProcessor = new TablePostProcessor(viewController, this.viewRegistry);
const postProcessor = new TablePostProcessor(
viewController,
this.viewRegistry,
this.settingsService
);
this.registerMarkdownPostProcessor((el, ctx) => postProcessor.process(el, ctx));

const codeBlockProcessor = new TableCodeBlockProcessor(viewController, this.viewRegistry);
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export type DateFormatOption =
export interface PluginSettings {
defaultTagFormat: TagFormat;
dateFormat?: DateFormatOption;
autoConvertMarkdownTables: boolean;
autoDetectMultiSelect: boolean;
multiSelectColumnNames: string[];
customTagColors: Record<string, TagColor>;
Expand All @@ -168,6 +169,7 @@ export interface PluginSettings {

export const DEFAULT_SETTINGS: PluginSettings = {
defaultTagFormat: "comma",
autoConvertMarkdownTables: true,
autoDetectMultiSelect: true,
multiSelectColumnNames: [
"Tags",
Expand Down
21 changes: 21 additions & 0 deletions src/ui/settings-tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export class TableBaseSettingTab extends PluginSettingTab {
}

return [
{
name: "Auto-convert Markdown tables",
desc: "Automatically convert standard Markdown tables into interactive TableBase tables.",
control: {
type: "toggle",
key: "autoConvertMarkdownTables",
},
},
{
name: "Auto-detect multi-select columns",
desc: "Automatically detect multi-select columns by analyzing cell values (lists, wikilinks, tags).",
Expand Down Expand Up @@ -149,6 +157,19 @@ export class TableBaseSettingTab extends PluginSettingTab {
const settings = this.settingsService.getSettings();
this.addHeading(containerEl, "Column detection");

new Setting(containerEl)
.setName("Auto-convert Markdown tables")
.setDesc(
"Automatically convert standard Markdown tables into interactive TableBase tables."
)
.addToggle((toggle) =>
toggle
.setValue(settings.autoConvertMarkdownTables)
.onChange(async (value) => {
await this.settingsService.updateSettings({ autoConvertMarkdownTables: value });
})
);

new Setting(containerEl)
.setName("Auto-detect multi-select columns")
.setDesc(
Expand Down
5 changes: 3 additions & 2 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,8 @@ input[type="text"].ms-filter-value-input:focus {
}

.ms-db-grid-table {
width: max-content;
min-width: 0;
width: 100%;
min-width: 100%;
border-collapse: separate;
border-spacing: 0;
table-layout: auto;
Expand Down Expand Up @@ -1201,6 +1201,7 @@ input[type="text"].ms-filter-value-input:focus {
min-height: 20px;
line-height: 1.4;
word-break: break-word;
overflow-wrap: anywhere;
}

.ms-cell-text-wrapper.is-number {
Expand Down
9 changes: 8 additions & 1 deletion tests/column-type-change.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,14 @@ describe("changing a column type from the header menu", () => {
"",
].join("\n");

const processor = new TablePostProcessor(controller, new TableViewRegistry());
const processor = new TablePostProcessor(
controller,
new TableViewRegistry(),
new SettingsService({
loadData: async () => null,
saveData: async () => undefined,
})
);
const ctx = {
docId: "doc",
sourcePath: "Notes/Test.md",
Expand Down
14 changes: 13 additions & 1 deletion tests/post-processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function createProcessor(sectionInfo?: SectionSource): {
new TableSyncService(new VaultService(app))
);

const processor = new TablePostProcessor(controller, new TableViewRegistry());
const processor = new TablePostProcessor(controller, new TableViewRegistry(), settingsService);

const ctx = {
docId: "doc",
Expand Down Expand Up @@ -110,6 +110,18 @@ describe("TablePostProcessor date columns", () => {
expect(addColTh?.querySelector(".ms-db-th-add-col-icon svg")).not.toBeNull();
});

it("should skip standard Markdown tables when auto-conversion is disabled", async () => {
const { processor, ctx, settingsService } = createProcessor();
await settingsService.updateSettings({ autoConvertMarkdownTables: false });
const wrapper = buildRenderedTable(["Task"], [["Buy bread"]]);

processor.process(wrapper, ctx);

expect(wrapper.querySelector(".ms-notion-database-container")).toBeNull();
expect(wrapper.querySelector("table")).not.toBeNull();
expect(ctx.addChild).not.toHaveBeenCalled();
});

it("should register the view for lifecycle teardown", () => {
const { processor, ctx } = createProcessor();
const wrapper = buildRenderedTable(["Task", "Due Date [date]"], [["A", "2026-09-15"]]);
Expand Down
1 change: 1 addition & 0 deletions tests/settings-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe("SettingsService", () => {
const loaded = await service.loadSettings();
expect(loaded.defaultTagFormat).toBe("wikilink");
expect(loaded.showRowNumbers).toBe(true);
expect(loaded.autoConvertMarkdownTables).toBe(true);
expect(loaded.autoDetectMultiSelect).toBe(DEFAULT_SETTINGS.autoDetectMultiSelect);
expect(storage.loadData).toHaveBeenCalledOnce();
});
Expand Down
18 changes: 16 additions & 2 deletions tests/settings-tab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,26 @@ describe("TableBaseSettingTab", () => {
const toggles = tab.containerEl.querySelectorAll<HTMLElement>(".checkbox-container");
expect(toggles.length).toBeGreaterThan(0);

const autoDetectToggle = toggles[0];
const autoDetectToggle = toggles[1];
autoDetectToggle.click();

expect(settingsService.getSettings().autoDetectMultiSelect).toBe(false);
});

it("should update autoConvertMarkdownTables when its toggle is clicked", async () => {
const plugin = createMockPlugin();
const settingsService = new SettingsService(plugin);
await settingsService.loadSettings();

const tab = new TableBaseSettingTab({} as App, plugin, settingsService);
tab.display();

const toggles = tab.containerEl.querySelectorAll<HTMLElement>(".checkbox-container");
toggles[0].click();

expect(settingsService.getSettings().autoConvertMarkdownTables).toBe(false);
});

it("should update multiSelectColumnNames when textarea changes", async () => {
const plugin = createMockPlugin();
const settingsService = new SettingsService(plugin);
Expand Down Expand Up @@ -106,7 +120,7 @@ describe("TableBaseSettingTab", () => {
tab.display();

const toggles = tab.containerEl.querySelectorAll<HTMLElement>(".checkbox-container");
const rowNumberToggle = toggles[1];
const rowNumberToggle = toggles[2];
expect(rowNumberToggle).toBeDefined();

rowNumberToggle.click();
Expand Down
Loading