2 pontos por GN⁺ 4 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Wordgard 0.1 é uma nova biblioteca JavaScript de editor de texto rico, criada com base em 9 anos de experiência desde a estabilização do ProseMirror e refletindo o design do CodeMirror 6
  • Em vez de transformar o ProseMirror existente em 2.0 ou adicionar camadas ao 1.x, ele foi redesenhado com uma nova API sem o peso da compatibilidade e com um nome separado
  • O design central usa um modelo baseado em seções de mudança em vez de steps, combinando tipos independentes de nó e marca com um sistema de extensões facet no estilo do CodeMirror
  • Reduz a dependência do comportamento de seleção do navegador ao lidar diretamente com seleção por ponteiro e teclado, mas mantém a implementação do navegador para seleção por toque devido a problemas com o menu de contexto nativo
  • Pode ser instalado via npm com wordgard, e a documentação e o manual de referência já foram publicados, mas deve permanecer na série 0.x por algum tempo enquanto recebe feedback e correções de bugs

Natureza do Wordgard e estado de lançamento

  • Wordgard é um projeto que reimagina do zero um sistema de editor de texto rico no estilo do ProseMirror
  • Foi fortemente influenciado pelo que foi aprendido nos 9 anos desde a estabilização do ProseMirror e pelo redesenho da versão 6 do CodeMirror
  • É uma biblioteca JavaScript que exibe a interface do editor usando o DOM do navegador, e sua licença é MIT
  • O código está disponível em um servidor Forgejo
  • Pode ser instalado como wordgard no registro npm, e o modo de uso pode ser consultado no site

Por que criar um novo sistema sem substituir o ProseMirror

  • O ProseMirror continua sendo mantido, mas algumas escolhas de design permaneceram como pontos que hoje deveriam ter sido feitos de outra forma
  • Se fosse lançado um ProseMirror 2.0 com interface incompatível, poderia ficar ambíguo o que as pessoas querem dizer quando falam “ProseMirror”
  • Se novas ideias fossem adicionadas ao ProseMirror 1.x de forma retrocompatível, a estrutura poderia acabar seguindo por compromissos excessivos
  • O Wordgard reaproveita muitas ideias do ProseMirror, mas sua interface de programação foi redesenhada do zero sem preocupação com compatibilidade

Representação de mudanças: modelo baseado em seções em vez de steps

  • Os steps do ProseMirror dividem uma mudança em várias operações atômicas, e cada step é aplicado ao documento gerado pelo step anterior
  • Esse método funciona, mas lidar com o ajuste de posições entre vários steps e rastrear o escopo das mudanças é complexo e pouco prático
  • O Wordgard usa um modelo mais simples, baseado na representação de mudanças do CodeMirror e no formato “delta” do ShareJS
    • Quando o documento tem comprimento 10 e se insere L na posição 4, isso é representado como [keep 4] [replace 0 with "L"] [keep 6]
    • Ao remover os dois primeiros caracteres, fica [replace 2 with ""] [keep 8]
  • Para lidar com texto rico, ele adiciona seções de mudança, permitindo adicionar ou remover marcas como destaque, estilo de link e texto alternativo de imagem sem quebrar a estrutura
    • Se as palavras de 3 a 6 forem colocadas em negrito, isso é representado como [keep 3] [update 3 +bold] [keep 4]
  • O Wordgard usa o mesmo índice por contagem de tokens do ProseMirror, tratando as posições do documento como uma sequência plana de tokens de abertura/fechamento de nó e tokens folha
  • Uma transação única sempre contém exatamente uma mudança, o que facilita composição, verificação e inferência
  • Há suporte a transformação operacional limitada para mesclar múltiplas mudanças expressas com base no mesmo documento inicial
    • Isso permite representar com mais conforto transações com várias mudanças
    • Também pode ser usado para edição colaborativa e para implementar histórico de undo com reversão parcial de mudanças

Como manter uma estrutura de documento válida

  • Um documento do Wordgard não é apenas uma sequência simples de tokens, mas uma estrutura de árvore balanceada
  • Por exemplo, se um token de fechamento de nó for removido, o equilíbrio dos tokens pode se quebrar e gerar uma mudança impossível de aplicar
  • O código que cria conjuntos de mudanças precisa verificar e ajustar as mudanças para que o resultado mantenha uma estrutura de documento válida
  • Na transformação operacional, a mudança transformada também não pode invalidar o documento
  • O modelo de mudanças do Wordgard deriva uma fix-up change para corrigir o resultado combinado durante a transformação
    • As entradas são usadas com cuidado para que A-over-B e B-over-A produzam a mesma correção
    • Sem essa correção, as duas ordens poderiam produzir o mesmo documento, porém inválido
    • Ao compor a mesma correção, ambas as ordens convergem para o mesmo documento válido
  • A maioria das mudanças não precisa de correção, mas, quando precisa, o sistema foi projetado para preservar a convergência

