mirror of
https://github.com/moranrs/table-master.git
synced 2026-07-22 06:53:11 +00:00
- src/editor/actions.ts: drop two unnecessary type assertions on navigator.clipboard
- src/i18n/en.ts: rewrite 9 strings into sentence case (drop button-name parentheticals like ' (Tab)' and 'Excel/web')
- src/i18n/zh.ts: drop now-unused plugin.name key
- src/main.ts: split async init out of onload into a private bootstrap()
so Plugin.onload's declared void return type is preserved
- src/main.ts, src/i18n/index.ts, src/editor/actions.ts: remove unused
'_' catch parameters (use bare 'catch')
- src/render/tableRenderer.ts: replace 'Function' with an explicit
MarkdownRenderFn signature for the renderer.render fallback
- src/settings.ts: drop the manual createEl('h2', ...) heading;
Obsidian renders the plugin name as the settings-tab heading
- src/ui/floatingToolbar.ts: replace inline element.style.display
writes with an 'is-hidden' CSS class toggle, drop redundant
inline 'position: fixed' (now CSS-only), and parse SVG icons via
DOMParser instead of innerHTML
- styles.css: add .tm-floating-toolbar.is-hidden rule
- add eslint.config.mjs + dev dependencies so contributors can
reproduce ObsidianReviewBot's checks locally
213 lines
6 KiB
CSS
213 lines
6 KiB
CSS
/* ===== Floating toolbar ===== */
|
|
.tm-floating-toolbar {
|
|
/* We mount on <body> and rely on `position: fixed` so transformed editor
|
|
* ancestors cannot anchor the toolbar to themselves. (Position lives in
|
|
* CSS rather than inline styles; only the dynamic `top`/`left` are set
|
|
* imperatively by the view plugin.) */
|
|
position: fixed;
|
|
/* Some Obsidian themes bump table-widget z-index up into the 30-40s; keep
|
|
* the toolbar above any of them so it's never visually buried. */
|
|
z-index: 100;
|
|
pointer-events: auto;
|
|
/* Stack functional groups vertically — each group becomes its own row.
|
|
* The user explicitly asked for this layout so the toolbar is compact
|
|
* and not stretched across the full editor width. */
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 2px;
|
|
padding: 4px;
|
|
background: var(--background-primary);
|
|
border: 1px solid var(--background-modifier-border);
|
|
border-radius: 6px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
font-size: var(--font-ui-smaller);
|
|
user-select: none;
|
|
}
|
|
|
|
.tm-floating-toolbar.is-hidden {
|
|
/* Toggled by the view plugin via classList instead of inline display
|
|
* styles. `!important` is used so a theme that bumps `display` on
|
|
* `.tm-floating-toolbar` cannot accidentally re-show the toolbar while
|
|
* the plugin considers it hidden. */
|
|
display: none !important;
|
|
}
|
|
|
|
.tm-floating-toolbar .tm-group {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 1px;
|
|
padding: 2px 3px;
|
|
/* Visual separator between vertically-stacked groups. */
|
|
border-bottom: 1px solid var(--background-modifier-border);
|
|
}
|
|
|
|
.tm-floating-toolbar .tm-group:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.tm-floating-toolbar button.tm-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 26px;
|
|
height: 26px;
|
|
padding: 0 6px;
|
|
background: transparent;
|
|
border: none;
|
|
border-radius: 4px;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.tm-floating-toolbar button.tm-btn:hover {
|
|
background: var(--background-modifier-hover);
|
|
color: var(--text-normal);
|
|
}
|
|
|
|
.tm-floating-toolbar button.tm-btn.is-active {
|
|
background: var(--background-modifier-active-hover);
|
|
color: var(--text-accent);
|
|
}
|
|
|
|
.tm-floating-toolbar button.tm-btn .tm-icon {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
|
|
/* ===== Modal grid editor ===== */
|
|
.tm-modal .modal-content {
|
|
padding: 0;
|
|
}
|
|
|
|
.tm-grid-toolbar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 4px;
|
|
padding: 8px 12px;
|
|
border-bottom: 1px solid var(--background-modifier-border);
|
|
background: var(--background-secondary);
|
|
}
|
|
|
|
.tm-grid-toolbar button {
|
|
height: 28px;
|
|
padding: 0 10px;
|
|
}
|
|
|
|
.tm-grid-wrap {
|
|
max-height: 60vh;
|
|
overflow: auto;
|
|
padding: 8px;
|
|
}
|
|
|
|
table.tm-grid {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
table-layout: fixed;
|
|
}
|
|
|
|
table.tm-grid th,
|
|
table.tm-grid td {
|
|
border: 1px solid var(--background-modifier-border);
|
|
padding: 4px 8px;
|
|
min-width: 80px;
|
|
vertical-align: top;
|
|
position: relative;
|
|
}
|
|
|
|
table.tm-grid th {
|
|
background: var(--background-secondary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
table.tm-grid td.tm-selected,
|
|
table.tm-grid th.tm-selected {
|
|
outline: 2px solid var(--interactive-accent);
|
|
outline-offset: -2px;
|
|
background: var(--background-modifier-hover);
|
|
}
|
|
|
|
table.tm-grid .tm-cell-edit {
|
|
display: block;
|
|
width: 100%;
|
|
min-height: 1.4em;
|
|
outline: none;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.tm-grid-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
padding: 10px 12px;
|
|
border-top: 1px solid var(--background-modifier-border);
|
|
background: var(--background-secondary);
|
|
}
|
|
|
|
/* ===== Reading view & Live Preview rebuilt tables ===== */
|
|
/* When the post-processor / live-preview view plugin rewrites a table,
|
|
* Obsidian's widget-scoped CSS (e.g. `.cm-table-widget td`) no longer matches
|
|
* because we replace `<table>`'s children. Re-establish the cell metrics here
|
|
* so the rebuilt table never looks more cramped than the original GFM render.
|
|
*/
|
|
table.tm-rendered {
|
|
border-collapse: collapse;
|
|
margin: 0.5em 0;
|
|
}
|
|
|
|
table.tm-rendered caption {
|
|
caption-side: top;
|
|
font-style: italic;
|
|
color: var(--text-muted);
|
|
padding: 4px 0;
|
|
text-align: center;
|
|
}
|
|
|
|
table.tm-rendered th,
|
|
table.tm-rendered td {
|
|
padding: var(--table-cell-padding, 6px 12px);
|
|
border: 1px solid var(--background-modifier-border);
|
|
vertical-align: top;
|
|
line-height: var(--line-height-normal, 1.5);
|
|
}
|
|
|
|
table.tm-rendered th {
|
|
background: var(--background-secondary);
|
|
font-weight: var(--font-semibold, 600);
|
|
}
|
|
|
|
table.tm-rendered tbody + tbody {
|
|
border-top: 2px solid var(--background-modifier-border);
|
|
}
|
|
|
|
/* Highlight merged anchors so the user can spot the merged region at a
|
|
* glance. The legacy `.tm-merged-anchor` class is kept for backward compat,
|
|
* but the actual marker on rendered tables is `data-tm-merge="anchor"`
|
|
* (set by Live Preview) and the `[rowspan]` / `[colspan]` attributes
|
|
* (set by Reading-view rebuild + grid editor). */
|
|
table.tm-rendered td.tm-merged-anchor,
|
|
table.tm-rendered th.tm-merged-anchor,
|
|
table.tm-rendered td[rowspan]:not([rowspan="1"]),
|
|
table.tm-rendered th[rowspan]:not([rowspan="1"]),
|
|
table.tm-rendered td[colspan]:not([colspan="1"]),
|
|
table.tm-rendered th[colspan]:not([colspan="1"]),
|
|
table td[data-tm-merge="anchor"],
|
|
table th[data-tm-merge="anchor"] {
|
|
background-color: var(--background-secondary-alt);
|
|
}
|
|
|
|
/* Vertically center the text inside any cell that spans more than one row.
|
|
* Covers all three renderers: Reading view (`table.tm-rendered td[rowspan]`),
|
|
* Live Preview (anchor cells flagged with `data-tm-merge="anchor"`), and the
|
|
* modal grid editor (`table.tm-grid`). Merging up / down should feel
|
|
* symmetric — the merged text sits between the rows it now spans. */
|
|
table.tm-rendered td[rowspan]:not([rowspan="1"]),
|
|
table.tm-rendered th[rowspan]:not([rowspan="1"]),
|
|
table td[data-tm-merge="anchor"][rowspan]:not([rowspan="1"]),
|
|
table th[data-tm-merge="anchor"][rowspan]:not([rowspan="1"]),
|
|
table.tm-grid td[rowspan]:not([rowspan="1"]),
|
|
table.tm-grid th[rowspan]:not([rowspan="1"]) {
|
|
vertical-align: middle;
|
|
}
|