npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@edtroleis/plugin-techdocs-editor

v0.2.1

Published

Visual editor for TechDocs pages: drafts, checks and publishing through GitHub pull requests

Readme

TechDocs Editor

English · Português

CI npm npm provenance Backstage License

Editor visual das páginas do TechDocs para quem não conhece Git: a pessoa clica no lápis da página, escreve num editor parecido com um editor de texto comum e publica. Por baixo, o fluxo é o mesmo de qualquer mudança de código no GitHub: branch, pull request, verificações da pipeline e merge.

  • Editor visual e visão Markdown (Milkdown + CodeMirror), com a conversão fiel do Markdown do MkDocs (admonitions, abas, tabelas, imagens).
  • Lint na hora, com as regras do .markdownlint.* do próprio repositório (as mesmas da pipeline) e correções automáticas.
  • Salvar rascunho (só guarda, sem pipeline), Salvar e verificar (PR em rascunho + pipeline), Enviar para publicação/revisão (o rótulo segue as regras da branch no GitHub) e Descartar.
  • Verificações da pipeline em linguagem simples, com "ver linha" no ponto do problema.
  • Conflitos: o rascunho recebe o que foi publicado depois; se o mesmo trecho mudou, a pessoa escolhe o que fica.
  • Histórico da página, com "Restaurar" uma versão anterior.
  • Na página do TechDocs: lápis "Editar" (com ponto quando há rascunho), aviso de alterações aguardando publicação e as datas de criação e atualização no alto.

Quem pode escrever é decidido pelo GitHub: o editor age com o token da própria pessoa.

Funcionando

| Editar e publicar | Verificações em linguagem simples | Markdown e lint | |:---:|:---:|:---:| | Lápis na página do TechDocs, editor visual, salvar e verificar, enviar para publicação | Verificação que falhou explicada em linguagem simples; "ver linha" abre o Markdown no problema | Troca para a visão Markdown; o lint aponta problemas enquanto se digita | | Lápis na página, editor visual, PR em rascunho, verificações, envio | Verificação que falhou em linguagem simples; "ver linha" vai até o problema | O mesmo documento em Markdown, com lint enquanto se digita |

Pacotes

| Pacote | Conteúdo | |--------|----------| | @edtroleis/plugin-techdocs-editor | Página do editor e addon do TechDocs (este pacote) | | @edtroleis/plugin-techdocs-editor-common | Núcleo sem React: Markdown do MkDocs, lint, merge de 3 vias, cliente do GitHub, setup do repositório | | @edtroleis/plugin-scaffolder-backend-module-techdocs-editor | Action do Scaffolder techdocs-editor:setup |

Instalação

yarn --cwd packages/app add @edtroleis/plugin-techdocs-editor

O login do GitHub precisa estar configurado no Backstage (auth.providers.github, com o callback <backend>/api/auth/github/handler/frame e o módulo @backstage/plugin-auth-backend-module-github-provider no backend); o editor pede o popup só quando a pessoa clica em editar. Sem o provedor, o editor avisa que o login do GitHub não está configurado, em vez de abrir o popup.

Novo sistema de frontend

Com app.packages: all, a página é encontrada sozinha. O addon do TechDocs é um módulo à parte:

// packages/app/src/App.tsx
import techdocsEditorPlugin, { techdocsEditorTechDocsModule } from '@edtroleis/plugin-techdocs-editor/alpha';

export default createApp({
  features: [techdocsEditorPlugin, techdocsEditorTechDocsModule],
});

A página fica em /docs-editor.

Sistema de frontend antigo

// packages/app/src/App.tsx
import { TechDocsEditorPage, TechDocsEditAddon } from '@edtroleis/plugin-techdocs-editor';

<Route path="/docs-editor" element={<TechDocsEditorPage />} />

<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
  <TechDocsAddons>
    <TechDocsEditAddon />
  </TechDocsAddons>
</Route>

Configuração

Tudo é opcional (schema em config.d.ts):

