Problemas ao carregar um asset js de um Componente de Tema

Olá, é a primeira vez que desenvolvo no Discourse, então desculpe pelas perguntas bobas.
Estou construindo um componente de tema para exibir PGNs (tabuleiro de xadrez e partidas).
O componente não é teoricamente difícil, existe um componente js para isso (PGNViewer.js) e consegui traduzir as tags [wrap] para os blocos \u003cscript\u003evar x='pgn here'; ...\u003c/script\u003e e \u003cdiv class='pgn-blahblah'\u003e\u003c/div\u003e adequados.
Até aqui tudo bem, mas agora preciso carregar o js.
Descobri que posso usar import loadScript from \"discourse/lib/load-script\"; e await loadScript(settings.theme_uploads_local.pgnviewer_js); para carregá-lo no momento da inicialização do diretório /assets/.
Mas tenho alguns problemas aqui.
Apesar de conseguir carregar o componente na instalação de desenvolvimento, não consigo no meu servidor de produção, pois ele diz que o ativo é muito grande. Existe uma maneira de corrigir isso?
Segundo, na instalação de desenvolvimento, vejo um aviso dizendo que não conseguiu carregar /theme-javascripts/dist.js.map. Não tenho ideia de onde vem. Há algo que eu deveria fornecer?
No geral, essa abordagem está correta ou seria melhor implementar um plugin em vez disso?
Obrigado
Atenciosamente

FF

2 curtidas

Bem-vindo à Meta, @happycactus :wave:

Sim, provavelmente. A única razão pela qual você precisaria de um plugin seria se estivesse tentando alterar a API (ou seja, o back-end).

Tive um problema semelhante no passado.

Sim, você precisa alterar app.yml para permitir que arquivos grandes sejam alimentados através do proxy reverso (nginx).

Felizmente, esta é uma configuração simples, upload_size:, aqui em contexto:

params:
  ## Qual revisão do Git este contêiner deve usar? (padrão: tests-passed)
  version: tests-passed

  ## Tamanho máximo de upload (padrão: 10m)
  upload_size: 20m

Depois de alterar isso, você precisará reconstruir para que tenha efeito:

./launcher rebuild app

Claro, isso pressupõe que você tenha acesso apropriado ao servidor …

2 curtidas

Obrigado, Robert!

Estou em dúvida, provavelmente porque não tenho experiência nenhuma com tais plataformas.
Minha dúvida é:

minha abordagem é “incorporar” o pequeno trecho de javascript necessário para preencher o bloco div com o conteúdo, mas vejo que talvez eu possa executá-lo a partir de uma função “cookPgn”, como é feito no componente marmaid:

