Fermer

juillet 1, 2024

Redéfinir le markdown angulaire avec Analog.js

Redéfinir le markdown angulaire avec Analog.js


L’analogique en est encore à ses débuts, mais il se passe beaucoup de choses ! Parcourez une application de démonstration pour explorer les fonctionnalités et découvrez ses capacités de démarque.

Je suis intrigué par Analog depuis que j’ai vu la vidéo de Brandon Roberts le montrant en train de construire Angulaire avec Vite. C’était la première étape pour obtenir le package Angular SSR que nous souhaitions vraiment.

L’équipe Angular a incroyablement intensifié son jeu au cours de la dernière année et demie, mais Angular SSR ne peut toujours même pas être déployé sur Vercel ou Cloudflare sans Analog sans problème. Je pense que cela finira par être corrigé lorsqu’ils fusionneront avec Asle framework interne de Google, mais pour l’instant nous avons Analog.

j’ai construit un Application Todo analogique avec Firebase pour montrer quelques nouvelles fonctionnalités, mais maintenant je suis plus intrigué par les capacités de démarque. Markdown est intégré.

TL;DR

Nous allons créer un blog avec Analogique! Ma version se concentre sur le .md fichiers au lieu du content annuaire. Vous pouvez créer des fichiers de démarques dans le pages répertoire, et cela fonctionne. J’ai également ajouté la possibilité d’analyser les fichiers de démarques dans le pages répertoire pour les titres et les métadonnées, qui ne fonctionne pas immédiatement. L’analogique pourrait être meilleur, mais il facilite le déploiement et la gestion du serveur !

Créez notre application

Tout d’abord, nous devons créer notre application analogique.

npm create analog@latest

L’analogique prend en charge le ng update format. Si nous voulons mettre à jour plus tard, nous pouvons utiliser :

ng update @analogjs/platform@latest

Analog utilise Vite avec Angular, nous pouvons donc exécuter npm run start ou npm run dev ou ng serve.

npm run start

Analog prend en charge Markdown et Front-matter

Si vous souhaitez créer un fichier markdown, créez un .md fichier avec votre contenu et placez les métadonnées de première ligne en haut. Ceci est similaire à Contenu Nuxt. Nous avons également besoin d’un PostAttribute taper. Nous pouvons mettre ça dedans models.ts.

export interface PostAttributes {
    title: string;
    slug: string;
    description: string;
    publishedAt: string;
    content: string;
};

Contenu

Écrivez vos articles et mettez-les dans le pages/blog dossier. J’aime séparer mes fichiers habituels de ma démarque. J’ai généré des articles sur l’IA. Mon application utilise également Tailwind. Le slug doit correspondre au nom du fichier. Assurez-vous que le moteur de rendu Markdown est activé app.config.ts.

provideContent(withMarkdownRenderer())

Composant d’application

Il s’agit de votre composant d’accueil, où vous pouvez déclarer votre mise en page. j’utilise prose de Tailwind pour définir les styles ici. Je génère également un an pour un droit d’auteur.

📝 Généralement, vous souhaitez générer les années et les dates sur le serveur puis hydrater la valeur du serveur auprès du client ; sur Le jour de l’An la date de votre serveur peut ne pas se réhydrater avec la même année que celle du client. J’ai juste simplifié le code.

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
 
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  template: `
  <main class="p-3 m-3 prose md:prose-lg lg:prose-xl max-w-none">
    <router-outlet></router-outlet>
     <p>© Rocky Billy {{ year }}</p>
  </main> 
  `,
  styles: [],
})
export class AppComponent {
  readonly year = new Date().getFullYear();
}
 

Résolveurs

La clé pour utiliser Angular SSR est de toujours utiliser des résolveurs lors du chargement des données. Si vous ne le faites pas, vos données risquent de ne pas se charger complètement avant que l’application ne soit rendue. Voici quelques fonctions d’assistance que j’ai créées pour cela.

export const injectResolver = <T>(name: string) =>
    inject(ActivatedRoute).data.pipe<T>(map(r => r[name]));
 
export const injectSnapResolver = <T>(name: string) =>
    inject(ActivatedRoute).snapshot.data[name] as T;

Cela facilite l’injection des données.

Obtenir la démarque

Actuellement, il n’existe aucune méthode permettant d’obtenir des noms de fichiers en dehors du content annuaire. J’ai purgé le code source pour comprendre comment procéder. import.meta.glob est la fonction magique Vite qui vous permet de faire cela. J’ai l’intention de faire un PR pour rendre cela plus facile plus tard.

function getSlug(filename: string) {
    const parts = filename.match(/^(\\|\/)(.+(\\|\/))*(.+)\.(.+)$/);
    return parts?.length ? parts[4] : '';
}
 
export const indexResolver: ResolveFn<any> = async () => {
 
    const data = import.meta.glob('/src/app/pages/blog/*.md', {
        eager: true,
        import: 'default',
        query: { 'analog-content-list': true },
    });
 
    return Object.keys(data).map((filename) => {
        const attributes = data[filename] as any;
        const slug = attributes['slug'];
 
        return {
            filename: filename.split("https://www.telerik.com/").pop()?.split('.')[0],
            slug: slug ? encodeURI(slug) : encodeURI(getSlug(filename)),
            title: attributes.title
        };
    });
};

Affichage des pages du blog

Nous utilisons la fonction précédente et l’injectons dans notre résolveur pour obtenir les noms de tous les fichiers de notre blog dossier avec un .md extension.

import { Component} from '@angular/core';
import {
  RouterLink,
  RouterOutlet
} from '@angular/router';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { RouteMeta } from '@analogjs/router';
import { PostAttributes } from '../models';
import { indexResolver, injectSnapResolver } from '../utils';
 
  
export const routeMeta: RouteMeta = {
  resolve: { data: indexResolver }
};
 
@Component({
  standalone: true,
  imports: [RouterOutlet, RouterLink, NgFor, NgIf, AsyncPipe],
  template: `
  <h1>Rocky Billy's Blog</h1>
    <ul>
      <li *ngFor="let post of posts">
        <a [routerLink]="['blog', post.slug]">{{
          post.title
        }}</a>
      </li>
    </ul>
  `,
})
export default class BlogComponent {
  readonly posts = injectSnapResolver<PostAttributes[]>('data');

Remarquez à quel point l’injection du résolveur est facile. Utilisez simplement le routeMeta objet avec ma coutume injectSnapResolver fonction.

Déploiement

Alors c’est tout!

Analog utilise Vite, ce qui rend le déploiement extrêmement simple. Puisque mon application utilise SSR, j’ai décidé de l’héberger sur Netlify. Il y a préréglages intégrés pour chaque environnement d’hébergement, même les serveurs Edge.

Dépôt : GitHub

Démo : Le blog de Rocky Billy

Articles similaires

Quelques autres articles ont abordé le concept du blog, mais je souhaite proposer le mien.

Avenir

J’adore Analog et je suis super excité par le .de fonctionnalités expérimentales. Cela vous permet de créer un composant angulaire sans le passe-partout, et votre composant ressemblera à un fichier Svelte ou Vue. Analog est encore très jeune, mais j’ai l’intention de l’aider à se développer là où je peux.




Source link