UNPKG

angular-meta

Version:

angular-meta is a lightweight and flexible SEO utility for Angular applications, designed to work seamlessly with Server-Side Rendering (SSR). It dynamically updates <meta>, <link>, and structured schema tags using route data, parameters, and URL. Easily

129 lines (122 loc) 4.99 kB
import * as i0 from '@angular/core'; import { InjectionToken, inject, Injectable } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { HttpClient } from '@angular/common/http'; import { firstValueFrom, filter, map, switchMap, of } from 'rxjs'; import { Meta, Title } from '@angular/platform-browser'; import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; const ANGULAR_META_CONFIG = new InjectionToken('ANGULAR_META_CONFIG'); function provideAngularMeta(config) { return [{ provide: ANGULAR_META_CONFIG, useValue: config }]; } class AngularMetaCtrl { config = inject(ANGULAR_META_CONFIG); httpClient = inject(HttpClient); meta = inject(Meta); title = inject(Title); document = inject(DOCUMENT); router = inject(Router); activatedRoute = inject(ActivatedRoute); async getMetas(data) { return await firstValueFrom(this.httpClient.get(this.config.apiEndpoint, { params: data, headers: { 'content-type': 'application/json' }, })); } async setMetaData(data) { try { // Set title this.title.setTitle(data.title); // Set meta tags for (let i = 0, l = data.meta.length; i < l; i++) { const each = data.meta[i]; if (each.hasOwnProperty('href')) { const link = this.document.createElement('link'); if (each.hasOwnProperty('href')) { link.href = each.href; } if (each.hasOwnProperty('rel')) { link.rel = each.rel; } if (each.hasOwnProperty('type')) { link.type = each.type; } if (each.hasOwnProperty('title')) { link.title = each.title; } if (each.hasOwnProperty('media')) { link.media = each.media; } this.document.head.appendChild(link); } else { this.meta.addTag(each, this.config.forceCreation ?? false); } } // Set schema const all = this.document.head.getElementsByTagName('script'); let isExists = null; for (let i = 0, l = all.length; i < l; i++) { if (all[i].id === `ng_metas_page_json_ld`) { isExists = all[i]; break; } } if (isExists) { isExists.innerText = JSON.stringify(data.schema); } else { const script = this.document.createElement('script'); script.type = 'application/ld+json'; script.id = `ng_metas_page_json_ld`; script.innerText = JSON.stringify(data.schema); this.document.head.appendChild(script); } return true; } catch (e) { return false; } } initFromCtrl() { this.router.events .pipe(filter((event) => event instanceof NavigationEnd), map(() => this.activatedRoute), map((route) => route.firstChild), switchMap((route) => { return of({ params: route?.snapshot.params, queryParams: route?.snapshot.queryParams, data: route?.snapshot.data, url: new URL(this.document.URL).toString(), }); })) .subscribe({ next: async (response) => { const metas = await this.getMetas(response); this.setMetaData(metas); }, }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AngularMetaCtrl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AngularMetaCtrl, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AngularMetaCtrl, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); const angularMetaResolver = async (route, state) => { const document = inject(DOCUMENT); const metaCtrl = inject(AngularMetaCtrl); const params = route.params; const queryParams = route.queryParams; const data = route.data; const url = new URL(document.URL).toString(); const metaData = await metaCtrl.getMetas({ params, queryParams, data, url }); return await metaCtrl.setMetaData(metaData); }; /* * Public API Surface of ng-metas */ /** * Generated bundle index. Do not edit. */ export { AngularMetaCtrl, angularMetaResolver, provideAngularMeta }; //# sourceMappingURL=angular-meta.mjs.map