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
133 lines (126 loc) • 5.2 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, DOCUMENT, Injectable } from '@angular/core';
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];
// Update or Add link tag if provided
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 {
// Add meta tag
this.meta.addTag(each, this.config.forceCreation ?? false);
// There might be tags which will exists.
// Just update their content
this.meta.updateTag(each);
}
}
// 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: "20.0.6", ngImport: i0, type: AngularMetaCtrl, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AngularMetaCtrl, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", 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