/** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ const domino = require('domino'); import {ɵBrowserDomAdapter as BrowserDomAdapter} from '@angular/platform-browser'; import {ɵsetRootDomAdapter as setRootDomAdapter} from '@angular/common'; function _notImplemented(methodName: string) { return new Error('This method is not implemented in DominoAdapter: ' + methodName); } function setDomTypes() { // Make all Domino types available as types in the global env. Object.assign(global, domino.impl); (global as any)['KeyboardEvent'] = domino.impl.Event; } /** * Parses a document string to a Document object. */ export function parseDocument(html: string, url = '/') { let window = domino.createWindow(html, url); let doc = window.document; return doc; } /** * Serializes a document to string. */ export function serializeDocument(doc: Document): string { return (doc as any).serialize(); } /** * DOM Adapter for the server platform based on https://github.com/fgnass/domino. */ export class DominoAdapter extends BrowserDomAdapter { static makeCurrent() { setDomTypes(); setRootDomAdapter(new DominoAdapter()); } private static defaultDoc: Document; log(error: string) { // tslint:disable-next-line:no-console console.log(error); } logGroup(error: string) { console.error(error); } logGroupEnd() {} supportsDOMEvents(): boolean { return false; } createHtmlDocument(): HTMLDocument { return parseDocument('fakeTitle'); } getDefaultDocument(): Document { if (!DominoAdapter.defaultDoc) { DominoAdapter.defaultDoc = domino.createDocument(); } return DominoAdapter.defaultDoc; } isElementNode(node: any): boolean { return node ? node.nodeType === DominoAdapter.defaultDoc.ELEMENT_NODE : false; } isShadowRoot(node: any): boolean { return node.shadowRoot == node; } getProperty(el: Element, name: string): any { if (name === 'href') { // Domino tries to resolve href-s which we do not want. Just return the // attribute value. return this.getAttribute(el, 'href'); } else if (name === 'innerText') { // Domino does not support innerText. Just map it to textContent. return el.textContent; } return (el)[name]; } getGlobalEventTarget(doc: Document, target: string): EventTarget|null { if (target === 'window') { return doc.defaultView; } if (target === 'document') { return doc; } if (target === 'body') { return doc.body; } return null; } getBaseHref(doc: Document): string { const base = doc.documentElement !.querySelector('base'); let href = ''; if (base) { href = base.getAttribute('href') !; } // TODO(alxhub): Need relative path logic from BrowserDomAdapter here? return href; } dispatchEvent(el: Node, evt: any) { el.dispatchEvent(evt); // Dispatch the event to the window also. const doc = el.ownerDocument || el; const win = (doc as any).defaultView; if (win) { win.dispatchEvent(evt); } } getHistory(): History { throw _notImplemented('getHistory'); } getLocation(): Location { throw _notImplemented('getLocation'); } getUserAgent(): string { return 'Fake user agent'; } performanceNow(): number { return Date.now(); } supportsCookies(): boolean { return false; } getCookie(name: string): string { throw _notImplemented('getCookie'); } }