@ngaox/seo
Version:
Easily generate and manage SEO-friendly meta tags, page title,...
329 lines (318 loc) • 12.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Inject, Optional, Component, Input, NgModule } from '@angular/core';
import * as i2 from '@angular/router';
import { PRIMARY_OUTLET, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';
import * as i1 from '@angular/platform-browser';
const SeoKey = 'NgaoxSeo';
const SeoDefaultsToken = Symbol('DefaultsSeoData');
class SeoService {
constructor(title, meta, document, defaults = {}) {
this.title = title;
this.meta = meta;
this.document = document;
this.defaults = defaults;
}
generateTags(definitions) {
definitions.forEach(meta => {
this.meta.updateTag(meta);
});
}
set(seoData) {
seoData = {
...this.defaults,
...seoData
};
if (seoData.title)
this.setTitle(seoData.title);
if (seoData.keywords)
this.setKeywords(seoData.keywords);
if (seoData.description)
this.setDescription(seoData.description);
if (seoData.url)
this.setUrl(seoData.url);
if (seoData.type)
this.setType(seoData.type);
if (seoData.image)
this.setImage(seoData.image);
if (seoData.twitter)
this.setTwitter(seoData.twitter);
if (seoData.fbAppId)
this.setFbAppId(seoData.fbAppId);
if (seoData.siteName)
this.setSiteName(seoData.siteName);
if (seoData.extra)
this.generateTags(seoData.extra);
}
setTitle(title) {
this.title.setTitle(title);
this.generateTags([
{ property: 'og:title', content: title },
{ name: 'twitter:title', content: title },
{ name: 'title', content: title }
]);
}
setKeywords(keywords) {
this.generateTags([{ name: 'keywords', content: keywords }]);
}
setDescription(description) {
this.generateTags([
{ name: 'description', content: description },
{ property: 'og:description', content: description },
{ name: 'twitter:description', content: description }
]);
}
setUrl(url) {
this.generateTags([{ property: 'og:url', content: url }]);
// set canonical link
const oldElement = this.document.head.querySelector(`link[rel='canonical']`);
if (oldElement) {
this.document.head.removeChild(oldElement);
}
const link = this.document.createElement('link');
link.setAttribute('rel', 'canonical');
link.setAttribute('href', url);
this.document.head.appendChild(link);
}
setType(type) {
this.generateTags([{ property: 'og:type', content: type }]);
}
setImage(image) {
if (typeof image === 'string') {
this.generateTags([
{ property: 'og:image', content: image },
{ name: 'twitter:image', content: image },
{ property: 'image', content: image }
]);
}
else {
this.generateTags([
{ property: 'og:image', content: image.url },
{ name: 'twitter:image', content: image.url },
{ property: 'image', content: image.url }
]);
if (image.url.startsWith('https')) {
this.generateTags([
{ property: 'og:image:secure_url', content: image.url }
]);
}
if (image.alt) {
this.generateTags([
{ property: 'twitter:image:alt', content: image.alt },
{ property: 'og:image:alt', content: image.alt }
]);
}
if (image.height) {
this.generateTags([
{ property: 'og:image:height', content: image.height.toString() }
]);
}
if (image.width) {
this.generateTags([
{ property: 'og:image:width', content: image.width.toString() }
]);
}
if (image.width) {
this.generateTags([
{ property: 'og:image:type', content: `${image.mimeType}` }
]);
}
}
}
setTwitter(twitterData) {
if (twitterData.site) {
this.generateTags([{ name: 'twitter:site', content: twitterData.site }]);
}
if (twitterData.creator) {
this.generateTags([
{ name: 'twitter:creator', content: twitterData.creator }
]);
}
if (twitterData.card) {
this.generateTags([{ name: 'twitter:card', content: twitterData.card }]);
}
}
setFbAppId(Id) {
this.generateTags([{ property: 'fb:app_id', content: Id }]);
}
setSiteName(siteName) {
this.generateTags([{ property: 'og:site_name', content: siteName }]);
}
}
SeoService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoService, deps: [{ token: i1.Title }, { token: i1.Meta }, { token: DOCUMENT }, { token: SeoDefaultsToken, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
SeoService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: i1.Title }, { type: i1.Meta }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [SeoDefaultsToken]
}] }]; } });
class RouteDataSeoLoader {
resolve(snapshot) {
let seoData;
let route = snapshot.root;
while (route !== undefined) {
seoData = {
...(seoData ?? {}),
...(route.data[SeoKey] ?? {})
};
route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
}
return seoData ?? {};
}
}
RouteDataSeoLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: RouteDataSeoLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
RouteDataSeoLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: RouteDataSeoLoader, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: RouteDataSeoLoader, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class SeoDataLoader {
}
function currentPageRoute(route) {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}
class SeoComponent {
constructor(seoService) {
this.seoService = seoService;
this.seoData = {};
}
ngOnInit() {
this.seoService.set(this.seoData);
}
set title(value) {
this.seoData.title = value;
this.seoService.setTitle(value);
}
set keywords(value) {
this.seoData.keywords = value;
this.seoService.setKeywords(value);
}
set description(value) {
this.seoData.description = value;
this.seoService.setDescription(value);
}
set url(value) {
this.seoData.url = value;
this.seoService.setUrl(value);
}
set type(value) {
this.seoData.type = value;
this.seoService.setType(value);
}
set image(value) {
this.seoData.image = value;
this.seoService.setImage(value);
}
set twitter(value) {
this.seoData.twitter = value;
this.seoService.setTwitter(value);
}
set fbAppId(value) {
this.seoData.fbAppId = value;
this.seoService.setFbAppId(value);
}
set siteName(value) {
this.seoData.siteName = value;
this.seoService.setSiteName(value);
}
set extra(value) {
this.seoData.extra = value;
this.seoService.generateTags(value);
}
}
SeoComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoComponent, deps: [{ token: SeoService }], target: i0.ɵɵFactoryTarget.Component });
SeoComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.8", type: SeoComponent, selector: "ngaox-seo", inputs: { title: "title", keywords: "keywords", description: "description", url: "url", type: "type", image: "image", twitter: "twitter", fbAppId: "fbAppId", siteName: "siteName", extra: "extra" }, ngImport: i0, template: ``, isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoComponent, decorators: [{
type: Component,
args: [{ selector: 'ngaox-seo', template: `` }]
}], ctorParameters: function () { return [{ type: SeoService }]; }, propDecorators: { title: [{
type: Input
}], keywords: [{
type: Input
}], description: [{
type: Input
}], url: [{
type: Input
}], type: [{
type: Input
}], image: [{
type: Input
}], twitter: [{
type: Input
}], fbAppId: [{
type: Input
}], siteName: [{
type: Input
}], extra: [{
type: Input
}] } });
class SeoModule {
constructor(Loader, router, route, seo) {
if (Loader) {
router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => {
seo.set(Loader.resolve(currentPageRoute(route).snapshot));
});
}
}
static forRoot(defaults = {
title: '📝 Default NgaoxSeo Title - Change me!'
}) {
return {
ngModule: SeoModule,
providers: [
SeoService,
{
provide: SeoDefaultsToken,
useValue: defaults
}
]
};
}
}
SeoModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoModule, deps: [{ token: SeoDataLoader }, { token: i2.Router }, { token: i2.ActivatedRoute }, { token: SeoService }], target: i0.ɵɵFactoryTarget.NgModule });
SeoModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.8", ngImport: i0, type: SeoModule, declarations: [SeoComponent], exports: [SeoComponent] });
SeoModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoModule, providers: [
{
provide: SeoDataLoader,
useClass: RouteDataSeoLoader
}
] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: SeoModule, decorators: [{
type: NgModule,
args: [{
declarations: [SeoComponent],
imports: [],
providers: [
{
provide: SeoDataLoader,
useClass: RouteDataSeoLoader
}
],
exports: [SeoComponent]
}]
}], ctorParameters: function () { return [{ type: SeoDataLoader }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: SeoService }]; } });
/*
* Public API Surface of seo
*/
/**
* Generated bundle index. Do not edit.
*/
export { RouteDataSeoLoader, SeoComponent, SeoDataLoader, SeoDefaultsToken, SeoKey, SeoModule, SeoService, currentPageRoute };
//# sourceMappingURL=ngaox-seo.mjs.map