techdocsEditor:
  github:
    auth: user            # user (padrão) | proxy (só demonstração)
    host: github.com      # quando a doc não informa; a API vem de integrations.github (GitHub Enterprise)
    scopes: [repo]        # [public_repo] basta para wikis só em repositórios públicos
  branchPattern: 'docs/{login}/{path}'
  drafts:
    skipCi: true          # "Salvar rascunho" com [skip ci]
  verification:
    mode: auto            # auto | pipeline | editor
    startTimeoutSeconds: 120
    checkHelp:            # mensagem em linguagem simples por nome de job da pipeline
      Links: Há links que não funcionam.
  polling:
    intervalSeconds: 8        # com check rodando ou PR esperando publicação
    idleIntervalSeconds: 60   # parado; com a aba em segundo plano, nenhuma consulta

Verificação: qualquer CI, com ou sem pipeline

| Repositório | O que "Salvar e verificar" confere | Enviar | |-------------|-----------------------------------|--------| | Com workflows do GitHub Actions, ou checks obrigatórios num ruleset ou na proteção de branch clássica (mode: auto detecta) | Tudo o que o CI reporta no PR: checks (GitHub Actions, Azure Pipelines, Jenkins com GitHub Checks…) e commit statuses (Jenkins, CircleCI e outros CIs externos), com qualquer nome de job | Liberado quando nenhum check falhou | | Sem nada disso (mode: auto detecta) ou mode: editor | O lint do editor, com as regras do repositório; o painel explica que não há verificações automáticas | Liberado com o lint ok |

Se nenhum check começar em startTimeoutSeconds, o painel avisa e mostra o link do PR. O "ver linha" vem dos apontamentos dos checks; commit statuses só têm o link para o CI.

Configuração por repositório

Com muitos repositórios de documentação, cada time descreve a própria pipeline no .techdocs-editor.yaml da raiz do repositório (branch principal), sem mexer no app-config do portal:

verification:
  mode: pipeline              # auto | pipeline | editor
  startTimeoutSeconds: 600    # ex.: fila do Jenkins que demora a começar
  checkHelp:                  # mensagem em linguagem simples por nome de job, somada às do portal
    continuous-integration/jenkins/pr-merge: A documentação não pôde ser montada. Abra os detalhes.

Vale, nesta ordem: a anotação techdocs-editor/verification: pipeline | editor do catálogo, o .techdocs-editor.yaml e o app-config. O checkHelp do repositório é somado ao do portal (para o mesmo job, vale o do repositório). Valor inválido é ignorado (vale o do portal), para um erro de digitação não travar o editor. O setup do repositório não oferece o workflow padrão quando o repositório tem CI próprio (checks obrigatórios) ou o arquivo diz mode: pipeline ou mode: editor.

Modos de uso

| Modo | Login no portal | Quem vê o lápis | Escrita no GitHub | |------|-----------------|-----------------|-------------------| | Demonstração | Guest | Owner da doc ou todos (política allow all) | auth: proxy: conta do servidor, pelo proxy techdocs-editor-github do backend; o editor avisa na tela | | PoC | Guest ou o provedor existente | Owner da doc (antes do login do GitHub) | Token do próprio usuário | | Produção | Provedor real | Permissão techdocs-editor.page.edit (abaixo) | Token do próprio usuário |

O modo proxy precisa do endpoint no proxy do backend, com o token de uma conta de serviço:

proxy:
  endpoints:
    /techdocs-editor-github:
      target: https://api.github.com
      headers:
        Authorization: Bearer ${GITHUB_TOKEN}
      allowedMethods: [GET, POST, PUT, PATCH, DELETE]
      credentials: require   # só usuários logados no portal

Permissão

O pacote -common exporta techdocsEditorEditPermission (techdocs-editor.page.edit), uma permissão de recurso sobre a entidade do catálogo. Ela decide se o lápis aparece e se o editor abre; a escrita continua dependendo do GitHub. Numa política, por exemplo, só o owner da documentação:

if (isPermission(request.permission, techdocsEditorEditPermission)) {
  return createCatalogConditionalDecision(request.permission, catalogConditions.isEntityOwner({
    claims: user?.info.ownershipEntityRefs ?? [],
  }));
}