Composição de schema e generalização de marks

  • No ProseMirror, o schema do documento define diretamente as relações entre nós, então normalmente ele precisa ser configurado manualmente
  • Os tipos de nó e mark do ProseMirror existem apenas dentro de um schema específico, sem uma identidade de nó compartilhável entre schemas
  • No Wordgard, os tipos de nó e mark são objetos independentes que podem ser incluídos em vários schemas de documento
  • Esses objetos funcionam como handles com tipagem e autocomplete, facilitando montar um schema combinando apenas os elementos necessários
  • O schema pode sobrescrever relações de elementos existentes
    • Definições de nó ou mark especificam conteúdo ou tipos de destino padrão
    • Quando se quer usar o mesmo elemento de outra forma, o schema pode alterar essas relações
  • Isso permite fornecer nós embutidos padrão mais ricos e facilita anexar diretamente a esses nós integrações de sistema, como extensões de suporte à edição ou botões de menu
  • Recursos antes presos a atributos específicos de nós, como alinhamento de texto ou texto alternativo, podem ser adicionados de forma mais modular por meio da generalização de marks
  • O próprio tipo de nó não precisa saber quais marks o têm como alvo

Por que flexibilizar as restrições de conteúdo

  • A especificação de conteúdo permitido baseada em expressões regulares, um recurso marcante do ProseMirror, não é suportada no Wordgard
  • A descrição de conteúdo de nós no Wordgard restringe apenas quais tipos de filhos são aceitos, mas não restringe sua ordem
  • Restrições baseadas em expressões regulares dificultam a escrita de código genérico de manipulação de documentos
    • Código não escrito para um schema específico quase não consegue assumir quais transformações são válidas
    • Cada operação precisa ser comparada com as restrições de conteúdo, e esse processo é sutil e pesado
  • Restrições que travam fortemente a forma do documento podem bloquear etapas intermediárias de edição rumo ao resultado pretendido pelo usuário, prejudicando a experiência
  • O Wordgard incentiva uma abordagem mais flexível para a forma do documento
  • Quando são necessárias condições invariantes além das regras do schema, ele fornece a abstração de correction
    • Formas de documento indesejadas podem ser corrigidas por código
    • Isso permite correções mais inteligentes e sensíveis ao contexto do que impor expressões de conteúdo
    • Também serve para condições que nem poderiam ser expressas nas restrições do ProseMirror, como garantir tabelas retangulares

Sistema de extensões: facets no estilo do CodeMirror 6

  • O sistema de extensões do ProseMirror faz com que plugins assumam várias funções, e a ordem no array influencia a prioridade
  • Pode acontecer de um plugin precisar de baixa prioridade em um hook e alta prioridade em outro
  • O sistema baseado em facets do CodeMirror torna as extensões mais granulares e permite que cada valor de extensão defina sua própria categoria de prioridade
  • Um Facet é um ponto de extensão tipado que pode ser definido não só pela biblioteca, mas por qualquer código
  • O Wordgard traz essa parte do sistema do CodeMirror quase intacta, incluindo o mecanismo de atualização de estado e reconfiguração
  • A configuração não é um array de plugins, mas uma árvore de extensões
    • definição de manipuladores de evento
    • configuração de propriedades do editor
    • adição de novo estado ao editor
  • A implementação de funcionalidades costuma ser composta por conjuntos de extensões que atuam em conjunto
  • Os elementos primitivos foram projetados para que os pacotes de extensões geralmente se combinem bem apenas sendo adicionados à configuração

Redução da dependência do navegador e tratamento de seleção

  • Muitos problemas do ProseMirror estão ligados à dependência do comportamento nativo de seleção do navegador
  • A abordagem anterior deixava o navegador lidar com movimentação de cursor em texto bidirecional ou conteúdo com estilos incomuns e depois refletia o resultado no próprio modelo de seleção
  • Na prática, os navegadores podem não mover o cursor por certos conteúdos, não desenhá-lo, desenhá-lo na posição errada ou se comportar de forma estranha ao arrastar a seleção com o mouse
  • O Wordgard lida diretamente com quase toda a seleção por ponteiro e teclado
    • Implementa o tratamento de texto bidirecional
    • Cria um modelo de layout de conteúdo
    • Desenha o cursor por conta própria
  • A seleção por toque é a exceção e usa a implementação nativa
    • Reimplementar isso parece quebrar o menu de contexto nativo
    • Em celulares e tablets, é difícil substituir o menu de contexto
    • A seleção por toque também tende a apresentar menos comportamentos estranhos do que a seleção por teclado

