ozi-editor
Versão: 3.1.0 — Atualizado em: 2026-06-01
Você tem a escolha de editor html ou editor markdown na mesma ferramenta.
Descrição
Editor visual ativado sobre um <textarea>, com suporte a dois modos: HTML e Markdown. O <textarea> continua sendo o campo real de envio — o plugin cria uma interface visual sobre ele, mantendo compatibilidade natural com formulários, Livewire e qualquer backend PHP.
O type é declarado diretamente no atributo identificador:
data-ozi-editor-html="key" <!-- editor HTML -->
data-ozi-editor-md="key" <!-- editor Markdown -->
Zero ambiguidade — o type é visível de relance no template, sem atributo extra.
O modo Markdown requer o arquivo complementar ozi-editor-md.js.
Recursos
- Dois modos — HTML rico ou Markdown com preview visual
- Toolbar configurável — ferramentas, grupos e quebras de linha via atributo
- Themes de toolbar — presets built-in e presets do dev via
oziConf - Classes CSS customizadas — dropdown de estilos aplicáveis ao texto selecionado
- Headings — dropdown h1–h6 na toolbar
- Sanitização — remove tags fora do conjunto permitido ao colar conteúdo externo
- Validação — campo obrigatório com mensagem customizada e integração com
ozi-validate - Disabled — bloqueia edição e toolbar programaticamente
- Cor customizável —
data-ozi-editor-uicolorcontrola foco e botões ativos - Dark mode — via
[data-ozi-theme="dark"]e@media (prefers-color-scheme: dark) - Compatível com Livewire — re-init via
OZI.hooks.afterRender - API pública — leitura, escrita, disable, reload e destroy por chave
Exemplos
[1] Simples — HTML e Markdown
<!-- Editor HTML -->
<textarea
name="conteudo"
data-ozi-editor-html="conteudo">
</textarea>
<!-- Editor Markdown -->
<textarea
name="conteudo"
data-ozi-editor-md="conteudo">
</textarea>
[2] Custom simples — HTML e Markdown
<!-- Editor HTML -->
<textarea
name="descricao"
data-ozi-editor-html="descricao"
data-ozi-editor-tools="bold, italic, underline, ul, codeblock, table"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
<!-- Editor Markdown -->
<textarea
name="descricao"
data-ozi-editor-md="descricao"
data-ozi-editor-tools="bold, italic, ul, codeblock, table"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
[3] Toolbar agrupada — HTML e Markdown
[ ] agrupa botões visualmente — , separa itens — ; quebra a linha da toolbar.
<!-- Editor HTML -->
<textarea
name="descricao"
data-ozi-editor-html="descricao"
data-ozi-editor-tools="[bold,italic,underline], [ul,ol], codeblock; table, clear, [left,center,right], source"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
<!-- Editor Markdown -->
<textarea
name="descricao"
data-ozi-editor-md="descricao"
data-ozi-editor-tools="[bold,italic], [ul,ol], codeblock; table, source"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
| Sintaxe | Efeito |
|---|---|
[bold,italic] |
Agrupa os botões visualmente |
, |
Separa itens dentro e fora de grupos |
; |
Quebra a linha da toolbar |
left,center,righteclearnão estão disponíveis no modo Markdown — se declarados, aparecem como?(inativo).
[4] Classes CSS e headings — HTML e Markdown
<!-- Editor HTML -->
<textarea
name="descricao"
data-ozi-editor-html="descricao"
data-ozi-editor-tools="[bold,italic,underline], classes, [ul,ol], codeblock; heading, table, clear, [left,center,right], source"
data-ozi-editor-class="text-success:Sucesso, text-info:Info, text-danger:Perigo"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
<!-- Editor Markdown -->
<textarea
name="descricao"
data-ozi-editor-md="descricao"
data-ozi-editor-tools="[bold,italic], [ul,ol], codeblock; heading, table, source"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
O botão
classessó aparece na toolbar sedata-ozi-editor-classestiver declarado com ao menos uma entrada válida. No modo Markdown o dev pode usá-lo conscientemente — gera HTML literal no Markdown.
[5] Editor HTML — Themes de toolbar
Themes são atalhos para strings de toolbar pré-definidas. Evitam repetir configuração em cada elemento.
Themes built-in para HTML:
| Theme | Toolbar |
|---|---|
minimal |
[bold,italic,underline]; source |
standard |
[bold,italic,underline]; heading; [ul,ol]; codeblock,clear; source |
full |
[bold,italic,underline], [ul,ol], [left,center,right]; [heading,classes], table, clear, codeblock, source |
blog |
[bold,italic,underline]; heading; [ul,ol]; table,clear; classes,source |
code |
[bold,italic,underline]; codeblock,source |
Usando um theme built-in:
<textarea
name="descricao"
data-ozi-editor-html="descricao"
data-ozi-editor-theme="blog"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
Criando um theme customizado via oziConf:
<textarea
name="descricao"
data-ozi-editor-html="descricao"
data-ozi-editor-theme="custom"
data-ozi-editor-class="text-success:Sucesso, text-info:Info, text-danger:Perigo"
data-ozi-editor-uicolor="#9AB8F3"
data-ozi-editor-placeholder="Digite aqui..."
data-ozi-editor-height="220px">
</textarea>
<script>
oziConf({
components: {
editor: {
themes: {
html: {
custom: '[bold,italic], heading, source'
}
}
}
}
});
</script>
Prioridade de resolução da toolbar (do mais ao menos específico):
| # | Fonte |
|---|---|
| 1 | data-ozi-editor-theme — theme declarado no elemento |
| 2 | data-ozi-editor-tools — string direta no elemento |
| 3 | oziConf components.editor.defaultTheme — theme global |
| 4 | oziConf components.editor.defaultTools — string global (compat) |
| 5 | DEFAULT_TOOLS_HTML / DEFAULT_TOOLS_MD — fallback do autor |
[6] Editor Markdown
Requer ozi-editor-md.js carregado após ozi-editor.js.
Themes built-in para MD:
| Theme | Toolbar |
|---|---|
minimal |
[bold,italic]; source |
standard |
[bold,italic], [ul,ol]; heading; codeblock; source |
full |
[bold,italic], [ul,ol]; heading; codeblock, table; source |
Ferramentas bloqueadas em MD — aparecem como ? (inativas, com tooltip explicativo):
| Ferramenta | Motivo |
|---|---|
left / center / right |
Sem equivalente Markdown |
clear |
Sem equivalente Markdown |
Subset Markdown suportado:
| Markdown | HTML gerado |
|---|---|
# … ###### |
<h1> … <h6> |
**texto** |
<strong> |
*texto* ou _texto_ |
<em> |
<u>texto</u> |
<u> (passthrough — sem equiv. MD nativo) |
- item / * item |
<ul><li> |
1. item |
<ol><li> |
```código``` |
<pre><code> |
`código` |
<code> |
| col | col | |
<table> GFM |
| linha em branco | separador de <p> |
\n dentro do parágrafo |
<br> |
Carregamento do ozi-editor-md.js:
Via oziConf (recomendado):
oziConf({
plugins: ['editor', 'editor-md']
});
Via <script> manual (ordem importa):
<script src="./plugins/ozi-ui/components/ozi-editor/js/ozi-editor.js"></script>
<script src="./plugins/ozi-ui/components/ozi-editor/js/ozi-editor-md.js"></script>
[7] Dois editores na mesma página
<!-- HTML para o corpo do post -->
<textarea
name="corpo"
data-ozi-editor-html="corpo"
data-ozi-editor-theme="blog">
</textarea>
<!-- Markdown para a descrição técnica -->
<textarea
name="readme"
data-ozi-editor-md="readme"
data-ozi-editor-theme="standard">
</textarea>
Nenhuma configuração extra — cada atributo carrega seu type.
[8] Saída enviada ao backend
O <textarea> sempre recebe o conteúdo no formato nativo do type:
data-ozi-editor-html — HTML sanitizado:
<p>Texto normal</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
<pre><code>const x = 10;</code></pre>
data-ozi-editor-md — Markdown puro:
Texto normal
- Item 1
- Item 2
```js
const x = 10;
` ` `
[9] Uso via JavaScript
// Inicializar todos os editores da página
OZI.components.editor.init();
// Inicializar em conteúdo injetado (ex: após loaddata ou Livewire)
OZI.components.editor.init(document.querySelector('#destino'));
// Obter valor (retorna no formato nativo do type)
var conteudo = OZI.components.editor.value('descricao');
// Definir valor
OZI.components.editor.value('descricao', '<p>Texto inicial</p>');
// Obter instância
var inst = OZI.components.editor.get('descricao');
console.log(inst.editorType); // 'html' ou 'md'
// Listar todas as instâncias ativas
var todas = OZI.components.editor.getAll();
// Disable / Enable
OZI.components.editor.disable('descricao');
OZI.components.editor.enable('descricao');
// Recarregar instância
OZI.components.editor.reload('descricao');
// Destruir instância
OZI.components.editor.destroy('descricao');
Ferramentas disponíveis
| Ferramenta | HTML | Markdown | Descrição |
|---|---|---|---|
bold |
✅ | ✅ | Negrito |
italic |
✅ | ✅ | Itálico |
underline |
✅ | ✅ | Sublinhado |
ul |
✅ | ✅ | Lista não ordenada |
ol |
✅ | ✅ | Lista ordenada |
codeblock |
✅ | ✅ | Bloco de código <pre><code> |
table |
✅ | ✅ | Tabela simples 2×2 |
heading |
✅ | ✅ | Dropdown h1–h6 |
classes |
✅ | ✅ | Dropdown de classes CSS (requer data-ozi-editor-class) |
source |
✅ | ✅ | Alterna para visualização do código fonte (HTML ou Markdown) |
left |
✅ | ⛔ | Alinhar à esquerda — sem equivalente Markdown |
center |
✅ | ⛔ | Centralizar — sem equivalente Markdown |
right |
✅ | ⛔ | Alinhar à direita — sem equivalente Markdown |
clear |
✅ | ⛔ | Limpar formatação — sem equivalente Markdown |
⛔ Ferramentas bloqueadas no modo Markdown aparecem como
?na toolbar (inativas, com tooltip explicativo).
Atributos HTML
[1] Identificação e tipo
| Atributo | Obrigatório | Descrição |
|---|---|---|
data-ozi-editor-html="key" |
✔ (ou md) | Ativa o editor no modo HTML. Valor = chave única |
data-ozi-editor-md="key" |
✔ (ou html) | Ativa o editor no modo Markdown. Valor = chave única |
Um dos dois é obrigatório. Usar os dois no mesmo elemento inicializa como HTML (html vence).
[2] Toolbar
| Atributo | Descrição |
|---|---|
data-ozi-editor-tools |
Ferramentas na toolbar — string com vírgulas, grupos [ ] e quebras ; |
data-ozi-editor-theme |
Nome de theme — built-in ou customizado via oziConf |
data-ozi-editor-class |
Classes CSS do dropdown Styles — formato classe:Label, classe:Label |
[3] Visual
| Atributo | Descrição |
|---|---|
data-ozi-editor-uicolor |
Cor principal — foco e botões ativos — ex: #9AB8F3 ou var(--minha-cor) |
data-ozi-editor-placeholder |
Placeholder da área editável |
data-ozi-editor-height |
Altura mínima da área — ex: 220px |
[4] Estado e Validação
| Atributo | Descrição |
|---|---|
data-ozi-editor-disabled |
Desabilita o editor e toda a toolbar |
data-ozi-editor-required |
Marca como obrigatório |
data-ozi-editor-required-message |
Mensagem de validação customizada |
HTML Permitido (sanitização)
Tags aceitas na área editável e no conteúdo colado:
p, br, strong, em, u, span,
ul, ol, li,
pre, code,
table, thead, tbody, tr, td, th,
h1, h2, h3, h4, h5, h6
Substituições automáticas: <div> → <p>, <b> → <strong>, <i> → <em>.
Atributos removidos exceto style.textAlign e class (quando aplicado via dropdown de classes).
API Pública
OZI.components.editor
| Método | Descrição |
|---|---|
init(root?, type?) |
Inicializa editores. root limita a busca; type filtra por 'html' ou 'md' |
get(chave) |
Retorna a instância do editor |
getAll() |
Retorna array com todas as instâncias ativas |
value(chave) |
Obtém o valor atual no formato nativo do type |
value(chave, v) |
Define um valor |
disable(chave) |
Desabilita o editor |
enable(chave) |
Habilita o editor |
reload(chave) |
Destrói e reinicializa a instância |
destroy(chave) |
Destrói a instância |
registerConverters({ mdToHtml, htmlToMd }) |
Registra conversores MD↔HTML (chamado por ozi-editor-md.js) |
Namespace legado
| Método | Equivalente em OZI |
|---|---|
OziEditor.init(root?) |
OZI.components.editor.init(root) |
OziEditor.get(chave) |
OZI.components.editor.get(chave) |
OziEditor.value(chave, v?) |
OZI.components.editor.value(chave, v?) |
OziEditor.destroy(chave) |
OZI.components.editor.destroy(chave) |
OziEditor.reload(chave) |
OZI.components.editor.reload(chave) |
Eventos
| Evento | Elemento | Payload |
|---|---|---|
ozi:change |
<textarea> |
{ key, value, type } |
document.querySelector('[data-ozi-editor-html="descricao"]')
.addEventListener('ozi:change', function (e) {
console.log(e.detail.key); // 'descricao'
console.log(e.detail.value); // conteúdo atual
console.log(e.detail.type); // 'html'
});
oziConf
oziConf({
components: {
editor: {
uicolor: 'var(--ozi-color-primary)', // cor padrão global
defaultTheme: 'standard', // theme padrão global
defaultTools: '[bold,italic]; source', // string direta (compat)
themes: {
html: {
custom: '[bold,italic], heading, source'
},
md: {
custom: '[bold,italic]; heading; source'
}
}
}
}
});
Como funciona
1. <script src="ozi.js"> carrega o ecossistema
2. _boot() inicializa apenas [data-ozi-editor-html]
→ elementos [data-ozi-editor-md] aguardam
3. ozi-editor-md.js carrega (após ozi-editor.js)
→ registerConverters({ mdToHtml, htmlToMd })
→ init(null, 'md') inicializa os elementos md pendentes
4. Usuário edita no modo visual
→ conteúdo sanitizado sincroniza com o <textarea>
5. Livewire / loaddata injeta HTML novo
→ OZI.hooks.afterRender.run(root)
→ editor reinicializa nos novos elementos
6. Formulário submete
→ <textarea> com conteúdo no formato nativo do type
Chaves em uso nesta página
| Chave | Exemplo | Type |
|---|---|---|
ex1_html |
[1] Simples | html |
ex1_md |
[1] Simples | md |
ex2_html |
[2] Custom simples | html |
ex2_md |
[2] Custom simples | md |
ex3_html |
[3] Toolbar agrupada | html |
ex3_md |
[3] Toolbar agrupada | md |
ex4_html |
[4] Classes e headings | html |
ex4_md |
[4] Classes e headings | md |
ex5_theme |
[5] Theme built-in | html |
ex5_custom |
[5] Theme customizado | html |