Sem permission framework (ou com a política allow all), todos podem; vale então só o GitHub.

GitHub Enterprise

O host vem do backstage.io/source-location da documentação (ou de techdocsEditor.github.host), e a URL da API da integração desse host em integrations.github. O login do GitHub do Backstage precisa estar configurado para o mesmo Enterprise (auth.providers.github.<env>.enterpriseInstanceUrl).

Segurança

  • Token do GitHub: vem do login do GitHub do Backstage e fica só em memória no navegador; o editor não grava o token nem o escreve em log. No localStorage fica apenas o texto do rascunho ainda não salvo.

  • Escopo mínimo: o escopo repo do OAuth App dá escrita em todos os repositórios que a pessoa acessa, não só nas wikis. Em ordem de preferência:

    1. GitHub App no lugar do OAuth App (auth.providers.github aceita um App): o token vale só nos repositórios onde o App foi instalado, com as permissões contents: write, pull_requests: write, checks: read e metadata: read;
    2. wikis só em repositórios públicos: scopes: [public_repo];
    3. OAuth App com repo (padrão), aceitando o alcance acima.
  • Navegador: restrinja o connect-src do CSP ao backend e à API do GitHub configurada:

    backend:
      csp:
        connect-src: ["'self'", 'https://api.github.com'] # GitHub Enterprise: https://<host>/api/v3
  • Conteúdo: imagens enviadas só com tipo image/* e até images.maxSizeMB; HTML hostil no Markdown (scripts, links javascript:) é testado em e2e/tests.

  • Modo proxy: todos escrevem com a mesma conta de serviço. Só para demonstração.

  • CI (.github/workflows/ci.yml): lint, tipos, testes, yarn npm audit (falha em alta/crítica nas dependências do plugin; exceções sem correção ficam em .yarnrc.yml com o motivo), gitleaks e CodeQL.

Requisitos da documentação

  • Anotações backstage.io/techdocs-ref e github.com/project-slug no catalog-info.yaml.
  • Merge por squash com a descrição do PR como mensagem: o rascunho usa [skip ci], e a mensagem padrão do squash levaria o marcador para a branch principal.

O setup abaixo confere e ajusta isso.

Setup do repositório

O que falta para o editor conferir cada alteração é aplicado de dois jeitos, com a mesma lógica (planSetup/applySetup no -common). Só o que falta é feito, então dá para rodar de novo:

| Passo | Quando falta | Como é aplicado | |-------|--------------|-----------------| | workflow | Nenhum workflow no repositório | PR com .github/workflows/techdocs-checks.yml (os 4 checks, só em PRs) | | markdownlint | Nenhum .markdownlint.* | No mesmo PR, .markdownlint.yaml com as regras para iniciantes | | merge | Merge não é só squash com título e descrição do PR | Na hora (admin) | | ruleset | A branch principal aceita mudança sem PR, ou já roda os checks padrão sem exigi-los | Na hora (admin): ruleset techdocs-editor com PR obrigatório e, se o workflow padrão já está na branch, os 4 checks |

  • No editor: quem é admin do repositório vê "Configurar verificações" no painel quando falta algo. A confirmação diz o que muda na hora e o que vai em PR.

  • No Scaffolder: a action techdocs-editor:setup (registre o módulo no backend):

    backend.add(import('@edtroleis/plugin-scaffolder-backend-module-techdocs-editor'));
    - id: setup
      action: techdocs-editor:setup
      input:
        repoUrl: github.com?owner=my-org&repo=wiki-team
        requiredApprovals: 1   # opcional; padrão 0

    O token é o da integração do GitHub (ou token na entrada); sem admin, só o PR é aberto.

Pipeline própria não é trocada: o ruleset passa a exigir PR, mas não checks de nome desconhecido.

Testes

yarn test:editor          # unitários (os dois pacotes) + editor no navegador
yarn test:editor:portal   # painel dentro da app de desenvolvimento, com o GitHub simulado (sobe a app sozinho)