async function applyMermaid(element, key = "composer") {
  const mermaids = element.querySelectorAll("pre[data-code-wrap=mermaid]");
  ...
  await loadScript(settings.theme_uploads_local.mermaid_js);
  ...
  mermaids.forEach((mermaid) => {
    if (mermaid.dataset.processed) {
      return;
    }

    const spinner = document.createElement("div");
    spinner.classList.add("spinner");
    ...
    mermaid.append(spinner);
  });

Dessa forma, se entendi corretamente, não preciso carregar o script da página (usando loadScript talvez??) mas posso simplesmente importá-lo no js do tema? Ou provavelmente estou totalmente enganado!
Quero dizer, qual é a diferença entre loadScript e um simples import?
Você pode me indicar algum recurso na web onde eu possa entender melhor isso?
Desculpe novamente se as perguntas são triviais ou estúpidas!

Outra coisa, o limite é por padrão de 10M, mas meu ativo tem cerca de 300kb, e todo o zip tem 337kb, ainda assim durante o upload ele diz que é mais de 512kb.

Obrigado,

FF

Você já tentou um import? Eu não acho que você possa importar um script externo.

Loadscript é a abordagem correta e garante que o script seja totalmente carregado antes que seu código prossiga e o utilize (é por isso que ele retorna uma promessa).

você pode compartilhar o erro exato - isso está no console do navegador?

Seu problema real é tentar usar JS inline, o que é proibido pelo CSP.

Coloque este código em uma função auxiliar no código do seu componente de tema e não o injete dentro de posts.

Faça o upload do seu tema atual para o GitHub e podemos dar uma olhada também.

5 curtidas

Dê uma olhada no Discourse Mermaid, que carrega uma biblioteca e faz coisas acontecerem nas postagens.

2 curtidas

Obrigado, @Falco, essa era uma das minhas dúvidas.

Claro, aqui está: GitHub - studiofuga/discourse-pgn-component: A theme component for Discourse to display PGN blocks
Também existe uma versão de plugin, mas acho que não seguirei essa abordagem e ficarei com o componente de tema.

Obrigado @pfaffman, de fato me inspirei nele, e notei que ele faz exatamente o que preciso e da maneira correta, sem injetar o código como sugerido acima.

Obrigado a todos, tentarei com suas sugestões e voltarei com os resultados. Claro que meu código é de código aberto, então qualquer contribuição ou crítica é muito bem-vinda.

1 curtida

Minha culpa, esqueci que limitei o tamanho do anexo para 512kB, aumentei para o padrão (4096) e funcionou bem. Obrigado e desculpe pela pergunta estúpida.

2 curtidas

Ok, eu corrigi tudo e o componente funciona! Mas temos um problema, uma "unsafe eval" na biblioteca que estou usando. Acho que devo corrigir a biblioteca upstream, não tenho ideia de como empacotá-la.
Para quem estiver interessado, enviei todas as minhas alterações para o meu repositório acima, e aqui estão os detalhes do erro.

e a linha é esta (no módulo js original)

let isBrowser=new Function("try {return this===window;}catch(e){ return false;}")

aqui.

1 curtida

Seu script está falhando com a Content Security Policy em Produção.

Você precisa adicionar 'unsafe-eval' como um item na configuração do site: content security policy script src

Obrigado, estou consultando a documentação para ver como fazer isso. :slight_smile: Estou aprendendo muito, obrigado

1 curtida

Ok, eu consegui, só que precisei usar o ’ … lol… De qualquer forma, meu script quase funcionou, enviei tudo para o main e de alguma forma funcionou, parece que tenho um problema com a renderização, mas pelo menos o componente principal é chamado (suspeito que seja aí que está o problema).
Obrigado a todos… Voltarei em breve com mais perguntas LOL. Obrigado!

1 curtida

Tendo em mente que adicionar unsafe-eval à sua CSP basicamente remove todo o propósito da CSP e torna seu site menos seguro como resultado.

Usar eval é um “code smell” (cheiro de código ruim), e deve ser corrigido a montante, como você apontou acima.

4 curtidas

Sim, definitivamente. No momento, não consigo corrigi-lo, mas meu plano é primeiro corrigir meu componente, depois corrigir a biblioteca upstream e remover a substituição da CSP.
Obrigado pelo conselho!

Estou quase terminando. Consegui exibir “algo”, mas está funcionando aleatoriamente.
A biblioteca JS que estou usando funciona desta forma:

Primeiro, precisamos definir um bloco <div id='board'> com um ID exclusivo. Em seguida, precisamos chamar uma função para popular o div, algo como isto: PGNV.pgnBoard('board', {});. O script requer o mesmo ID para popular o div.

Se entendi corretamente, não posso fazer isso enquanto decoro o bloco pronto, porque o documento ainda não foi preenchido e o objeto PGNV não consegue encontrar o bloco. Então, usei primeiro um widget (não funciona, porque a função HTML deve retornar o bloco, e eu não o tenho), depois mudei para uma função debounced: debounceFunction(this, renderPgn, attrs, 200);.

Mas funciona “às vezes”.

O que estou perdendo?

Obrigado

debounceFunction atrasa a chamada do método de destino até que o período de debounce tenha decorrido sem chamadas de debounce adicionais, às vezes pode não funcionar ainda porque

debounce pode não ser a solução no seu caso de uso

Tente usar as opções afterAdopt

1 curtida

Olá Hawn, obrigado pela sua dica!
Parece ser exatamente o que eu estava procurando. Tentei duas abordagens diferentes:

  • primeiro usar o decorateCooked normal para analisar e anexar o bloco div e, em seguida, o afterAdopt para renderizar chamando PGNV.pgnviewer() ou
  • usar apenas a opção afterAdopt para anexar e renderizar
    Nenhuma funcionou ainda por outro problema que não consigo entender completamente, parece que a biblioteca interna falha com um erro, incapaz de encontrar o atributo className aparentemente em um elemento DOM. Estou um pouco perdido :slight_smile: . Vi que alguém usou loadScript, mas eu apenas importei a biblioteca e a função debounce funcionou. Qual é a diferença entre os dois métodos?

Obrigado!

Olá @hawm , descobri por que não está funcionando e estou travado.
Claro, sou totalmente novo no Ember e em JavaScript recente em geral. Então, estudei um pouco e descobri o motivo.
O PgnViewerJs espera funcionar no DOM real, não no DOM Virtual. Portanto, mesmo depois que o elemento preparado foi adotado, ele não está presente no DOM real, e o PGNV procura por IDs usando document.getElementById.
Estudei tudo o que pude encontrar: os componentes Ember parecem atender às minhas necessidades, mas não tenho certeza de como lidar com isso.
Ou talvez API.onAppEvent?

Obrigado.

Usei later() do Ember e, embora seja uma solução improvisada (dirty hack), funciona. Alguma solução melhor?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.