UNPKG

@ngaox/seo

Version:

Easily generate and manage SEO-friendly meta tags, page title,...

329 lines (318 loc) 12.3 kB
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