O pequeno gerador de site estático de recarga a quente do shell. Assume Bash 4.4+.
AVISO: Aqui estão iaques!
O trabalho do shite
é me ajudar a fazer meu site: https://evalapply.org Assim, o escopo do shite
, o conjunto de (des) recursos e o polonês sempre serão de nível de produção, onde a produção é "funciona na(s) minha(s) máquina(s) )" :)
Índice
Bem, shite
pretende fazer sites.
É um pequeno sistema de publicação feito de fluxos de trabalho em pipeline, opcionalmente conduzidos por fluxos de eventos de arquivo (para os bits de hotreloading).
Isso não surpreenderá um hacker cavalheiro de Perl/PHP do século passado.
Existe porque assobiamos músicas bobas e barbeamos iaques.
Isso é basicamente o que ele faz (ref: a função shite_templating_publish_sources
).
cat " ${watch_dir} /sources/ ${url_slug} " |
__shite_templating_compile_source_to_html ${file_type} |
__shite_templating_wrap_content_html ${content_type} |
__shite_templating_wrap_page_html |
${html_formatter_fn} |
tee " ${watch_dir} /public/ ${slug} .html "
# The complete "business logic" is 300-ish lines as of this comment,
# counted as all lines except comments and blank lines.
grep -E -v " s?#|^$ "
./bin/{events,metadata,templating,utils,hotreload}.sh |
wc -l
Antes que você fique muito irritado, posso avisá-lo que a licença do MIT significa que não preciso me importar se esse pequeno criador de merda não conseguir fazer sua merda funcionar. Contribuir está repleto de mais avisos.
E por último, mas não menos importante, decreto que todos os textos aqui contidos sejam lidos em Sean Connery voish.
Nos meus sonhos shite
, eu desejo...
Acima de tudo, para mantê-la (a “lógica de negócios”) pequena . Pequeno o suficiente para armazenar em cache, depurar e refatorar na minha cabeça.
Para instalar e usar sem permissão de superusuário.
Para evitar extremamente cadeias de ferramentas e construir dependências. Sem joias / npms / venvs / o que você tem. Assim, Bash é a linguagem, porque Bash está em todo lugar. E pacotes padrão como pandoc
ou tidy
, quando é necessária funcionalidade avançada específica .
Modelagem livre de dependência com HTML simples definido em bons e velhos heredocs.
Sistema simples de metadados, namespace de conteúdo, organização de ativos estáticos, etc.
Servidor Web opcional (ou qualquer tipo de processo de servidor). Afinal, nosso objetivo é criar sites estáticos que funcionem perfeitamente com a navegação file://
.
Construí-lo a partir de peças pequenas, combináveis, puramente funcionais, semelhantes a ferramentas Unix, porque gosto muito desse tipo de coisa.
Para me proporcionar um fluxo de trabalho perfeito, semelhante ao REPL, editar-salvar-construir-visualizar.
Eu acidentalmente reiniciei o blog depois de um longo haitus. Antes que eu pudesse colocar as palavras na nuvem, me atrapalhei com os "modernos" geradores de sites estáticos. Porque o WordPress é do século passado (ou assim eu disse a mim mesmo). Então fiquei irritado com a magia da construção de modelos sob medida do SSG Jamstack, etc. Agora estou no caminho sombrio de fazer isso. Está sendo blogado em: shite: sites estáticos do shell: parte 1/2
Eu uso o shite principalmente no modo "hotreload", principalmente para escrever posts (no orgmode) e visualizá-los ao vivo (no Firefox). Menos principalmente, para pré-visualizar modificações em estilos e/ou modelos de página. Pelo menos principalmente, depois de trabalhar interminavelmente em uma postagem, eu a uso no modo "não recarregar a quente" para fazer uma reconstrução completa do site.
exemplos de demonstração de merda abaixo.
Basicamente, isso significa que se eu criar, atualizar, excluir qualquer arquivo em sources
, ele deverá ser traduzido automaticamente para HTML, ser publicado localmente em public
e causar uma navegação de página apropriada ou uma ação de recarga no navegador da Web, onde meu site está aberto.
Chame o script "principal" em uma nova sessão de terminal ou painel tmux.
./shite.sh
É útil abrir o arquivo de índice no Firefox, de acordo com os padrões que defini na matriz shite_global_data
em ./shite.sh
.
No seu Emacs ou Vim, abra algum arquivo de conteúdo em sources
. Edite, salve e veja o conteúdo aparecer no navegador. (Sim, especificar Emacs/Vim é bobo, porque eu aciono ações importantes com base em eventos inotify. Aparentemente, diferentes editores fazem atualizações de arquivos de maneira diferente. Eu uso Emacs ou Vim, então observo os eventos que eles causam, para que funcione na minha máquina.: )).
Freqüentemente, o navegador se lembra da posição de rolagem, o que é legal. Às vezes o hotreload é, bem, uma merda. Então, apertei espaço e salvei o arquivo de conteúdo para acionar o hotreload novamente.
Vá para algum ativo estático, como uma folha de estilo CSS. Altere algo, como o valor da cor de fundo. Salve e observe a mudança de cor no navegador.
Ajuste algum fragmento de modelo em templates.sh
--- digamos, modelo de postagem de blog. Em seguida, mude para algum arquivo de conteúdo de postagem de blog e modifique-o para acionar a construção da página com o modelo modificado (por exemplo, pressione espaço e salve).
Isso é um truque. A página raiz index.org em fontes é especial. Se eu modificá-lo, significa que quero reconstruir listas de postagens para a página de índice, para tags e também reconstruir meta-arquivos relacionados, como feed RSS, mapa do site, robots.txt etc.
Em uma nova sessão de terminal limpa, chame shite.sh
com "no" e, opcionalmente, com o base_url
do ambiente de implantação:
Reconstrua o site completo para navegação "local" no arquivo: ///. Verdadeiramente "sem servidor" :)
./shite.sh " no "
Reconstrua o site completo para publicação no meu domínio.
./shite.sh " no " " https://evalapply.org "
Esses sinalizadores alteram o comportamento do sistema.
SHITE_BUILD
como "hot" executará o sistema de eventos no modo "monitor", que por sua vez aciona o comportamento de hotreload. Definir como "não" suprimirá o hotreload do navegador.SHITE_DEBUG_TEMPLATES
como "debug" fará com que os modelos sejam originados primeiro, antes de publicar qualquer conteúdo de origem do modelo. shite
é bastante Unixy por dentro. Ou assim eu gostaria de pensar.
O código é Bash no estilo de programação funcional. Tudo é uma função. A maioria das funções são funções puras – pequenas ferramentas Unix em si. A maior parte da lógica é orientada para pipeline. Isso funciona surpreendentemente bem, porque a Shell não é um lugar ruim para FP.
Eu também queria uma experiência interativa ao vivo do tipo REPL ao escrever com shite
, porque gosto de trabalhar em tempos de execução interativos/ao vivo como Clojure e Emacs.
Então, shite
se tornou um sistema totalmente reativo orientado a eventos, capaz de construir e recarregar ao salvar a quente.
Existem três namespaces de diretório principais:
sources
que abrigam o conteúdo "fonte", como postagens de blog escritas em modo organizacional, bem como CSS, Javascript e outros ativos estáticos.public
para os artefatos compilados/construídosbin
para o código de construção de merda O esquema de nomenclatura de URL segue a estrutura de subdiretórios em sources
e é replicado como está na estrutura de diretórios pubilic
. Como este é um esquema padrão de namespace de URL, ele também se aplica diretamente ao conteúdo publicado. Assim:
file:///absolute/path/to/shite/posts/slug/index.html
http://localhost:8080/posts/slug/index.html
https://your-domain-name.com/posts/slug/index.html
Todas as funções "públicas" têm namespace como shite_the_func_name
. Todas as funções "privadas" têm namespace como __shite_the_func_name
.
Existem funções para:
Em uma nova sessão de terminal limpa:
source ./bin/utils_dev.sh
shitTABTAB
ou __shiTABTAB
na linha de comando para preenchimento automático.type -a func_name
para imprimir a definição da função e ler sua API.shite_global_data
e shite_page_data
conforme necessário. Existem modelos para fragmentos de página (como cabeçalho, rodapé, navegação) e para definições de página completa (como o modelo de página padrão). Eles são escritos como HTML simples agrupados em heredocs. ./bin/templates.sh
fornece isso.
Os modelos são preenchidos com dados variáveis de diferentes fontes:
shite_global_data
contém metadados de todo o site e shite_page_data
contém metadados específicos da página. Algum processo externo deve pré-definir essas matrizes antes de processar qualquer página.Por exemplo, uma página inteira pode ser construída da seguinte forma:
cat ./sample/hello.md |
pandoc -f markdown -t html |
cat << EOF
<!DOCTYPE html>
<html>
<head>
$( shite_template_common_meta )
$( shite_template_common_links )
${shite_page_data[canonical_url]}
</head>
<body ${shite_page_data[page_id]} >
$( shite_template_common_header )
<main>
$( cat - )
</main>
$( shite_template_common_footer )
</body>
</html>
EOF
O sistema de metadados de shite
é definido como pares de valores-chave. As chaves nomeiam os itens de metadados e seriam associadas a qualquer valor desse tipo. Exemplos abaixo.
Conforme observado anteriormente, os metadados de tempo de execução são transportados no ambiente pelas matrizes associativas shite_global_data
e shite_page_data
. Estes podem ser preenchidos por construção direta, bem como atualizados a partir de fontes externas.
Cada página pode especificar seus próprios metadados no “assunto inicial” no topo da página. Isso será usado além dos metadados da página derivados de outras fontes.
shite
espera que escrevamos o assunto inicial usando uma sintaxe compatível com o tipo de conteúdo fornecido, como segue.
Use linhas de comentários # SHITE_META
para demarcar os metadados de estilo organizacional que shite
também deve analisar como metadados específicos da página.
# SHITE_META
#+title: This is a Title
#+slug: this/is/a/slug
#+date: Friday 26 August 2022 03:38:01 PM IST
#+tags: foo bar baz quxx
# SHITE_META
#+more_org_metadata: but not processed as shite metadata
#+still_more_org_metadata: and still not processed as shite metadata
* this is a top level heading
this is some orgmode content
#+TOC: headlines 1 local
** this is a sub heading
- this is a point
- this is another point
- a third point
Escreva o tema YAML no estilo Jekyll, encaixado entre ---
separadores.
---
TITLE : This is a Title
slug : this/is/a/slug
DATE : Friday 26 August 2022 03:38:01 PM IST
TAGS : foo BAR baz QUXX
---
# this is a heading
this is some markdown content
## this is a subheading
- this is a point
- this is another point
- a third point
Podemos simplesmente usar tags <meta>
padrão, que obedecem a esta convenção: <meta name="KEY" content="value">
.
< meta name =" TITLE " content =" This is a Title " >
< meta name =" slug " content =" this/is/a/slug " >
< meta name =" DATE " content =" Friday 26 August 2022 03:38:01 PM IST " >
< meta name =" TAGS " content =" foo BAR baz QUXX " >
< h1 > This is a heading </ h1 >
< p > This is some text </ p >
< h2 > This is a subheading </ h2 >
< p >
< ul >
< li > This is a point </ li >
< li > This is another point. </ li >
< li > This is a third point. </ li >
</ ul >
</ p >
Aqui estão Iaques!
Sendo totalmente estragado pelos fluxos de trabalho interativos ao vivo e gratificantes no estilo Clojure/Lisp/Planilha, também quero recarregar e navegar a quente na criação de merda.
Mas parece não existir um servidor/ferramenta de desenvolvimento web autônomo e ativo que também não queira que eu baixe metade da Internet conhecida como dependências. Como eu disse antes, algo que eu extremamente não quero fazer.
DuckSearch entregou o modo impaciente do Emacs, o que é bastante quente, mas não quero conectar este meu Emacs. Felizmente, ele também forneceu esta onda cerebral emocionante com 'inotify-tools' e 'xdotool': github.com/traviscross/inotify-refresh
Cópia quente!
Porque o que poderia ser mais quente do que meu computador apertando a tecla F5 para mim? Como se soubesse o que eu realmente queria no fundo do meu coração.
O subsistema de eventos é ortogonal a todo o resto e se compõe com o resto do sistema.
O design é uma arquitetura de streaming padrão, viz. observe os eventos do sistema de arquivos e, em seguida, filtre, desduplique, analise e encaminhe-os (tee) para diferentes processadores de eventos. Atualmente existem apenas dois desses processadores; um para compilar e publicar a página ou ativo associado ao evento, outro para recarregar o navegador (ou navegar a quente) dependendo do mesmo evento.
Basicamente isso:
# detect file events
__shite_detect_changes ${watch_dir} ' create,modify,close_write,moved_to,delete ' |
__shite_events_gen_csv ${watch_dir} |
# hot-compile-and-publish content, HTML, static, etc.
tee >( shite_templating_publish_sources > /dev/null ) |
# browser hot-reload
tee >( __shite_hot_cmd_public_events ${window_id} ${base_url} |
__shite_hot_cmd_exec )
Os eventos são simplesmente um fluxo de registros CSV estruturados assim:
unix_epoch_seconds,event_type,base_dir,sub_dir,url_slug,file_type,content_type `
Usamos diferentes partes do registro do evento para causar diferentes tipos de ações.
O script inotify-refresh vinculado anteriormente tenta atualizar periodicamente um conjunto de janelas do navegador. Nós, no entanto, queremos estar muito ansiosos. Qualquer ação de edição em nossos arquivos de conteúdo e/ou ativos estáticos deve acionar instantaneamente ações de recarga/navegação na guia do navegador que está exibindo nossa merda.
Queremos definir cenários de recarga distintos: buckets mutuamente exclusivos e coletivamente exaustivos nos quais podemos mapear eventos de arquivo que queremos monitorar.
Se fizermos isso, poderemos modelar as atualizações como uma espécie de log write-ahead, perfurando eventos por meio de um pipeline de análise, associá-los ao cenário de correspondência exata e, finalmente, causar a ação. Por exemplo:
Atualizar guia atual quando
Vá para casa quando
Navegue até o conteúdo quando
Como estamos fazendo o computador emular nossas próprias ações de teclado, ele pode atrapalhar nossas ações pessoais. Se nos limitarmos a escrever nossas merdas em nosso editor de texto e deixarmos o computador fazer o hotreloady, não deveremos permanecer aborrecidos.
Existem muitos Iaques no mundo.
Para um encanto de publicação multisite verdadeiramente difundido:
shite
deve estar disponível no meu PATHEste é um pequeno iaque. Provavelmente vou fazer a barba em breve.
Obviamente, pode-se usar os trabalhos de CI de hosts git populares para acionar compilações shite
. Mas por que usar a tecnologia desajeitada do século atual, quando já avançamos para o estado da arte do final dos anos 1900... totalmente streaming e totalmente reativo?
Sarcasam à parte, não vejo por que o mesmo sistema de eventos não pode ser usado para adicionar suporte de implantação a quente em uma máquina remota que eu executo.
Na caixa remota:
sources
do site é consagradosources
(menos a observação do navegador).Na minha caixa local:
https://mydomain.com/posts/hello/index.html
Faça algo através do SSH para trazer a atualização do navegador de volta para a caixa local, no caso de implantações a quente no servidor remoto.
Talvez algum cenário de configuração de tempo/desmontagem de "Desenvolvimento/Esboço"? Talvez uma função 'dev_server' que usamos para iniciar uma nova sessão de escrita de merda?
Se você chegou até aqui e ainda quer contribuir...
Por que?
Por que, em nome de tudo o que é sagrado e bom, você iria querer isso? Não é extremamente óbvio que este é o trabalho de um idiota? Você nunca ouviu falar que Bash nem é uma linguagem de programação real? E não é óbvio que seus PRs irão definhar eternamente e seus comentários cairão em um vazio sem nome?
Sim, enviar patches é uma péssima ideia.
Mas, por favor, envie-me um e-mail com suas esperanças e sonhos sobre o seu criador de merda! Eu li e-mails no meu nome, ponto, sobrenome no Gmail.
Juntos podemos assobiar músicas bobas e fazer a barba dos nossos respectivos iaques, à nossa maneira especial.
Que a Fonte esteja conosco.
Este trabalho possui licença dupla sob a licença MIT e a licença CC By-SA 4.0.
Identificador de licença SPDX: mit OR cc-by-sa-4.0