feat(prefs): configurável a tecla Tab — N espaços (padrão 4) ou \t
- Diálogo de preferências: seletor "insere espaços / insere tabulação" + campo de quantidade (1–16, validado e clampado) - tab-size do textarea e da camada de realce passa a seguir o valor via --tab-size, mantendo as duas camadas alinhadas - Persistido em localStorage; README atualizado
This commit is contained in:
1 parent
7e89207b70
commit
70887b5b48
4 files changed
+25
-6
No files matched your search
@@ -55,6 +55,9 @@ restauração) e autenticação por **token** (Bearer para API / cookie HttpOnly
|
|||||||
- **Marcador de coluna** customizável — padrão **80** (linha vertical no editor, exibida com
|
- **Marcador de coluna** customizável — padrão **80** (linha vertical no editor, exibida com
|
||||||
quebra de linha desligada, como no Mousepad/gedit).
|
quebra de linha desligada, como no Mousepad/gedit).
|
||||||
- **Quebrar linha** ligado/desligável (alternável também pelo menu Exibir).
|
- **Quebrar linha** ligado/desligável (alternável também pelo menu Exibir).
|
||||||
|
- **Tecla Tab**: insere N espaços (padrão **4**, configurável 1–16) **ou** o caractere de
|
||||||
|
tabulação `\t`; o valor também define a largura exibida do `\t` (`tab-size`) no editor e no
|
||||||
|
realce, mantendo as camadas alinhadas.
|
||||||
- **Fonte** (DejaVu Sans Mono, Ubuntu Mono, Cascadia Code, Liberation Mono, Courier New ou
|
- **Fonte** (DejaVu Sans Mono, Ubuntu Mono, Cascadia Code, Liberation Mono, Courier New ou
|
||||||
monoespaçada do sistema) e **tamanho** (10–32 px).
|
monoespaçada do sistema) e **tamanho** (10–32 px).
|
||||||
- **Esquema de cores / tema**: Claro (Greybird), Escuro (Adwaita), Solarizado claro e
|
- **Esquema de cores / tema**: Claro (Greybird), Escuro (Adwaita), Solarizado claro e
|
||||||
|
|||||||
+3
-2
@@ -309,7 +309,7 @@ body.no-gutter #gutter { display: none; }
|
|||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
tab-size: 4;
|
tab-size: var(--tab-size, 4);
|
||||||
}
|
}
|
||||||
#hl.nowrap { white-space: pre; overflow-wrap: normal; }
|
#hl.nowrap { white-space: pre; overflow-wrap: normal; }
|
||||||
.hl-line { min-height: var(--line-h); }
|
.hl-line { min-height: var(--line-h); }
|
||||||
@@ -339,7 +339,7 @@ body.no-gutter #gutter { display: none; }
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
caret-color: var(--fg);
|
caret-color: var(--fg);
|
||||||
tab-size: 4;
|
tab-size: var(--tab-size, 4);
|
||||||
}
|
}
|
||||||
#editor:focus { outline: none; }
|
#editor:focus { outline: none; }
|
||||||
#editor::selection { background: rgba(53, 132, 228, .30); }
|
#editor::selection { background: rgba(53, 132, 228, .30); }
|
||||||
@@ -894,6 +894,7 @@ html[data-theme="solar-escuro"] #revisions-list li:hover { background: #0c4450;
|
|||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
}
|
}
|
||||||
|
.dialog .row select.compact { flex: 0 1 auto; }
|
||||||
.dialog .num { width: 74px; flex: none; }
|
.dialog .num { width: 74px; flex: none; }
|
||||||
|
|
||||||
/* diálogos no celular (depois das regras base de .dialog) */
|
/* diálogos no celular (depois das regras base de .dialog) */
|
||||||
|
|||||||
@@ -34,6 +34,14 @@
|
|||||||
<label class="row"><input type="checkbox" id="pf-colmark"> Marcar coluna
|
<label class="row"><input type="checkbox" id="pf-colmark"> Marcar coluna
|
||||||
<input type="number" id="pf-col" min="20" max="320" step="1" class="num"> (padrão 80)</label>
|
<input type="number" id="pf-col" min="20" max="320" step="1" class="num"> (padrão 80)</label>
|
||||||
<label class="row"><input type="checkbox" id="pf-hl"> Colorir sintaxe (Markdown e HTML)</label>
|
<label class="row"><input type="checkbox" id="pf-hl"> Colorir sintaxe (Markdown e HTML)</label>
|
||||||
|
<label class="row">Tecla Tab
|
||||||
|
<select id="pf-tabmode" class="compact">
|
||||||
|
<option value="spaces">insere espaços</option>
|
||||||
|
<option value="tab">insere tabulação (\t)</option>
|
||||||
|
</select>
|
||||||
|
<input type="number" id="pf-tabsize" min="1" max="16" step="1" class="num"
|
||||||
|
title="Quantidade de espaços inseridos — e largura exibida do caractere \t"> espaços
|
||||||
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Fonte e tema</legend>
|
<legend>Fonte e tema</legend>
|
||||||
|
|||||||
+11
-4
@@ -687,11 +687,11 @@
|
|||||||
refreshPreviewIfOpen();
|
refreshPreviewIfOpen();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tab insere 4 espaços em vez de sair do textarea.
|
// Tab: insere N espaços ou \t conforme as preferências (nunca troca de foco).
|
||||||
E.editor.addEventListener('keydown', (e) => {
|
E.editor.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Tab') {
|
if (e.key === 'Tab' && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
insertText(' ');
|
insertText(prefs.tabSpaces ? ' '.repeat(prefs.tabSize) : '\t');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -819,7 +819,7 @@
|
|||||||
/* ------------------------------------------------------- preferências */
|
/* ------------------------------------------------------- preferências */
|
||||||
|
|
||||||
const PREFS_KEY = 'notas_prefs';
|
const PREFS_KEY = 'notas_prefs';
|
||||||
const PREFS_DEFAULT = { gutter: true, wrap: true, colmark: true, col: 80, hl: true, font: 'mono', size: 14, theme: 'claro' };
|
const PREFS_DEFAULT = { gutter: true, wrap: true, colmark: true, col: 80, hl: true, tabSpaces: true, tabSize: 4, font: 'mono', size: 14, theme: 'claro' };
|
||||||
const THEMES = ['claro', 'escuro', 'solar-claro', 'solar-escuro'];
|
const THEMES = ['claro', 'escuro', 'solar-claro', 'solar-escuro'];
|
||||||
const FONT_STACKS = {
|
const FONT_STACKS = {
|
||||||
mono: '"DejaVu Sans Mono", "Ubuntu Mono", "Cascadia Code", Consolas, monospace',
|
mono: '"DejaVu Sans Mono", "Ubuntu Mono", "Cascadia Code", Consolas, monospace',
|
||||||
@@ -839,6 +839,7 @@
|
|||||||
}
|
}
|
||||||
p.col = Math.min(320, Math.max(20, Math.round(p.col) || 80));
|
p.col = Math.min(320, Math.max(20, Math.round(p.col) || 80));
|
||||||
p.size = Math.min(32, Math.max(10, Math.round(p.size) || 14));
|
p.size = Math.min(32, Math.max(10, Math.round(p.size) || 14));
|
||||||
|
p.tabSize = Math.min(16, Math.max(1, Math.round(p.tabSize) || 4));
|
||||||
if (!FONT_STACKS[p.font]) p.font = 'mono';
|
if (!FONT_STACKS[p.font]) p.font = 'mono';
|
||||||
if (!THEMES.includes(p.theme)) p.theme = 'claro';
|
if (!THEMES.includes(p.theme)) p.theme = 'claro';
|
||||||
return p;
|
return p;
|
||||||
@@ -852,6 +853,7 @@
|
|||||||
root.style.setProperty('--editor-font', FONT_STACKS[prefs.font]);
|
root.style.setProperty('--editor-font', FONT_STACKS[prefs.font]);
|
||||||
root.style.setProperty('--editor-size', prefs.size + 'px');
|
root.style.setProperty('--editor-size', prefs.size + 'px');
|
||||||
root.style.setProperty('--line-h', Math.round(prefs.size * 1.55) + 'px');
|
root.style.setProperty('--line-h', Math.round(prefs.size * 1.55) + 'px');
|
||||||
|
root.style.setProperty('--tab-size', String(prefs.tabSize));
|
||||||
root.dataset.theme = prefs.theme;
|
root.dataset.theme = prefs.theme;
|
||||||
document.body.classList.toggle('no-gutter', !prefs.gutter);
|
document.body.classList.toggle('no-gutter', !prefs.gutter);
|
||||||
if (prefs.wrap) E.editor.removeAttribute('wrap');
|
if (prefs.wrap) E.editor.removeAttribute('wrap');
|
||||||
@@ -1066,6 +1068,7 @@
|
|||||||
const PF = {
|
const PF = {
|
||||||
overlay: $('#prefs-overlay'), form: $('#prefs-form'), gutter: $('#pf-gutter'),
|
overlay: $('#prefs-overlay'), form: $('#prefs-form'), gutter: $('#pf-gutter'),
|
||||||
wrap: $('#pf-wrap'), colmark: $('#pf-colmark'), col: $('#pf-col'), hl: $('#pf-hl'),
|
wrap: $('#pf-wrap'), colmark: $('#pf-colmark'), col: $('#pf-col'), hl: $('#pf-hl'),
|
||||||
|
tabmode: $('#pf-tabmode'), tabsize: $('#pf-tabsize'),
|
||||||
font: $('#pf-font'), size: $('#pf-size'), theme: $('#pf-theme'),
|
font: $('#pf-font'), size: $('#pf-size'), theme: $('#pf-theme'),
|
||||||
reset: $('#pf-reset'), cancel: $('#pf-cancel'),
|
reset: $('#pf-reset'), cancel: $('#pf-cancel'),
|
||||||
};
|
};
|
||||||
@@ -1077,6 +1080,8 @@
|
|||||||
PF.colmark.checked = prefs.colmark;
|
PF.colmark.checked = prefs.colmark;
|
||||||
PF.col.value = prefs.col;
|
PF.col.value = prefs.col;
|
||||||
PF.hl.checked = prefs.hl;
|
PF.hl.checked = prefs.hl;
|
||||||
|
PF.tabmode.value = prefs.tabSpaces ? 'spaces' : 'tab';
|
||||||
|
PF.tabsize.value = prefs.tabSize;
|
||||||
PF.font.value = prefs.font;
|
PF.font.value = prefs.font;
|
||||||
PF.size.value = prefs.size;
|
PF.size.value = prefs.size;
|
||||||
PF.theme.value = prefs.theme;
|
PF.theme.value = prefs.theme;
|
||||||
@@ -1088,6 +1093,8 @@
|
|||||||
prefs.colmark = PF.colmark.checked;
|
prefs.colmark = PF.colmark.checked;
|
||||||
prefs.col = Math.min(320, Math.max(20, parseInt(PF.col.value, 10) || 80));
|
prefs.col = Math.min(320, Math.max(20, parseInt(PF.col.value, 10) || 80));
|
||||||
prefs.hl = PF.hl.checked;
|
prefs.hl = PF.hl.checked;
|
||||||
|
prefs.tabSpaces = PF.tabmode.value !== 'tab';
|
||||||
|
prefs.tabSize = Math.min(16, Math.max(1, parseInt(PF.tabsize.value, 10) || 4));
|
||||||
prefs.font = FONT_STACKS[PF.font.value] ? PF.font.value : 'mono';
|
prefs.font = FONT_STACKS[PF.font.value] ? PF.font.value : 'mono';
|
||||||
prefs.size = Math.min(32, Math.max(10, parseInt(PF.size.value, 10) || 14));
|
prefs.size = Math.min(32, Math.max(10, parseInt(PF.size.value, 10) || 14));
|
||||||
prefs.theme = THEMES.includes(PF.theme.value) ? PF.theme.value : 'claro';
|
prefs.theme = THEMES.includes(PF.theme.value) ? PF.theme.value : 'claro';
|
||||||
|
|||||||
Reference in new issue
Block a user