ozi-editor

Versão: 3.1.0Atualizado 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áveldata-ozi-editor-uicolor controla 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, right e clear nã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 classes só aparece na toolbar se data-ozi-editor-class estiver 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