Tratamento de eventos de entrada e remoção da observação de mudanças no DOM

  • Nos últimos 9 anos, o suporte dos navegadores a eventos de edição, especialmente ao beforeinput, ficou mais consistente
  • Ainda é necessário testar em ambientes reais de uso, mas o Wordgard parece capaz de funcionar sem a observação de mudanças no DOM nem os truques de parse de conteúdo alterado dos quais o ProseMirror dependia
  • O Wordgard trata o evento beforeinput para tudo, exceto entrada de texto em composição
  • Essa abordagem evita uma série de problemas que exigiam implementações de contorno complicadas

Estabilidade, plano de versão e licença

  • O Wordgard está em um estado um pouco mais avançado do que projetos anteriores no momento em que foram anunciados
  • As interfaces centrais já suportam quase tudo o que se desejava, e várias extensões também foram escritas para verificar se o design é prático
  • A documentação ainda está um pouco crua, mas o manual de referência está completo e pode ser usado
  • Muitos problemas podem não aparecer até que pessoas comecem a usá-lo em trabalho real
  • Ainda há recursos que o autor quer adicionar, e a expectativa é que outras pessoas também passem a examiná-lo após o lançamento
  • Algumas partes da interface pública podem precisar ser repensadas à luz de mais experiência
  • A primeira versão é a 0.1, e ela deve permanecer na série 0.x por algum tempo para coletar feedback, corrigir bugs e aparar arestas
    • O período estimado é de pelo menos cerca de 1 ano
  • Assim como nos projetos anteriores, a licença é MIT
  • Uma licença mais restritiva foi considerada, mas o interesse maior é em uso amplo, por isso foi escolhida uma licença permissiva

Modelos de IA, geração de código e política de pull requests

  • Modelos de linguagem não foram usados para criar este software
  • Como o código JavaScript estará na web e a documentação precisa ser pública, considera-se que não há uma forma confiável de impedir que código e ideias públicas entrem em grandes modelos de linguagem
  • No Wordgard, está sendo feito um experimento de não aceitar pull requests, ao contrário da prática padrão de código aberto
  • Revisar grandes mudanças e ajustá-las para que correspondam ao esperado costuma dar mais trabalho do que implementá-las diretamente
  • Com a forte redução no custo de geração de código, torna-se menos atraente uma estrutura em que outras pessoas simplesmente enviam código e os mantenedores precisam revisar, manter ou explicar por que recusaram

1 comentários

 
GN⁺ 4 시간 전
Comentários no Lobste.rs
  • Como autor, vou verificar esta thread de vez em quando caso haja perguntas ou feedback

    • Parece bem impressionante. Não vi isso no FAQ, mas fiquei curioso sobre como poderia ser usado ou configurado para edição de Markdown
      Imagino que dê para gerar HTML com um renderizador de Markdown e editá-lo no Wordgard, mas depois disso como seria possível extrair Markdown do conteúdo do editor?
    • Fiquei curioso sobre qual caminho de transição as pessoas que usam ProseMirror vão seguir
      Elas acabarão migrando para o Wordgard? Se alguém estiver pensando em usar ProseMirror em um projeto novo, quando deveria escolher o Wordgard?
  • Contains 0% AI

    Not having PRs is an effective way to nip the problem of people submitting LLM-generated slop code in the bud.

    E também há uma arte bacana feita por uma artista real, humana
    Gostei

  • Parabéns ao Marijn pelo projeto e pelo lançamento. Parece ótimo, e também gostei da arte da Kamila Stankiewicz

  • A página inicial principal do projeto é https://wordgard.net/

  • As a deviation from standard open-source practice, I'm doing an experiment where I don't take pull requests for Wordgard.

    Este trecho, especialmente o último parágrafo inteiro, é realmente interessante
    Fico imaginando se esse tipo de abordagem pode se tornar mais comum por um tempo, até termos uma relação melhor com a geração de código por IA — ou até optarmos por não ter relação nenhuma com ela
    Para constar, o código está sob a licença MIT