"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Faça ajudantes personalizados do guidão em fantasma!

Faça ajudantes personalizados do guidão em fantasma!

Postado em 2025-04-08
Navegar:572

Make Custom Handlebar Helpers in Ghost!

Este artigo é para muitos desenvolvedores e criadores temáticos que encontram os ajudantes padrão oferecidos por Ghost (https://ghost.org/docs/themes/helpers/) insuficiente. É completamente normal procurar maneiras de estender as capacidades de nossos temas que usam guidão fornecido pelo fantasma. Antes de publicar este artigo e encontrar uma solução para o meu tema, pesquisei a Internet inteira e conduzi uma análise do código -fonte do fantasma.

Método 1 (modificando o código principal)

descobri que é possível estender o código -fonte do Ghost com ajudantes adicionais. Consegui isso adicionando um novo diretório no Current/Core/Frontend/Apps. Usei o exemplo de um "aplicativo" existente chamado AMP, cujo código é muito simples, para começar a criar um novo ajudante disponível no tema. Nesses aplicativos existentes, a estrutura é direta porque os ajudantes são registrados em LIB/ajudantes. No final do processo, você precisa adicionar o nome do seu diretório nos aplicativos à Current/Core/Shared/config/substituir.json na seção Apps.internal JSON.

Um exemplo de conteúdo do arquivo index.js em nosso aplicativo seria:

const path = require('path');

module.exports = {
    activate: function activate(ghost) {
        ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers'));
    }
};

a seguir, no diretório Lib deste aplicativo, criamos uma pasta chamada Helpers. No interior, criamos um novo arquivo, que será o nome do ajudante a ser chamado em um modelo de guidão. Por exemplo, vamos nomear o valor superior.js.

abaixo está um exemplo do código desse ajudante, que simplesmente converte as letras do texto fornecido no argumento auxiliar na maçaneta:

const {SafeString, escapeExpression} = require('../../../../services/handlebars');

module.exports = function uppercase(text) {
    return `${text.toUpperCase()}`;
};
! Depois de reiniciar o fantasma, tudo deve estar pronto.

Método 2 (sem modificar o código principal)

desenvolvi recentemente esse método e você pode aplicá-lo não apenas em fantasmas auto-hospedados, mas também em instâncias fantasmas oferecidas pelos provedores de hospedagem. Neste último caso, requer planejamento arquitetônico apropriado e compra de um pequeno servidor que atuará como um proxy para sua instância final do fantasma.

a arquitetura que usaremos neste método: Nginx Server ← Node.js Middleware ← Ghost Instância

O navegador do usuário envia uma solicitação para o servidor nginx, que contém o upstream do middleware. Todas as solicitações, independentemente da localização, serão proxiadas para o middleware.

O middleware é um servidor expresso em execução no Node.js com a biblioteca expreste-http-proxy (https://github.com/villadora/express-http-proxy), que simplifica significativamente o trabalho. Configuramos o proxy para se comunicar com a instância fantasma. A Biblioteca Express-Http-Proxy possui uma propriedade UserResDecorator que podemos usar para "decorar a resposta do servidor proxado". Simplificando, podemos modificar a resposta do fantasma antes de enviá -la para o navegador do usuário.

Nosso UserResDecorator será assíncrono para não bloquear o encadeamento principal. Voltaremos ao tópico do processamento assíncrono ao criar ajudantes. Por enquanto, você precisa saber que nem tudo o que as solicitações do navegador do usuário precisam ser decoradas. Portanto, a primeira etapa será verificar o cabeçalho do tipo de conteúdo da resposta do Ghost. Você pode fazer isso da seguinte


// onde 'proxyres' é sua resposta de proxy dentro de 'userResdecorator' const contentType = proxyres.headers ['content-type'] || ''; if (! contentType.includes ('text/html')) { // retorna conteúdo original se a resposta não for 'texto/html' retornar proxyresdata; } Seja htmlContent = proxyresdata.toString ('utf8'); // Faça algo com 'htmlContent' e retorne retornar htmlContent;

// Where 'proxyRes' is your proxy response inside 'userResDecorator'
const contentType = proxyRes.headers['content-type'] || '';
if (!contentType.includes('text/html')) {
    // Return original content if response is not 'text/html'
    return proxyResData;
}

let htmlContent = proxyResData.toString('utf8');
// Do something with 'htmlContent' and return
return htmlContent;

Neste artigo, criarei um ajudante personalizado no arquivo index.hbs (página inicial) do meu tema. Em um local visível no modelo do guidão, adiciono um exemplo de ajudante personalizado, nomeando -o {{hello_world}}.

⚠️ Então, eu o coloco em um local visível na página inicial - mas observe o que acontece quando eu refresco a página fantasma!


{{!

Após a atualização, recebo uma mensagem de erro do Ghost porque o {{hello_world}} Helper não existe nos ajudantes padrão do Ghost. Para que nossa lógica funcione, devemos escapar deste ajudante para que ele não seja tratado como um ajudante pelo guidão embutido do fantasma.
{{!



After refreshing, I get an error message from Ghost because the {{hello_world}} helper doesn’t exist in Ghost's default helpers. For our logic to work, we must escape this helper so that it’s not treated as a helper by Ghost’s built-in Handlebars.

The correct way is to write this helper as \{{hello_world}}. This way, Ghost treats it as plain text. After refreshing the Ghost homepage, you should see the plain text {{hello_world}}. If this happens, you are on the right track. Let’s now return to the middleware server file, where we will use the response decorator.

⚠️ Remember to escape custom helpers in your theme! Don’t forget to add the \ character.

let htmlContent = proxyResData.toString('utf8');


// Compile Response HTML com guidão e modelo renderizado de retorno Seja htmlContent = proxyresdata.toString ('utf8'); const modelo = handlebars.compile (htmlcontent); htmlContent = modelo ({});

// Compile response HTML with Handlebars, and return rendered template
let htmlContent = proxyResData.toString('utf8');
const template = handlebars.compile(htmlContent);
htmlContent = template({});


// retorna 'Olá do middleware!' Com o registro de data e hora atual handlebars.registerhelper ('hello_world', função (opções) { Retorne `Olá do Middleware! $ {new Date (). ToisSoString ()} `; });

// Returns 'Hello from middleware!' with the current timestamp
handlebars.registerHelper('hello_world', function (options) {
   return `Hello from middleware! ${new Date().toISOString()}`;
});

Nesta fase, você pode estender seu tema fantasma com ajudantes personalizados adicionais, que você adicionará ao código do servidor de middleware.

Segurança

Em algum momento, você pode querer devolver várias coisas com seus ajudantes. Por padrão, a biblioteca protege contra ataques XSS, mas quando você usa o método de segurança, essa proteção para de funcionar. Evite usá -lo sempre que possível.

outra coisa! Imagine um usuário adiciona esse ajudante na seção de comentários em uma postagem e adiciona conteúdo malicioso no parâmetro. Esteja atento à segurança. Por exemplo, se você renderizar todos os HTML completamente, poderá estar vulnerável a ataques XSS. É recomendável compilar e renderizar guidão.js em áreas específicas e fechadas. Você pode usar a biblioteca Cheerio (https://cheerio.js.org/) para analisar HTML e renderizar guidão quando necessário. Aqui está um exemplo de como você pode se proteger modificando o código de renderização anterior:


// renderizar guidão apenas dentro

com> Neste código, nossos ajudantes e guidão personalizados são renderizados apenas dentro de um
contêiner com>
// Render handlebars only inside 
with>

In this code, our custom helpers and Handlebars are rendered only within a

container with>

Asynchronous Processing

If you intend to create dynamic helpers that return more complex data, you’ll probably need to implement asynchronous helpers in Handlebars over time. This is useful in cases like:

  • Fetching values from a database (e.g., Ghost database)
  • Sending API requests and processing their responses

You can use an extension called handlebars-async-helpers (https://www.npmjs.com/package/handlebars-async-helpers) for this purpose. It enables asynchronous operations in Handlebars.js, making potentially lengthy and dynamic tasks possible. Here’s a simple example of how you can implement asynchronous processing in your middleware:

// Register async helpers with Handlebars
const hb = asyncHelpers(handlebars);

hb.registerHelper('hello_world', async function (options) {
  // You can use await's here!
  // ...
});

Comunicação e objetos do banco de dados

Se você deseja fazer consultas de banco de dados em fantasma buscar, por exemplo, a postagem atual, é possível e não é difícil. Você pode usar uma biblioteca como o Knex (https://knexjs.org/), que é um construtor de consultas SQL claro e rápido. Lembre-se de que você precisará de hidroces-helpers para isso. Configure o Knex corretamente para se conectar ao banco de dados do Ghost.

inicialize Knex como a variável DB e tente o seguinte código:


// Retorna o título atual da postagem do banco de dados HB.RegisterHelper ('post_title', função assíncrona (opções) { const uuid = options.hash.uuid; tentar { const {title} = aguarda db ("postagens") .Select ("título") . Onde ("uuid", uuid) .limit (1) .primeiro(); título de retorno; } catch (error) {return `error: $ {error.message}`; } });

// Return current post title from database
hb.registerHelper('post_title', async function (options) {
  const uuid = options.hash.uuid;
  try {
    const { title } = await db("posts")
      .select("title")
      .where("uuid", uuid)
      .limit(1)
      .first();
    return title;
  } catch (error) { return `Error: ${error.message}`; }
});

você também pode usar o AXIOS para fazer solicitações HTTP para a API de conteúdo fantasma, mas isso é significativamente mais lento que a comunicação direta do banco de dados.

Desempenho

eu sei que uma solução baseada em middleware pode não ser a melhor em termos de velocidade, mas eu pessoalmente uso essa solução e não notei uma queda significativa nos tempos de carregamento da página. O tempo médio de resposta para uma única solicitação estava abaixo de 100ms (de acordo com o monitor de status expresso), e eu uso um ajudante personalizado que recupera alguns valores do banco de dados em todas as páginas.

Você pode, é claro, adicionar mecanismos de cache para melhorar o desempenho do middleware ou usar soluções alternativas em vez de expresso-http-proxy.

Implementação da arquitetura

use o Docker ou outro mecanismo de contêinerização. Eu o usei no meu projeto e funciona muito bem. Adicione imagens de fantasma e banco de dados para a imagem Ghost, Nginx e Node.js. Conecte -os a uma rede compartilhada (Driver: Bridge), configure o Nginx e o Node.js Server de acordo - é tudo muito simples!

Declaração de lançamento Este artigo é reproduzido em: https://dev.to/piotrbednarski/make-custom-handlebar-helpers-in-ghost-48nh?1 Se houver alguma infração, entre em contato com [email protected] para excluí-lo.
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3