├── .editorconfig
├── .github
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── main.yml
├── .gitignore
├── .npmignore
├── .vscode
├── launch.json
└── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── dist
├── dom.js
├── feature.js
├── global.js
├── index.js
├── nodejs-dom.js
├── nodejs-feature.js
├── nodejs-global.js
├── nodejs-pal-builder.js
├── nodejs-platform.js
├── observer.js
├── performance.js
├── platform.js
└── types
│ ├── dom.d.ts
│ ├── feature.d.ts
│ ├── global.d.ts
│ ├── index.d.ts
│ ├── nodejs-dom.d.ts
│ ├── nodejs-feature.d.ts
│ ├── nodejs-global.d.ts
│ ├── nodejs-pal-builder.d.ts
│ ├── nodejs-platform.d.ts
│ ├── observer.d.ts
│ ├── performance.d.ts
│ └── platform.d.ts
├── doc
├── CHANGELOG.md
├── MAINTAINER.md
└── api.json
├── package-lock.json
├── package.json
├── src
├── dom.ts
├── feature.ts
├── global.ts
├── index.ts
├── nodejs-dom.ts
├── nodejs-feature.ts
├── nodejs-global.ts
├── nodejs-pal-builder.ts
├── nodejs-platform.ts
├── observer.ts
├── performance.ts
└── platform.ts
├── test
├── nodejs-dom.spec.ts
├── nodejs-pal-builder.spec.ts
├── nodejs-platform.spec.ts
└── support
│ └── jasmine.json
├── tsconfig.build.json
├── tsconfig.json
└── tsfmt.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = false
13 | insert_final_newline = false
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
18 | # 2 space indentation
19 | [**.*]
20 | indent_style = space
21 | indent_size = 2
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
19 | **I'm submitting a bug report**
20 | **I'm submitting a feature request**
21 |
22 | * **Library Version:**
23 | major.minor.patch-pre
24 |
25 |
26 | **Please tell us about your environment:**
27 | * **Operating System:**
28 | OSX 10.x|Linux (distro)|Windows [7|8|8.1|10]
29 |
30 | * **Node Version:**
31 | 6.2.0
32 |
36 |
37 | * **NPM Version:**
38 | 3.8.9
39 |
43 |
44 | * **JSPM OR Webpack AND Version**
45 | JSPM 0.16.32 | webpack 2.1.0-beta.17
46 |
52 |
53 | * **Browser:**
54 | all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView
55 |
56 | * **Language:**
57 | all | TypeScript X.X | ESNext
58 |
59 |
60 | **Current behavior:**
61 |
62 |
63 | **Expected/desired behavior:**
64 |
71 |
72 |
73 | * **What is the expected behavior?**
74 |
75 |
76 | * **What is the motivation / use case for changing the behavior?**
77 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Make sure you check the following:
2 | * [ ] unless trivial, a corresponding issue exists for this PR (reference it)
3 | * [ ] if this PR fixes the issue, then include `fix #` and the issue number
4 | * [ ] if this PR adds a feature, then you've included tests in `spec/`
5 | * [ ] you've ran `gulp test` and it passes the lint and spec
6 | * [ ] you've prepended the PR description i.e. (chore):, (feat):, (fix):
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: main
2 | on: [push]
3 |
4 | jobs:
5 |
6 | ci:
7 | timeout-minutes: 10
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | - uses: actions/setup-node@v1
12 | with:
13 | node-version: 16
14 | - run: npm ci
15 | - run: npm run cut-release
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | jspm_packages
3 | .idea
4 | .DS_STORE
5 | build/reports
6 | spec/*.js
7 | spec/*.map
8 | .npmrc
9 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .github
3 | .idea
4 | *.map
5 | doc/
6 | spec/
7 | build/
8 | src/
9 | .editorconfig
10 | circle.yml
11 | CONTRIBUTING.md
12 | gulpfile.js
13 | ISSUE_TEMPLATE.md
14 | tsconfig.json
15 | tsfmt.json
16 | tslint.json
17 |
18 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Launch Tests",
6 | "type": "node",
7 | "request": "launch",
8 | "program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js",
9 | "stopOnEntry": false,
10 | "args": [
11 | "dev:debug"
12 | ],
13 | "cwd": "${workspaceRoot}",
14 | "preLaunchTask": "dev:pre-debug",
15 | "internalConsoleOptions": "openOnSessionStart",
16 | "runtimeExecutable": null,
17 | "runtimeArgs": [
18 | "--nolazy"
19 | ],
20 | "env": {
21 | "NODE_ENV": "development"
22 | },
23 | "externalConsole": false,
24 | "sourceMaps": true,
25 | "outDir": "${workspaceRoot}/dist"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "**/*.map":true,
5 | "**/*.js": {
6 | "when": "$(basename).ts"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We'd love for you to contribute and to make this project even better than it is today! If this interests you, please begin by reading [our contributing guidelines](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md). The contributing document will provide you with all the information you need to get started. Once you have read that, you will need to also [sign our CLA](http://goo.gl/forms/dI8QDDSyKR) before we can accept a Pull Request from you. More information on the process is included in the [contributor's guide](https://github.com/DurandalProject/about/blob/master/CONTRIBUTING.md).
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2010 - 2018 Blue Spire Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | [](https://opensource.org/licenses/MIT)
8 | [](https://www.npmjs.com/package/aurelia-templating-resources)
9 | 
10 | [](https://discourse.aurelia.io)
11 | [](https://twitter.com/intent/follow?screen_name=aureliaeffect)
12 | [](https://discord.gg/RBtyM6u)
13 |
14 | # aurelia-pal-nodejs
15 |
16 | This library is part of the [Aurelia](http://www.aurelia.io/) platform and contains the node-specific implementation of the platform abstraction layer.
17 |
18 | > To keep up to date on [Aurelia](http://www.aurelia.io/), please visit and subscribe to [the official blog](http://blog.aurelia.io/) and [our email list](http://eepurl.com/ces50j). We also invite you to [follow us on twitter](https://twitter.com/aureliaeffect). If you have questions look around our [Discourse forums](https://discourse.aurelia.io/), chat in our [community on Discord](https://discord.gg/RBtyM6u) or use [stack overflow](http://stackoverflow.com/search?q=aurelia). Documentation can be found [in our developer hub](http://aurelia.io/docs).
19 |
20 | ## Platform Support
21 |
22 | This library can be used in **NodeJS**.
23 |
24 | # Building The Code
25 |
26 | To build the code, follow these steps.
27 |
28 | 1. Ensure that [NodeJS](http://nodejs.org/) is installed. This provides the platform on which the build tooling runs.
29 | 2. From the project folder, execute the following command:
30 |
31 | ```shell
32 | npm install
33 | ```
34 | 3. To test the code, run:
35 |
36 | ```shell
37 | npm test
38 | ```
39 | 4. To build the code, run:
40 |
41 | ```shell
42 | npm run build
43 | ```
44 | 5. You will find the compiled code in the `dist` folder in CommonJS module format.
45 |
46 | # Acknowledgement
47 |
48 | This software used a snippet borrowed from [browser-env](https://github.com/lukechilds/browser-env).
49 |
--------------------------------------------------------------------------------
/dist/dom.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/feature.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/global.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.reset = exports.globalize = exports.initialize = exports.ensurePerformance = void 0;
4 | const aurelia_pal_1 = require("aurelia-pal");
5 | const nodejs_pal_builder_1 = require("./nodejs-pal-builder");
6 | var nodejs_pal_builder_2 = require("./nodejs-pal-builder");
7 | Object.defineProperty(exports, "ensurePerformance", { enumerable: true, get: function () { return nodejs_pal_builder_2.ensurePerformance; } });
8 | function initialize() {
9 | if (aurelia_pal_1.isInitialized) {
10 | return;
11 | }
12 | let pal = (0, nodejs_pal_builder_1.buildPal)();
13 | (0, aurelia_pal_1.initializePAL)((platform, feature, dom) => {
14 | Object.assign(platform, pal.platform);
15 | Object.setPrototypeOf(platform, pal.platform.constructor.prototype);
16 | Object.assign(dom, pal.dom);
17 | Object.setPrototypeOf(dom, pal.dom.constructor.prototype);
18 | Object.assign(feature, pal.feature);
19 | Object.setPrototypeOf(feature, pal.feature.constructor.prototype);
20 | (function (global) {
21 | global.console = global.console || {};
22 | let con = global.console;
23 | let prop;
24 | let method;
25 | let empty = {};
26 | let dummy = function () { };
27 | let properties = 'memory'.split(',');
28 | let methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
29 | 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
30 | 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
31 | while (prop = properties.pop())
32 | if (!con[prop])
33 | con[prop] = empty;
34 | while (method = methods.pop())
35 | if (!con[method])
36 | con[method] = dummy;
37 | })(platform.global);
38 | if (platform.global.console && typeof console.log === 'object') {
39 | if (typeof console['debug'] === 'undefined') {
40 | console['debug'] = this.bind(console['log'], console);
41 | }
42 | ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'].forEach(function (method) {
43 | console[method] = this.bind(console[method], console);
44 | }, Function.prototype.call);
45 | }
46 | Object.defineProperty(dom, 'title', {
47 | get: function () {
48 | return pal.global.document.title;
49 | },
50 | set: function (value) {
51 | pal.global.document.title = value;
52 | }
53 | });
54 | Object.defineProperty(dom, 'activeElement', {
55 | get: function () {
56 | return pal.global.document.activeElement;
57 | }
58 | });
59 | Object.defineProperty(platform, 'XMLHttpRequest', {
60 | get: function () {
61 | return pal.global.XMLHttpRequest;
62 | }
63 | });
64 | });
65 | }
66 | exports.initialize = initialize;
67 | function createBrowserGlobals() {
68 | Object.getOwnPropertyNames(aurelia_pal_1.PLATFORM.global)
69 | .filter(prop => typeof global[prop] === 'undefined' && prop !== 'undefined')
70 | .forEach(prop => global[prop] = aurelia_pal_1.PLATFORM.global[prop]);
71 | }
72 | function globalize() {
73 | initialize();
74 | createBrowserGlobals();
75 | global.System = {
76 | import(moduleId) {
77 | try {
78 | return Promise.resolve(require(moduleId));
79 | }
80 | catch (e) {
81 | return Promise.reject(e);
82 | }
83 | }
84 | };
85 | global.PAL = {
86 | DOM: aurelia_pal_1.DOM, PLATFORM: aurelia_pal_1.PLATFORM, FEATURE: aurelia_pal_1.FEATURE
87 | };
88 | return global;
89 | }
90 | exports.globalize = globalize;
91 | function reset(window) {
92 | if (window) {
93 | window.close();
94 | }
95 | }
96 | exports.reset = reset;
97 |
--------------------------------------------------------------------------------
/dist/nodejs-dom.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.NodeJsDom = void 0;
4 | class NodeJsDom {
5 | constructor(global) {
6 | this.global = global;
7 | this.boundary = 'aurelia-dom-boundary';
8 | this.title = "";
9 | this.activeElement = null;
10 | this.Element = global.Element;
11 | this.NodeList = global.NodeList;
12 | this.SVGElement = global.SVGElement || class SVGElement extends global.Element {
13 | };
14 | }
15 | addEventListener(eventName, callback, capture) {
16 | return this.global.document.addEventListener(eventName, callback, capture);
17 | }
18 | removeEventListener(eventName, callback, capture) {
19 | return this.global.document.removeEventListener(eventName, callback, capture);
20 | }
21 | createElement(tagName) {
22 | return this.global.document.createElement(tagName);
23 | }
24 | createAttribute(name) {
25 | return this.global.document.createAttribute(name);
26 | }
27 | createTextNode(text) {
28 | return this.global.document.createTextNode(text);
29 | }
30 | createComment(text) {
31 | return this.global.document.createComment(text);
32 | }
33 | createDocumentFragment() {
34 | return this.global.document.createDocumentFragment();
35 | }
36 | createTemplateElement() {
37 | return this.global.document.createElement('template');
38 | }
39 | createMutationObserver(callback) {
40 | return new (this.global.window.MutationObserver)(callback);
41 | }
42 | createCustomEvent(eventType, options) {
43 | return new this.global.CustomEvent(eventType, options);
44 | }
45 | dispatchEvent(evt) {
46 | this.global.window.dispatchEvent(evt);
47 | }
48 | getComputedStyle(element) {
49 | return this.global.window.getComputedStyle(element);
50 | }
51 | getElementById(id) {
52 | return this.global.document.getElementById(id);
53 | }
54 | querySelector(query) {
55 | return this.global.document.querySelector(query);
56 | }
57 | querySelectorAll(query) {
58 | return this.global.document.querySelectorAll(query);
59 | }
60 | nextElementSibling(element) {
61 | return element.nextElementSibling;
62 | }
63 | createTemplateFromMarkup(markup) {
64 | let parser = this.global.document.createElement('div');
65 | parser.innerHTML = markup;
66 | let temp = parser.firstElementChild;
67 | if (!temp || temp.nodeName !== 'TEMPLATE') {
68 | throw new Error('Template markup must be wrapped in a element e.g. ');
69 | }
70 | return temp;
71 | }
72 | injectStyles(styles, destination, prepend) {
73 | let node = this.global.document.createElement('style');
74 | node.innerHTML = styles;
75 | node.type = 'text/css';
76 | destination = destination || this.global.document.head;
77 | if (prepend && destination.childNodes.length > 0) {
78 | destination.insertBefore(node, destination.childNodes[0]);
79 | }
80 | else {
81 | destination.appendChild(node);
82 | }
83 | return node;
84 | }
85 | adoptNode(node) {
86 | return this.global.document.adoptNode(node);
87 | }
88 | appendNode(newNode, parentNode) {
89 | (parentNode || this.global.document.body).appendChild(newNode);
90 | }
91 | replaceNode(newNode, node, parentNode) {
92 | if (node.parentNode) {
93 | node.parentNode.replaceChild(newNode, node);
94 | }
95 | else {
96 | parentNode.replaceChild(newNode, node);
97 | }
98 | }
99 | removeNode(node, parentNode) {
100 | if (node.parentNode) {
101 | node.parentNode.removeChild(node);
102 | }
103 | else {
104 | parentNode.removeChild(node);
105 | }
106 | }
107 | }
108 | exports.NodeJsDom = NodeJsDom;
109 |
--------------------------------------------------------------------------------
/dist/nodejs-feature.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.NodeJsFeature = void 0;
4 | class NodeJsFeature {
5 | constructor(global) {
6 | this.global = global;
7 | this.shadowDOM = this.global.window.HTMLElement.prototype.attachShadow != undefined;
8 | this.scopedCSS = 'scoped' in this.global.document.createElement('style');
9 | this.htmlTemplateElement = true;
10 | this.mutationObserver = true;
11 | }
12 | }
13 | exports.NodeJsFeature = NodeJsFeature;
14 |
--------------------------------------------------------------------------------
/dist/nodejs-global.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aurelia/pal-nodejs/56eeb2275f5cd016089e5da96a62bf4fd5ebc9c2/dist/nodejs-global.js
--------------------------------------------------------------------------------
/dist/nodejs-pal-builder.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.ensurePerformance = exports.buildPal = void 0;
4 | const nodejs_platform_1 = require("./nodejs-platform");
5 | const nodejs_feature_1 = require("./nodejs-feature");
6 | const nodejs_dom_1 = require("./nodejs-dom");
7 | const jsdom_1 = require("jsdom");
8 | function buildPal() {
9 | var jsdom = new jsdom_1.JSDOM(undefined, { url: "http://localhost/" });
10 | var global = jsdom.window;
11 | ensurePerformance(global.window);
12 | var platform = new nodejs_platform_1.NodeJsPlatform(global, jsdom);
13 | var dom = new nodejs_dom_1.NodeJsDom(global);
14 | var feature = new nodejs_feature_1.NodeJsFeature(global);
15 | return {
16 | global: global,
17 | platform: platform,
18 | dom: dom,
19 | feature: feature
20 | };
21 | }
22 | exports.buildPal = buildPal;
23 | let intersectSetter = function (proto, propertyName, intersect) {
24 | let old = Object.getOwnPropertyDescriptor(proto, propertyName);
25 | let oldSet = old.set;
26 | let newSet = function set(V) {
27 | oldSet.call(this, V);
28 | intersect(this);
29 | };
30 | Object.defineProperty(proto, propertyName, {
31 | set: newSet,
32 | get: old.get,
33 | configurable: old.configurable,
34 | enumerable: old.enumerable
35 | });
36 | };
37 | let intersectMethod = function (proto, methodName, intersect) {
38 | let orig = proto[methodName];
39 | proto[methodName] = function (...args) {
40 | var ret = orig.apply(this, args);
41 | intersect(this);
42 | return ret;
43 | };
44 | };
45 | function ensurePerformance(window) {
46 | const _entries = [];
47 | const _marksIndex = {};
48 | function _filterEntries(key, value) {
49 | var i = 0, n = _entries.length, result = [];
50 | for (; i < n; i++) {
51 | if (_entries[i][key] == value) {
52 | result.push(_entries[i]);
53 | }
54 | }
55 | return result;
56 | }
57 | function _clearEntries(type, name) {
58 | var i = _entries.length, entry;
59 | while (i--) {
60 | entry = _entries[i];
61 | if (entry.entryType == type && (name === void 0 || entry.name == name)) {
62 | _entries.splice(i, 1);
63 | }
64 | }
65 | }
66 | ;
67 | if (window.performance === undefined) {
68 | window.performance = {};
69 | }
70 | if (window.performance.now === undefined) {
71 | let nowOffset = Date.now();
72 | window.performance.now = function now() {
73 | return Date.now() - nowOffset;
74 | };
75 | }
76 | if (!window.performance.mark) {
77 | window.performance.mark = window.performance.webkitMark || function (name) {
78 | const mark = {
79 | name,
80 | entryType: "mark",
81 | startTime: window.performance.now(),
82 | duration: 0
83 | };
84 | _entries.push(mark);
85 | _marksIndex[name] = mark;
86 | };
87 | }
88 | if (!window.performance.measure) {
89 | window.performance.measure = window.performance.webkitMeasure || function (name, startMark, endMark) {
90 | startMark = _marksIndex[startMark].startTime;
91 | endMark = _marksIndex[endMark].startTime;
92 | _entries.push({
93 | name,
94 | entryType: "measure",
95 | startTime: startMark,
96 | duration: endMark - startMark
97 | });
98 | };
99 | }
100 | if (!window.performance.getEntriesByType) {
101 | window.performance.getEntriesByType = window.performance.webkitGetEntriesByType || function (type) {
102 | return _filterEntries("entryType", type);
103 | };
104 | }
105 | if (!window.performance.getEntriesByName) {
106 | window.performance.getEntriesByName = window.performance.webkitGetEntriesByName || function (name) {
107 | return _filterEntries("name", name);
108 | };
109 | }
110 | if (!window.performance.clearMarks) {
111 | window.performance.clearMarks = window.performance.webkitClearMarks || function (name) {
112 | _clearEntries("mark", name);
113 | };
114 | }
115 | if (!window.performance.clearMeasures) {
116 | window.performance.clearMeasures = window.performance.webkitClearMeasures || function (name) {
117 | _clearEntries("measure", name);
118 | };
119 | }
120 | }
121 | exports.ensurePerformance = ensurePerformance;
122 |
--------------------------------------------------------------------------------
/dist/nodejs-platform.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.NodeJsPlatform = void 0;
4 | class NodeJsPlatform {
5 | constructor(global, jsdom) {
6 | this.global = global;
7 | this.jsdom = jsdom;
8 | this.noop = () => { };
9 | this.performance = this.global.performance;
10 | this.location = this.global.location;
11 | this.history = this.global.history;
12 | this.XMLHttpRequest = this.global.XMLHttpRequest;
13 | }
14 | requestAnimationFrame(callback) {
15 | return setImmediate(() => callback(Date.now()));
16 | }
17 | eachModule(callback) {
18 | }
19 | addEventListener(eventName, callback, capture) {
20 | this.global.addEventListener(eventName, callback, capture);
21 | }
22 | removeEventListener(eventName, callback, capture) {
23 | this.global.removeEventListener(eventName, callback, capture);
24 | }
25 | }
26 | exports.NodeJsPlatform = NodeJsPlatform;
27 |
--------------------------------------------------------------------------------
/dist/observer.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/performance.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/platform.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/dist/types/dom.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Represents the core APIs of the DOM.
3 | */
4 | export interface IDom {
5 | /**
6 | * The global DOM Element type.
7 | */
8 | Element: typeof Element;
9 | /**
10 | * The global DOM SVGElement type.
11 | */
12 | SVGElement: typeof SVGElement;
13 | /**
14 | * A key representing a DOM boundary.
15 | */
16 | boundary: string;
17 | /**
18 | * The document title.
19 | */
20 | title: string;
21 | /**
22 | * The document's active/focused element.
23 | */
24 | activeElement: Element;
25 | /**
26 | * Add an event listener to the document.
27 | * @param eventName A string representing the event type to listen for.
28 | * @param callback The function that receives a notification when an event of the specified type occurs.
29 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
30 | */
31 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
32 | /**
33 | * Remove an event listener from the document.
34 | * @param eventName A string representing the event type to listen for.
35 | * @param callback The function to remove from the event.
36 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
37 | */
38 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
39 | /**
40 | * Adopts a node from an external document.
41 | * @param node The node to be adopted.
42 | * @return The adopted node able to be used in the document.
43 | */
44 | adoptNode(node: Node): Node;
45 | /**
46 | * Creates the specified HTML element or an HTMLUnknownElement if the given element name isn't a known one.
47 | * @param tagName A string that specifies the type of element to be created.
48 | * @return The created element.
49 | */
50 | createElement(tagName: T): HTMLElementTagNameMap[T];
51 | createElement(tagName: string): HTMLElement;
52 | /**
53 | * Creates the specified HTML attribute
54 | * @param name A string that specifies the name of attribute to be created.
55 | * @return The created attribute.
56 | */
57 | createAttribute(name: string): Attr;
58 | /**
59 | * Creates a new Text node.
60 | * @param text A string to populate the new Text node.
61 | * @return A Text node.
62 | */
63 | createTextNode(text: string): Text;
64 | /**
65 | * Creates a new Comment node.
66 | * @param text A string to populate the new Comment node.
67 | * @return A Comment node.
68 | */
69 | createComment(text: string): Comment;
70 | /**
71 | * Creates a new DocumentFragment.
72 | * @return A DocumentFragment.
73 | */
74 | createDocumentFragment(): DocumentFragment;
75 | /**
76 | * Creates a new MutationObserver.
77 | * @param callback A callback that will recieve the change records with the mutations.
78 | * @return A MutationObservere.
79 | */
80 | createMutationObserver(callback: (changes: MutationRecord[], instance: MutationObserver) => void): MutationObserver;
81 | /**
82 | * Creates a new CustomEvent.
83 | * @param eventType A string representing the event type.
84 | * @param options An options object specifying bubbles:boolean, cancelable:boolean and/or detail:Object information.
85 | * @return A CustomEvent.
86 | */
87 | createCustomEvent(eventType: string, options: Object): CustomEvent;
88 | /**
89 | * Dispatches an event on the document.
90 | * @param evt The event to dispatch.
91 | */
92 | dispatchEvent(evt: Event): void;
93 | /**
94 | * Gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.
95 | * @param element The Element for which to get the computed style.
96 | * @return The computed styles.
97 | */
98 | getComputedStyle(element: Element): CSSStyleDeclaration;
99 | /**
100 | * Locates an element in the document according to its id.
101 | * @param id The id to search the document for.
102 | * @return The found element.
103 | */
104 | getElementById(id: string): Element;
105 | /**
106 | * Performs a query selector on the document and returns first matched element, depth first.
107 | * @param query The query to use in searching the document.
108 | * @return A list of all matched elements in the document.
109 | */
110 | querySelector(selectors: string): E | null;
111 | /**
112 | * Performs a query selector on the document and returns all located matches.
113 | * @param query The query to use in searching the document.
114 | * @return A list of all matched elements in the document.
115 | */
116 | querySelectorAll(selectors: string): NodeListOf;
117 | /**
118 | * Gets the element that is the next sibling of the provided element.
119 | * @param element The element whose next sibling is being located.
120 | * @return The next sibling Element of the provided Element.
121 | */
122 | nextElementSibling(element: Node): Element;
123 | /**
124 | * Creates an HTMLTemplateElement using the markup provided.
125 | * @param markup A string containing the markup to turn into a template. Note: This string must contain the template element as well.
126 | * @return The instance of HTMLTemplateElement that was created from the provided markup.
127 | */
128 | createTemplateFromMarkup(markup: string): HTMLTemplateElement;
129 | /**
130 | * Appends a node to the parent, if provided, or the document.body otherwise.
131 | * @param newNode The node to append.
132 | * @param parentNode The node to append to, otherwise the document.body.
133 | */
134 | appendNode(newNode: Node, parentNode?: Node): void;
135 | /**
136 | * Replaces a node in the parent with a new node.
137 | * @param newNode The node to replace the old node with.
138 | * @param node The node that is being replaced.
139 | * @param parentNode The node that the current node is parented to.
140 | */
141 | replaceNode(newNode: Node, node: Node, parentNode?: Node): void;
142 | /**
143 | * Removes the specified node from the parent node.
144 | * @param node The node to remove.
145 | * @param parentNode The parent node from which the node will be removed.
146 | */
147 | removeNode(node: Node, parentNode?: Node): void;
148 | /**
149 | * Injects styles into the destination element, or the document.head if no destination is provided.
150 | * @param styles The css text to injext.
151 | * @param destination The destination element to inject the css text into. If not specified it will default to the document.head.
152 | * @param prepend Indicates whether or not the styles should be prepended to the destination. By default they are appended.
153 | * @return The Style node that was created.
154 | */
155 | injectStyles(styles: string, destination?: Element, prepend?: boolean): Node;
156 | }
157 |
--------------------------------------------------------------------------------
/dist/types/feature.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Enables discovery of what features the runtime environment supports.
3 | */
4 | export interface IFeature {
5 | /**
6 | * Does the runtime environment support ShadowDOM?
7 | */
8 | shadowDOM: boolean;
9 | /**
10 | * Does the runtime environment support the css scoped attribute?
11 | */
12 | scopedCSS: boolean;
13 | /**
14 | * Does the runtime environment support native HTMLTemplateElement?
15 | */
16 | htmlTemplateElement: boolean;
17 | /**
18 | * Does the runtime environment support native DOM mutation observers?
19 | */
20 | mutationObserver: boolean;
21 | }
22 |
--------------------------------------------------------------------------------
/dist/types/global.d.ts:
--------------------------------------------------------------------------------
1 | import { DOMWindow, JSDOM } from 'jsdom';
2 | export interface IGlobal extends DOMWindow {
3 | MutationObserver: typeof MutationObserver;
4 | Element: typeof Element;
5 | NodeList: typeof NodeList;
6 | jsdom: typeof JSDOM;
7 | SVGElement: typeof SVGElement;
8 | XMLHttpRequest: typeof XMLHttpRequest;
9 | CustomEvent: typeof CustomEvent;
10 | }
11 |
--------------------------------------------------------------------------------
/dist/types/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export { ensurePerformance } from './nodejs-pal-builder';
3 | /**
4 | * Initializes the PAL with the NodeJS-targeted implementation.
5 | */
6 | export declare function initialize(): void;
7 | /**
8 | * @description initializes and makes variables like 'window' into NodeJS globals
9 | */
10 | export declare function globalize(): typeof globalThis;
11 | export declare function reset(window?: Window): void;
12 |
--------------------------------------------------------------------------------
/dist/types/nodejs-dom.d.ts:
--------------------------------------------------------------------------------
1 | import { IDom } from './dom';
2 | import { IGlobal } from './global';
3 | declare module './global' {
4 | interface IGlobal {
5 | window: any;
6 | document: any;
7 | }
8 | }
9 | /**
10 | * Represents the core APIs of the DOM.
11 | */
12 | export declare class NodeJsDom implements IDom {
13 | global: IGlobal;
14 | constructor(global: IGlobal);
15 | Element: typeof Element;
16 | NodeList: typeof NodeList;
17 | SVGElement: typeof SVGElement | any;
18 | boundary: string;
19 | title: string;
20 | activeElement: Element;
21 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
22 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
23 | createElement(tagName: T): HTMLElementTagNameMap[T];
24 | createAttribute(name: string): Attr;
25 | createTextNode(text: string): Text;
26 | createComment(text: string): Comment;
27 | createDocumentFragment(): DocumentFragment;
28 | createTemplateElement(): HTMLTemplateElement;
29 | createMutationObserver(callback: (changes: MutationRecord[], instance: MutationObserver) => void): MutationObserver;
30 | createCustomEvent(eventType: string, options?: Object): CustomEvent;
31 | dispatchEvent(evt: Event): void;
32 | getComputedStyle(element: Element): CSSStyleDeclaration;
33 | getElementById(id: string): Element;
34 | querySelector(query: string): E | null;
35 | querySelectorAll(query: string): NodeListOf;
36 | nextElementSibling(element: Element): Element;
37 | createTemplateFromMarkup(markup: string): HTMLTemplateElement;
38 | injectStyles(styles: string, destination?: Element, prepend?: boolean): Node;
39 | adoptNode(node: Node): Node;
40 | appendNode(newNode: Node, parentNode?: Node): void;
41 | replaceNode(newNode: Node, node: Node, parentNode?: Node): void;
42 | removeNode(node: Node, parentNode?: Node): void;
43 | }
44 |
--------------------------------------------------------------------------------
/dist/types/nodejs-feature.d.ts:
--------------------------------------------------------------------------------
1 | import { IFeature } from './feature';
2 | import { IGlobal } from './global';
3 | export declare class NodeJsFeature implements IFeature {
4 | private global;
5 | constructor(global: IGlobal);
6 | shadowDOM: boolean;
7 | scopedCSS: boolean;
8 | htmlTemplateElement: boolean;
9 | mutationObserver: boolean;
10 | }
11 |
--------------------------------------------------------------------------------
/dist/types/nodejs-global.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace NodeJS {
2 | interface Global {
3 | window: typeof window;
4 | self: typeof window;
5 | document: typeof Window.prototype.document;
6 | Element: typeof Element;
7 | NodeList: typeof NodeList;
8 | SVGElement: typeof SVGElement;
9 | HTMLElement: typeof HTMLElement;
10 | requestAnimationFrame: typeof requestAnimationFrame;
11 | location: typeof location;
12 | history: typeof history;
13 | System: {
14 | import(moduleId: string): Promise;
15 | };
16 | PAL: {
17 | DOM: any;
18 | PLATFORM: any;
19 | FEATURE: any;
20 | };
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/dist/types/nodejs-pal-builder.d.ts:
--------------------------------------------------------------------------------
1 | import { IPlatform } from './platform';
2 | import { IGlobal } from './global';
3 | import { IDom } from './dom';
4 | import { IFeature } from './feature';
5 | export declare function buildPal(): {
6 | global: IGlobal;
7 | platform: IPlatform;
8 | dom: IDom;
9 | feature: IFeature;
10 | };
11 | export declare function ensurePerformance(window: any): void;
12 |
--------------------------------------------------------------------------------
/dist/types/nodejs-platform.d.ts:
--------------------------------------------------------------------------------
1 | import { IPlatform } from './platform';
2 | import { IPerformance } from './performance';
3 | import { IGlobal } from './global';
4 | import { JSDOM } from 'jsdom';
5 | declare module './global' {
6 | interface IGlobal {
7 | performance: any;
8 | location: any;
9 | history: any;
10 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
11 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
12 | }
13 | }
14 | export declare class NodeJsPlatform implements IPlatform {
15 | global: IGlobal;
16 | jsdom: JSDOM;
17 | constructor(global: IGlobal, jsdom: JSDOM);
18 | /**
19 | * A function wich does nothing.
20 | */
21 | noop: Function;
22 | /**
23 | * The runtime's location API.
24 | */
25 | location: Object;
26 | /**
27 | * The runtime's history API.
28 | */
29 | history: Object;
30 | /**
31 | * The runtime's performance API
32 | */
33 | performance: IPerformance;
34 | /**
35 | * Registers a function to call when the system is ready to update (repaint) the display.
36 | * @param callback The function to call.
37 | * @return A long integer value, the request id, that uniquely identifies the entry in the callback list.
38 | */
39 | requestAnimationFrame(callback: (animationFrameStart: number) => void): number;
40 | /**
41 | * Iterate all modules loaded by the script loader.
42 | * @param callback A callback that will receive each module id along with the module object. Return true to end enumeration.
43 | */
44 | eachModule(callback: (key: string, value: Object) => boolean): void;
45 | /**
46 | * Add a global event listener.
47 | * @param eventName A string representing the event type to listen for.
48 | * @param callback The function that receives a notification when an event of the specified type occurs.
49 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
50 | */
51 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
52 | /**
53 | * Remove a global event listener.
54 | * @param eventName A string representing the event type to listen for.
55 | * @param callback The function to remove from the event.
56 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
57 | */
58 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
59 | /**
60 | * The runtime's XMLHttpRequest API.
61 | */
62 | XMLHttpRequest: typeof XMLHttpRequest;
63 | }
64 |
--------------------------------------------------------------------------------
/dist/types/observer.d.ts:
--------------------------------------------------------------------------------
1 | export interface IObserver {
2 | target: Node;
3 | options?: MutationObserverInit;
4 | callback: (mutations: MutationRecord[]) => void;
5 | }
6 |
--------------------------------------------------------------------------------
/dist/types/performance.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The runtime's performance API.
3 | */
4 | export interface IPerformance {
5 | /**
6 | * Gets a DOMHighResTimeStamp.
7 | * @return The timestamp, measured in milliseconds, accurate to one thousandth of a millisecond.
8 | */
9 | now(): number;
10 | /**
11 | * Removes the given mark from the browser's performance entry buffer.
12 | *
13 | * @param {string} [markName] A DOMString representing the name of the timestamp. If this argument is omitted, all performance entries with an entry type of "mark" will be removed.
14 | * @memberof IPerformance
15 | */
16 | clearMarks(markName?: string): void;
17 | /**
18 | * Removes the given measure from the browser's performance entry buffer.
19 | *
20 | * @param {string} [measureName] A DOMString representing the name of the timestamp. If this argument is omitted, all performance entries with an entry type of "measure" will be removed.
21 | * @memberof IPerformance
22 | */
23 | clearMeasures(measureName?: string): void;
24 | /**
25 | * Returns a list of PerformanceEntry objects based on the given name and entry type.
26 | *
27 | * @param {string} name The name of the entry to retrieve
28 | * @param {string} [entryType] The type of entry to retrieve such as "mark". The valid entry types are listed in PerformanceEntry.entryType.
29 | * @returns {*}
30 | * @memberof IPerformance
31 | */
32 | getEntriesByName(name: string, entryType?: string): any;
33 | /**
34 | * Returns a list of PerformanceEntry objects of the given entry type.
35 | *
36 | * @param {string} entryType The type of entry to retrieve such as "mark". The valid entry types are listed in PerformanceEntry.entryType.
37 | * @returns {*}
38 | * @memberof IPerformance
39 | */
40 | getEntriesByType(entryType: string): any;
41 | /**
42 | * Creates a timestamp in the browser's performance entry buffer with the given name.
43 | *
44 | * @param {string} markName a DOMString representing the name of the mark
45 | * @memberof IPerformance
46 | */
47 | mark(markName: string): void;
48 | /**
49 | * Creates a named timestamp in the browser's performance entry buffer between two specified marks (known as the start mark and end mark, respectively).
50 | *
51 | * @param {string} measureName a DOMString representing the name of the measure.
52 | * @param {string} [startMarkName] A DOMString representing the name of the measure's starting mark. May also be the name of a PerformanceTiming property.
53 | * @param {string} [endMarkName] A DOMString representing the name of the measure's ending mark. May also be the name of a PerformanceTiming property.
54 | * @memberof IPerformance
55 | */
56 | measure(measureName: string, startMarkName?: string, endMarkName?: string): void;
57 | }
58 |
--------------------------------------------------------------------------------
/dist/types/platform.d.ts:
--------------------------------------------------------------------------------
1 | import { IPerformance } from './performance';
2 | /**
3 | * Represents the core APIs of the runtime environment.
4 | */
5 | export interface IPlatform {
6 | /**
7 | * The runtime environment's global.
8 | */
9 | global: any;
10 | /**
11 | * A function wich does nothing.
12 | */
13 | noop: Function;
14 | /**
15 | * The runtime's location API.
16 | */
17 | location: Object;
18 | /**
19 | * The runtime's history API.
20 | */
21 | history: Object;
22 | /**
23 | * The runtime's performance API
24 | */
25 | performance: IPerformance;
26 | /**
27 | * Registers a function to call when the system is ready to update (repaint) the display.
28 | * @param callback The function to call.
29 | * @return A long integer value, the request id, that uniquely identifies the entry in the callback list.
30 | */
31 | requestAnimationFrame(callback: (animationFrameStart: number) => void): number;
32 | /**
33 | * Iterate all modules loaded by the script loader.
34 | * @param callback A callback that will receive each module id along with the module object. Return true to end enumeration.
35 | */
36 | eachModule(callback: (key: string, value: Object) => boolean): void;
37 | /**
38 | * Add a global event listener.
39 | * @param eventName A string representing the event type to listen for.
40 | * @param callback The function that receives a notification when an event of the specified type occurs.
41 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
42 | */
43 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
44 | /**
45 | * Remove a global event listener.
46 | * @param eventName A string representing the event type to listen for.
47 | * @param callback The function to remove from the event.
48 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
49 | */
50 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
51 | /**
52 | * The runtime's XMLHttpRequest API.
53 | */
54 | XMLHttpRequest: typeof XMLHttpRequest;
55 | }
56 |
--------------------------------------------------------------------------------
/doc/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ## [3.0.0-rc.2](https://github.com/aurelia/pal-nodejs/compare/3.0.0-rc.1...3.0.0-rc.2) (2024-05-06)
6 |
7 |
8 | ### Bug Fixes
9 |
10 | * filter out not writable "undefined" property from globals ([69227d3](https://github.com/aurelia/pal-nodejs/commit/69227d3bb56daa99ffc9e61a80c93d1da8516389))
11 |
12 | ## [3.0.0-rc.1](https://github.com/aurelia/pal-nodejs/compare/2.0.0...3.0.0-rc.1) (2022-05-21)
13 |
14 | * Update `jsdom` to version 19, close [#46](https://github.com/aurelia/pal-nodejs/issues/46)
15 |
16 |
17 | # [2.0.0](https://github.com/aurelia/pal-nodejs/compare/1.2.0...2.0.0) (2020-02-28)
18 |
19 |
20 | ### Bug Fixes
21 |
22 | * **platform:** type mismatch ([c823413](https://github.com/aurelia/pal-nodejs/commit/c823413))
23 |
24 |
25 | ### Features
26 |
27 | * update jsdom v15.0.0 to improve compatibility of browser simulation ([dfc8b36](https://github.com/aurelia/pal-nodejs/commit/dfc8b36)), closes [aurelia/cli#1019](https://github.com/aurelia/cli/issues/1019)
28 |
29 |
30 |
31 |
32 | ## [1.1.1](https://github.com/aurelia/pal-nodejs/compare/1.1.0...1.1.1) (2018-06-12)
33 |
34 | ### Bug Fixes
35 |
36 | * **mutation-observer:** MutationObserver not handling changes to CharacterData.data
37 |
38 |
39 | # [1.0.0-beta.3.3.0](https://github.com/aurelia/pal-nodejs/compare/1.0.0-beta.3.2.0...1.0.0-beta.3.3.0) (2018-04-17)
40 |
41 | ### Features
42 |
43 | * Updated to support new PAL methods and typings.
44 |
45 |
46 | # [1.0.0-beta.3.2.0](https://github.com/aurelia/pal-nodejs/compare/1.0.0-beta.3.1.0...1.0.0-beta.3.2.0) (2018-03-06)
47 |
48 |
49 | ### Features
50 |
51 | * **performance:** update performance API ([1508a8b](https://github.com/aurelia/pal-nodejs/commit/1508a8b))
52 |
53 |
54 |
55 |
56 | # [1.0.0-beta.3.1.0](https://github.com/aurelia/pal-nodejs/compare/1.0.0-beta.3.0.0...1.0.0-beta.3.1.0) (2018-03-03)
57 |
58 | ### Features
59 |
60 | * **dom:** add NodeList to global ([20ce260](https://github.com/aurelia/pal-nodejs/commit/20ce260))
61 |
62 | ### Bug Fixes
63 |
64 | * **global:** add missing interface element to fix compile errors ([fa2bbd3](https://github.com/aurelia/pal-nodejs/commit/fa2bbd3))
65 |
66 |
67 |
68 |
69 | # [1.0.0-beta.2.0.0](https://github.com/aurelia/pal-nodejs/compare/1.0.0-beta.1.0.0...1.0.0-beta.2.0.0) (2017-08-22)
70 |
71 |
72 | ### Bug Fixes
73 |
74 | * **whole-text:** remove unnecessary wholeText polyfill ([348a272](https://github.com/aurelia/pal-nodejs/commit/348a272))
75 |
76 |
77 | ### Features
78 |
79 | * **dom:** add createTemplateElement ([8158b02](https://github.com/aurelia/pal-nodejs/commit/8158b02))
80 | * **dom:** implement createAttribute ([e926bd9](https://github.com/aurelia/pal-nodejs/commit/e926bd9))
81 | * **index:** add reset function ([a33a116](https://github.com/aurelia/pal-nodejs/commit/a33a116))
82 | * **jsdom:** update jsdom ([d8e6239](https://github.com/aurelia/pal-nodejs/commit/d8e6239))
83 |
84 |
85 |
86 |
87 | # [1.0.0-beta.1.0.0](https://github.com/aurelia/pal-nodejs/compare/1.0.0-alpha.5...v1.0.0-beta.1.0.0) (2016-12-07)
88 |
89 |
90 | ### Bug Fixes
91 |
92 | * **build:** correct spec require fix ([de0dca4](https://github.com/aurelia/pal-nodejs/commit/de0dca4))
93 | * **index:** alias console.debug to console.log ([6eae254](https://github.com/aurelia/pal-nodejs/commit/6eae254))
94 | * **index:** use proper objects for globalization ([06ad303](https://github.com/aurelia/pal-nodejs/commit/06ad303))
95 | * **jsdom-whole-text:** polyfill actual Text class too ([bb2c0f8](https://github.com/aurelia/pal-nodejs/commit/bb2c0f8))
96 | * **jsdom-whole-text:** use hasOwnProperty ([bf02c14](https://github.com/aurelia/pal-nodejs/commit/bf02c14))
97 | * **nodejs-dom:** fallback to a dummy class for SVGElement ([e406710](https://github.com/aurelia/pal-nodejs/commit/e406710))
98 | * **nodejs-global:** add the missing globals ([1f6e596](https://github.com/aurelia/pal-nodejs/commit/1f6e596))
99 | * **nodejs-global:** remove XMLHttpRequest ([d20ffb0](https://github.com/aurelia/pal-nodejs/commit/d20ffb0))
100 | * **typings:** updated types breaking the build ([e797969](https://github.com/aurelia/pal-nodejs/commit/e797969))
101 | * **whole-text:** do not polyfill if implemented ([d497559](https://github.com/aurelia/pal-nodejs/commit/d497559))
102 |
103 |
104 | ### Features
105 |
106 | * **index:** globalize returns global scope ([b1b001d](https://github.com/aurelia/pal-nodejs/commit/b1b001d))
107 | * **index:** move isInitialized to aurelia-pal ([b7ce21a](https://github.com/aurelia/pal-nodejs/commit/b7ce21a))
108 | * **nodejs-global:** add exported globalize function ([55c2ffd](https://github.com/aurelia/pal-nodejs/commit/55c2ffd))
109 | * **whole-text:** add [@jdanyow](https://github.com/jdanyow)'s wholeText jsdom polyfill ([a414eb7](https://github.com/aurelia/pal-nodejs/commit/a414eb7))
110 |
--------------------------------------------------------------------------------
/doc/MAINTAINER.md:
--------------------------------------------------------------------------------
1 | ## Workflow releasing a new version
2 |
3 | 1. Update: pull latest master with `git pull`
4 | 2. Cut release: Run `npm run cut-release`. Example:
5 |
6 | ```shell
7 | # automatic versioning
8 | npm run cut-release
9 | # manual version
10 | npm run cut-release -- -- --release-as minor
11 | npm run cut-release -- -- --release-as 1.x.x-beta
12 | ```
13 | 3. Commit: `git add .` and then `git commit chore(release): prepare release XXX` where `XXX` is the new version
14 | 4. Tag: `git tag -a XXX -m 'prepare release XXX'` where `XXX` is the version
15 | 5. Push to remote repo: `git push --follow-tags`
16 | 6. Publish: Run `npm publish` to release the new version
17 |
--------------------------------------------------------------------------------
/doc/api.json:
--------------------------------------------------------------------------------
1 | {"name":"aurelia-pal-nodejs","children":[{"id":4,"name":"globalize","kind":64,"kindString":"Function","flags":{"isExported":true},"signatures":[{"id":5,"name":"globalize","kind":4096,"kindString":"Call signature","flags":{},"comment":{"tags":[{"tag":"description","text":"initializes and makes variables like 'window' into NodeJS globals\n"}]},"type":{"type":"reference","name":"Global"}}],"sources":[{"fileName":"index.d.ts","line":10,"character":33}]},{"id":2,"name":"initialize","kind":64,"kindString":"Function","flags":{"isExported":true},"signatures":[{"id":3,"name":"initialize","kind":4096,"kindString":"Call signature","flags":{},"comment":{"shortText":"Initializes the PAL with the NodeJS-targeted implementation."},"type":{"type":"intrinsic","name":"void"}}],"sources":[{"fileName":"index.d.ts","line":6,"character":34}]},{"id":6,"name":"reset","kind":64,"kindString":"Function","flags":{"isExported":true},"signatures":[{"id":7,"name":"reset","kind":4096,"kindString":"Call signature","flags":{},"parameters":[{"id":8,"name":"window","kind":32768,"kindString":"Parameter","flags":{"isOptional":true},"type":{"type":"reference","name":"Window"}}],"type":{"type":"intrinsic","name":"void"}}],"sources":[{"fileName":"index.d.ts","line":11,"character":29}]}],"groups":[{"title":"Functions","kind":64,"children":[4,2,6]}]}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aurelia-pal-nodejs",
3 | "version": "3.0.0-rc.2",
4 | "description": "The Node.js-specific implementation of Aurelia's platform abstraction layer.",
5 | "keywords": [
6 | "aurelia",
7 | "pal",
8 | "nodejs"
9 | ],
10 | "homepage": "http://aurelia.io",
11 | "bugs": {
12 | "url": "https://github.com/aurelia/pal-nodejs/issues"
13 | },
14 | "license": "MIT",
15 | "author": "Rob Eisenberg (http://robeisenberg.com/)",
16 | "contributors": [
17 | "Meirion Hughes (https://github.com/MeirionHughes)",
18 | "Martin Gustafsson (https://github.com/martingust)",
19 | "Devan Patel (https://github.com/devanp92)"
20 | ],
21 | "main": "dist/index.js",
22 | "typings": "dist/types/index.d.ts",
23 | "files": [
24 | "dist",
25 | "doc/CHANGELOG.md",
26 | "LICENSE"
27 | ],
28 | "scripts": {
29 | "prebuild": "rimraf dist",
30 | "build": "tsc -p tsconfig.build.json",
31 | "build:dts": "tsc -p tsconfig.build.json --emitDeclarationOnly --declaration true --declarationDir dist/types --removeComments false",
32 | "postbuild": "npm run build:dts",
33 | "test": "ts-node node_modules/jasmine/bin/jasmine --config=test/support/jasmine.json",
34 | "changelog": "standard-version -t \"\" -i doc/CHANGELOG.md --skip.commit --skip.tag",
35 | "precut-release": "npm run test && npm run build",
36 | "cut-release": "npm run changelog"
37 | },
38 | "repository": {
39 | "type": "git",
40 | "url": "http://github.com/aurelia/pal-nodejs"
41 | },
42 | "dependencies": {
43 | "aurelia-pal": "^1.8.2",
44 | "jsdom": ">= 19"
45 | },
46 | "devDependencies": {
47 | "@types/jasmine": "^5.1.4",
48 | "@types/jsdom": "^21.1.6",
49 | "@types/node": "^20.12.8",
50 | "jasmine": "^5.1.0",
51 | "jasmine-core": "^5.1.2",
52 | "rimraf": "^5.0.5",
53 | "standard-version": "^9.5.0",
54 | "ts-node": "^10.9.2",
55 | "tslib": "^2.6.2",
56 | "typescript": "^4.9.5"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/dom.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Represents the core APIs of the DOM.
3 | */
4 | export interface IDom {
5 | /**
6 | * The global DOM Element type.
7 | */
8 | Element: typeof Element;
9 |
10 | /**
11 | * The global DOM SVGElement type.
12 | */
13 | SVGElement: typeof SVGElement;
14 | /**
15 | * A key representing a DOM boundary.
16 | */
17 | boundary: string;
18 | /**
19 | * The document title.
20 | */
21 | title: string;
22 | /**
23 | * The document's active/focused element.
24 | */
25 | activeElement: Element;
26 | /**
27 | * Add an event listener to the document.
28 | * @param eventName A string representing the event type to listen for.
29 | * @param callback The function that receives a notification when an event of the specified type occurs.
30 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
31 | */
32 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
33 | /**
34 | * Remove an event listener from the document.
35 | * @param eventName A string representing the event type to listen for.
36 | * @param callback The function to remove from the event.
37 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
38 | */
39 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void;
40 | /**
41 | * Adopts a node from an external document.
42 | * @param node The node to be adopted.
43 | * @return The adopted node able to be used in the document.
44 | */
45 | adoptNode(node: Node): Node;
46 | /**
47 | * Creates the specified HTML element or an HTMLUnknownElement if the given element name isn't a known one.
48 | * @param tagName A string that specifies the type of element to be created.
49 | * @return The created element.
50 | */
51 | createElement(tagName: T): HTMLElementTagNameMap[T];
52 | createElement(tagName: string): HTMLElement;
53 | /**
54 | * Creates the specified HTML attribute
55 | * @param name A string that specifies the name of attribute to be created.
56 | * @return The created attribute.
57 | */
58 | createAttribute(name: string): Attr;
59 | /**
60 | * Creates a new Text node.
61 | * @param text A string to populate the new Text node.
62 | * @return A Text node.
63 | */
64 | createTextNode(text: string): Text;
65 | /**
66 | * Creates a new Comment node.
67 | * @param text A string to populate the new Comment node.
68 | * @return A Comment node.
69 | */
70 | createComment(text: string): Comment;
71 | /**
72 | * Creates a new DocumentFragment.
73 | * @return A DocumentFragment.
74 | */
75 | createDocumentFragment(): DocumentFragment;
76 | /**
77 | * Creates a new MutationObserver.
78 | * @param callback A callback that will recieve the change records with the mutations.
79 | * @return A MutationObservere.
80 | */
81 | createMutationObserver(callback: (changes: MutationRecord[], instance: MutationObserver) => void): MutationObserver;
82 | /**
83 | * Creates a new CustomEvent.
84 | * @param eventType A string representing the event type.
85 | * @param options An options object specifying bubbles:boolean, cancelable:boolean and/or detail:Object information.
86 | * @return A CustomEvent.
87 | */
88 | createCustomEvent(eventType: string, options: Object): CustomEvent;
89 | /**
90 | * Dispatches an event on the document.
91 | * @param evt The event to dispatch.
92 | */
93 | dispatchEvent(evt: Event): void;
94 | /**
95 | * Gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.
96 | * @param element The Element for which to get the computed style.
97 | * @return The computed styles.
98 | */
99 | getComputedStyle(element: Element): CSSStyleDeclaration;
100 | /**
101 | * Locates an element in the document according to its id.
102 | * @param id The id to search the document for.
103 | * @return The found element.
104 | */
105 | getElementById(id: string): Element;
106 |
107 | /**
108 | * Performs a query selector on the document and returns first matched element, depth first.
109 | * @param query The query to use in searching the document.
110 | * @return A list of all matched elements in the document.
111 | */
112 | querySelector(selectors: string): E | null;
113 |
114 | /**
115 | * Performs a query selector on the document and returns all located matches.
116 | * @param query The query to use in searching the document.
117 | * @return A list of all matched elements in the document.
118 | */
119 | querySelectorAll(selectors: string): NodeListOf;
120 | /**
121 | * Gets the element that is the next sibling of the provided element.
122 | * @param element The element whose next sibling is being located.
123 | * @return The next sibling Element of the provided Element.
124 | */
125 | nextElementSibling(element: Node): Element;
126 | /**
127 | * Creates an HTMLTemplateElement using the markup provided.
128 | * @param markup A string containing the markup to turn into a template. Note: This string must contain the template element as well.
129 | * @return The instance of HTMLTemplateElement that was created from the provided markup.
130 | */
131 | createTemplateFromMarkup(markup: string): HTMLTemplateElement;
132 | /**
133 | * Appends a node to the parent, if provided, or the document.body otherwise.
134 | * @param newNode The node to append.
135 | * @param parentNode The node to append to, otherwise the document.body.
136 | */
137 | appendNode(newNode: Node, parentNode?: Node): void;
138 | /**
139 | * Replaces a node in the parent with a new node.
140 | * @param newNode The node to replace the old node with.
141 | * @param node The node that is being replaced.
142 | * @param parentNode The node that the current node is parented to.
143 | */
144 | replaceNode(newNode: Node, node: Node, parentNode?: Node): void;
145 | /**
146 | * Removes the specified node from the parent node.
147 | * @param node The node to remove.
148 | * @param parentNode The parent node from which the node will be removed.
149 | */
150 | removeNode(node: Node, parentNode?: Node): void;
151 | /**
152 | * Injects styles into the destination element, or the document.head if no destination is provided.
153 | * @param styles The css text to injext.
154 | * @param destination The destination element to inject the css text into. If not specified it will default to the document.head.
155 | * @param prepend Indicates whether or not the styles should be prepended to the destination. By default they are appended.
156 | * @return The Style node that was created.
157 | */
158 | injectStyles(styles: string, destination?: Element, prepend?: boolean): Node;
159 | }
160 |
--------------------------------------------------------------------------------
/src/feature.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Enables discovery of what features the runtime environment supports.
3 | */
4 | export interface IFeature {
5 | /**
6 | * Does the runtime environment support ShadowDOM?
7 | */
8 | shadowDOM: boolean;
9 | /**
10 | * Does the runtime environment support the css scoped attribute?
11 | */
12 | scopedCSS: boolean;
13 | /**
14 | * Does the runtime environment support native HTMLTemplateElement?
15 | */
16 | htmlTemplateElement: boolean;
17 |
18 | /**
19 | * Does the runtime environment support native DOM mutation observers?
20 | */
21 | mutationObserver: boolean;
22 | }
23 |
--------------------------------------------------------------------------------
/src/global.ts:
--------------------------------------------------------------------------------
1 | import { DOMWindow, JSDOM } from 'jsdom';
2 |
3 | export interface IGlobal extends DOMWindow {
4 | MutationObserver: typeof MutationObserver;
5 | Element: typeof Element;
6 | NodeList: typeof NodeList;
7 | jsdom: typeof JSDOM;
8 | SVGElement: typeof SVGElement;
9 | XMLHttpRequest: typeof XMLHttpRequest;
10 | CustomEvent: typeof CustomEvent;
11 | }
12 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { initializePAL, DOM, PLATFORM, FEATURE, isInitialized } from 'aurelia-pal';
4 | import { buildPal } from './nodejs-pal-builder';
5 | export { ensurePerformance } from './nodejs-pal-builder';
6 |
7 | /**
8 | * Initializes the PAL with the NodeJS-targeted implementation.
9 | */
10 | export function initialize(): void {
11 | if (isInitialized) {
12 | return;
13 | }
14 |
15 | let pal = buildPal();
16 |
17 | initializePAL((platform, feature, dom) => {
18 | Object.assign(platform, pal.platform);
19 | Object.setPrototypeOf(platform, pal.platform.constructor.prototype);
20 |
21 | Object.assign(dom, pal.dom);
22 | Object.setPrototypeOf(dom, pal.dom.constructor.prototype);
23 |
24 | Object.assign(feature, pal.feature);
25 | Object.setPrototypeOf(feature, pal.feature.constructor.prototype);
26 |
27 | (function (global) {
28 | global.console = global.console || {};
29 | let con = global.console;
30 | let prop;
31 | let method;
32 | let empty = {};
33 | let dummy = function () { };
34 | let properties = 'memory'.split(',');
35 | let methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
36 | 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
37 | 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
38 | while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;
39 | while (method = methods.pop()) if (!con[method]) con[method] = dummy;
40 | })(platform.global);
41 |
42 | if (platform.global.console && typeof console.log === 'object') {
43 | if (typeof console['debug'] === 'undefined') {
44 | console['debug'] = this.bind(console['log'], console);
45 | }
46 | ['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd'].forEach(function (method) {
47 | console[method] = this.bind(console[method], console);
48 | }, Function.prototype.call);
49 | }
50 |
51 | Object.defineProperty(dom, 'title', {
52 | get: function () {
53 | return pal.global.document.title;
54 | },
55 | set: function (value) {
56 | pal.global.document.title = value;
57 | }
58 | });
59 |
60 | Object.defineProperty(dom, 'activeElement', {
61 | get: function () {
62 | return pal.global.document.activeElement;
63 | }
64 | });
65 |
66 | Object.defineProperty(platform, 'XMLHttpRequest', {
67 | get: function () {
68 | return pal.global.XMLHttpRequest;
69 | }
70 | });
71 | });
72 | }
73 |
74 | // snippet copied from https://github.com/lukechilds/browser-env
75 | function createBrowserGlobals() {
76 | Object.getOwnPropertyNames(PLATFORM.global)
77 | // avoid conflict with nodejs globals
78 | .filter(prop => typeof global[prop] === 'undefined' && prop !== 'undefined')
79 | .forEach(prop => global[prop] = PLATFORM.global[prop]);
80 | }
81 |
82 | /**
83 | * @description initializes and makes variables like 'window' into NodeJS globals
84 | */
85 | export function globalize() {
86 | initialize();
87 | createBrowserGlobals();
88 | global.System = {
89 | import(moduleId: string) {
90 | try {
91 | return Promise.resolve(require(moduleId));
92 | } catch (e) {
93 | return Promise.reject(e);
94 | }
95 | }
96 | };
97 | global.PAL = {
98 | DOM, PLATFORM, FEATURE
99 | };
100 | return global;
101 | }
102 |
103 | export function reset(window?: Window) {
104 | if (window) {
105 | window.close();
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/nodejs-dom.ts:
--------------------------------------------------------------------------------
1 | import { IDom } from './dom';
2 | import { IGlobal } from './global';
3 |
4 | declare module './global' {
5 | interface IGlobal {
6 | window: any;
7 | document: any;
8 | }
9 | }
10 |
11 | /**
12 | * Represents the core APIs of the DOM.
13 | */
14 | export class NodeJsDom implements IDom {
15 |
16 | constructor(public global: IGlobal) {
17 | this.Element = global.Element;
18 | this.NodeList = global.NodeList;
19 | this.SVGElement = global.SVGElement || class SVGElement extends global.Element { };
20 | }
21 |
22 | Element: typeof Element;
23 | NodeList: typeof NodeList;
24 | SVGElement: typeof SVGElement /* until a proper implementation is ready: */ | any;
25 | boundary: string = 'aurelia-dom-boundary';
26 | title: string = "";
27 | activeElement: Element = null;
28 |
29 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void {
30 | return this.global.document.addEventListener(eventName, callback, capture);
31 | }
32 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture: boolean): void {
33 | return this.global.document.removeEventListener(eventName, callback, capture);
34 | }
35 | createElement(tagName: T): HTMLElementTagNameMap[T];
36 | createElement(tagName: string): Element {
37 | return this.global.document.createElement(tagName);
38 | }
39 | createAttribute(name: string): Attr {
40 | return this.global.document.createAttribute(name);
41 | }
42 | createTextNode(text: string): Text {
43 | return this.global.document.createTextNode(text);
44 | }
45 | createComment(text: string): Comment {
46 | return this.global.document.createComment(text);
47 | }
48 | createDocumentFragment(): DocumentFragment {
49 | return this.global.document.createDocumentFragment();
50 | }
51 | createTemplateElement(): HTMLTemplateElement {
52 | return this.global.document.createElement('template');
53 | }
54 | createMutationObserver(callback: (changes: MutationRecord[], instance: MutationObserver) => void): MutationObserver {
55 | return new ((this.global.window).MutationObserver)(callback);
56 | }
57 | createCustomEvent(eventType: string, options?: Object): CustomEvent {
58 | return new this.global.CustomEvent(eventType, options);
59 | }
60 | dispatchEvent(evt: Event): void {
61 | this.global.window.dispatchEvent(evt);
62 | }
63 | getComputedStyle(element: Element): CSSStyleDeclaration {
64 | return this.global.window.getComputedStyle(element);
65 | }
66 | getElementById(id: string): Element {
67 | return this.global.document.getElementById(id);
68 | }
69 | querySelector(query: string): E | null {
70 | return this.global.document.querySelector(query);
71 | }
72 | querySelectorAll(query: string): NodeListOf {
73 | return this.global.document.querySelectorAll(query);
74 | }
75 | nextElementSibling(element: Element): Element {
76 | return element.nextElementSibling;
77 | }
78 | createTemplateFromMarkup(markup: string): HTMLTemplateElement {
79 | let parser = this.global.document.createElement('div');
80 | parser.innerHTML = markup;
81 |
82 | let temp = parser.firstElementChild;
83 | if (!temp || temp.nodeName !== 'TEMPLATE') {
84 | throw new Error('Template markup must be wrapped in a element e.g. ');
85 | }
86 | return temp;
87 | }
88 |
89 | injectStyles(styles: string, destination?: Element, prepend?: boolean): Node {
90 | let node = this.global.document.createElement('style');
91 | node.innerHTML = styles;
92 | node.type = 'text/css';
93 |
94 | destination = destination || this.global.document.head;
95 |
96 | if (prepend && destination.childNodes.length > 0) {
97 | destination.insertBefore(node, destination.childNodes[0]);
98 | } else {
99 | destination.appendChild(node);
100 | }
101 | return node;
102 | }
103 |
104 | adoptNode(node: Node): Node {
105 | return this.global.document.adoptNode(node);
106 | }
107 |
108 | appendNode(newNode: Node, parentNode?: Node): void {
109 | (parentNode || this.global.document.body).appendChild(newNode);
110 | }
111 |
112 | replaceNode(newNode: Node, node: Node, parentNode?: Node): void {
113 | if (node.parentNode) {
114 | node.parentNode.replaceChild(newNode, node);
115 | } else {
116 | parentNode.replaceChild(newNode, node);
117 | }
118 | }
119 |
120 | removeNode(node: Node, parentNode?: Node): void {
121 | if (node.parentNode) {
122 | node.parentNode.removeChild(node);
123 | }
124 | else {
125 | parentNode.removeChild(node);
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/nodejs-feature.ts:
--------------------------------------------------------------------------------
1 | import { IFeature } from './feature';
2 | import { IGlobal } from './global';
3 |
4 | export class NodeJsFeature implements IFeature {
5 | constructor(private global: IGlobal) {
6 | this.shadowDOM = (this.global.window).HTMLElement.prototype.attachShadow != undefined;
7 | this.scopedCSS = 'scoped' in this.global.document.createElement('style');
8 | this.htmlTemplateElement = true;
9 | this.mutationObserver = true; // partial
10 | }
11 |
12 | shadowDOM: boolean;
13 | scopedCSS: boolean;
14 | htmlTemplateElement: boolean;
15 | mutationObserver: boolean;
16 | }
17 |
--------------------------------------------------------------------------------
/src/nodejs-global.ts:
--------------------------------------------------------------------------------
1 | declare namespace NodeJS {
2 | export interface Global {
3 | window: typeof window;
4 | self: typeof window;
5 | document: typeof Window.prototype.document;
6 | Element: typeof Element;
7 | NodeList: typeof NodeList;
8 | SVGElement: typeof SVGElement;
9 | HTMLElement: typeof HTMLElement;
10 | requestAnimationFrame: typeof requestAnimationFrame;
11 | location: typeof location;
12 | history: typeof history;
13 | System: {
14 | import(moduleId: string): Promise;
15 | };
16 | PAL: {
17 | DOM: any;
18 | PLATFORM: any;
19 | FEATURE: any;
20 | };
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/nodejs-pal-builder.ts:
--------------------------------------------------------------------------------
1 | import { initializePAL } from 'aurelia-pal';
2 | import { IPlatform } from './platform';
3 | import { IGlobal } from './global';
4 | import { IDom } from './dom';
5 | import { IFeature } from './feature';
6 | import { NodeJsPlatform } from './nodejs-platform';
7 | import { NodeJsFeature } from './nodejs-feature';
8 | import { NodeJsDom } from './nodejs-dom';
9 | import { JSDOM } from 'jsdom';
10 |
11 | export function buildPal(): { global: IGlobal, platform: IPlatform, dom: IDom, feature: IFeature } {
12 | // https://github.com/jsdom/jsdom/issues/2304
13 | // set url to enable global var localStorage and sessionStorage
14 | var jsdom = new JSDOM(undefined, {url: "http://localhost/"});
15 | var global: IGlobal = jsdom.window;
16 |
17 | ensurePerformance(global.window);
18 |
19 | var platform = new NodeJsPlatform(global, jsdom);
20 | var dom = new NodeJsDom(global);
21 | var feature = new NodeJsFeature(global);
22 |
23 | return {
24 | global: global,
25 | platform: platform,
26 | dom: dom,
27 | feature: feature
28 | };
29 | }
30 |
31 | let intersectSetter = function (proto, propertyName: string, intersect: Function) {
32 | let old = Object.getOwnPropertyDescriptor(proto, propertyName);
33 | let oldSet = old.set;
34 | let newSet = function set(V) {
35 | oldSet.call(this, V);
36 | intersect(this);
37 | };
38 | Object.defineProperty(proto, propertyName, {
39 | set: newSet,
40 | get: old.get,
41 | configurable: old.configurable,
42 | enumerable: old.enumerable
43 | });
44 | };
45 |
46 | let intersectMethod = function (proto, methodName: string, intersect: Function) {
47 | let orig = proto[methodName];
48 | proto[methodName] = function (...args) {
49 | var ret = orig.apply(this, args);
50 | intersect(this);
51 | return ret;
52 | };
53 | };
54 |
55 | export function ensurePerformance(window) {
56 | const _entries = [];
57 | const _marksIndex = {};
58 |
59 | function _filterEntries(key, value) {
60 | var i = 0, n = _entries.length, result = [];
61 | for (; i < n; i++) {
62 | if (_entries[i][key] == value) {
63 | result.push(_entries[i]);
64 | }
65 | }
66 | return result;
67 | }
68 |
69 | function _clearEntries(type, name) {
70 | var i = _entries.length, entry;
71 | while (i--) {
72 | entry = _entries[i];
73 | if (entry.entryType == type && (name === void 0 || entry.name == name)) {
74 | _entries.splice(i, 1);
75 | }
76 | }
77 | };
78 |
79 | if (window.performance === undefined) {
80 | window.performance = {};
81 | }
82 |
83 | if (window.performance.now === undefined) {
84 | let nowOffset = Date.now();
85 |
86 | window.performance.now = function now() {
87 | return Date.now() - nowOffset;
88 | };
89 | }
90 |
91 | if (!window.performance.mark) {
92 | window.performance.mark = window.performance.webkitMark || function (name) {
93 | const mark = {
94 | name,
95 | entryType: "mark",
96 | startTime: window.performance.now(),
97 | duration: 0
98 | };
99 |
100 | _entries.push(mark);
101 | _marksIndex[name] = mark;
102 | };
103 | }
104 |
105 |
106 | if (!window.performance.measure) {
107 | window.performance.measure = window.performance.webkitMeasure || function (name, startMark, endMark) {
108 | startMark = _marksIndex[startMark].startTime;
109 | endMark = _marksIndex[endMark].startTime;
110 |
111 | _entries.push({
112 | name,
113 | entryType: "measure",
114 | startTime: startMark,
115 | duration: endMark - startMark
116 | });
117 | };
118 | }
119 |
120 |
121 | if (!window.performance.getEntriesByType) {
122 | window.performance.getEntriesByType = window.performance.webkitGetEntriesByType || function (type) {
123 | return _filterEntries("entryType", type);
124 | };
125 | }
126 |
127 |
128 | if (!window.performance.getEntriesByName) {
129 | window.performance.getEntriesByName = window.performance.webkitGetEntriesByName || function (name) {
130 | return _filterEntries("name", name);
131 | };
132 | }
133 |
134 |
135 | if (!window.performance.clearMarks) {
136 | window.performance.clearMarks = window.performance.webkitClearMarks || function (name) {
137 | _clearEntries("mark", name);
138 | };
139 | }
140 |
141 |
142 | if (!window.performance.clearMeasures) {
143 | window.performance.clearMeasures = window.performance.webkitClearMeasures || function (name) {
144 | _clearEntries("measure", name);
145 | };
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/nodejs-platform.ts:
--------------------------------------------------------------------------------
1 | import { IPlatform } from './platform';
2 | import { IPerformance } from './performance';
3 | import { IGlobal } from './global';
4 | import { JSDOM } from 'jsdom';
5 |
6 | declare module './global' {
7 | interface IGlobal {
8 | performance: any;
9 | location: any;
10 | history: any;
11 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
12 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
13 | }
14 | }
15 |
16 | export class NodeJsPlatform implements IPlatform {
17 |
18 | constructor(public global: IGlobal, public jsdom: JSDOM) {
19 | this.performance = this.global.performance;
20 | this.location = this.global.location;
21 | this.history = this.global.history;
22 | this.XMLHttpRequest = this.global.XMLHttpRequest;
23 | }
24 |
25 | /**
26 | * A function wich does nothing.
27 | */
28 | noop: Function = () => { };
29 | /**
30 | * The runtime's location API.
31 | */
32 | location: Object;
33 | /**
34 | * The runtime's history API.
35 | */
36 | history: Object;
37 | /**
38 | * The runtime's performance API
39 | */
40 | performance: IPerformance;
41 | /**
42 | * Registers a function to call when the system is ready to update (repaint) the display.
43 | * @param callback The function to call.
44 | * @return A long integer value, the request id, that uniquely identifies the entry in the callback list.
45 | */
46 | requestAnimationFrame(callback: (animationFrameStart: number) => void): number {
47 | return setImmediate(() => callback(Date.now())) as any;
48 | }
49 |
50 | /**
51 | * Iterate all modules loaded by the script loader.
52 | * @param callback A callback that will receive each module id along with the module object. Return true to end enumeration.
53 | */
54 | eachModule(callback: (key: string, value: Object) => boolean): void {
55 | //TODO: What is this?
56 | }
57 | /**
58 | * Add a global event listener.
59 | * @param eventName A string representing the event type to listen for.
60 | * @param callback The function that receives a notification when an event of the specified type occurs.
61 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
62 | */
63 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void {
64 | this.global.addEventListener(eventName, callback, capture);
65 | }
66 | /**
67 | * Remove a global event listener.
68 | * @param eventName A string representing the event type to listen for.
69 | * @param callback The function to remove from the event.
70 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
71 | */
72 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void {
73 | this.global.removeEventListener(eventName, callback, capture);
74 | }
75 |
76 | /**
77 | * The runtime's XMLHttpRequest API.
78 | */
79 | XMLHttpRequest: typeof XMLHttpRequest;
80 | }
81 |
--------------------------------------------------------------------------------
/src/observer.ts:
--------------------------------------------------------------------------------
1 | export interface IObserver {
2 | target: Node;
3 | options?: MutationObserverInit;
4 | callback: (mutations: MutationRecord[]) => void;
5 | }
6 |
--------------------------------------------------------------------------------
/src/performance.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The runtime's performance API.
3 | */
4 | export interface IPerformance {
5 | /**
6 | * Gets a DOMHighResTimeStamp.
7 | * @return The timestamp, measured in milliseconds, accurate to one thousandth of a millisecond.
8 | */
9 | now(): number;
10 |
11 | /**
12 | * Removes the given mark from the browser's performance entry buffer.
13 | *
14 | * @param {string} [markName] A DOMString representing the name of the timestamp. If this argument is omitted, all performance entries with an entry type of "mark" will be removed.
15 | * @memberof IPerformance
16 | */
17 | clearMarks(markName?: string): void;
18 |
19 | /**
20 | * Removes the given measure from the browser's performance entry buffer.
21 | *
22 | * @param {string} [measureName] A DOMString representing the name of the timestamp. If this argument is omitted, all performance entries with an entry type of "measure" will be removed.
23 | * @memberof IPerformance
24 | */
25 | clearMeasures(measureName?: string): void;
26 |
27 | /**
28 | * Returns a list of PerformanceEntry objects based on the given name and entry type.
29 | *
30 | * @param {string} name The name of the entry to retrieve
31 | * @param {string} [entryType] The type of entry to retrieve such as "mark". The valid entry types are listed in PerformanceEntry.entryType.
32 | * @returns {*}
33 | * @memberof IPerformance
34 | */
35 | getEntriesByName(name: string, entryType?: string): any;
36 |
37 | /**
38 | * Returns a list of PerformanceEntry objects of the given entry type.
39 | *
40 | * @param {string} entryType The type of entry to retrieve such as "mark". The valid entry types are listed in PerformanceEntry.entryType.
41 | * @returns {*}
42 | * @memberof IPerformance
43 | */
44 | getEntriesByType(entryType: string): any;
45 |
46 | /**
47 | * Creates a timestamp in the browser's performance entry buffer with the given name.
48 | *
49 | * @param {string} markName a DOMString representing the name of the mark
50 | * @memberof IPerformance
51 | */
52 | mark(markName: string): void;
53 |
54 | /**
55 | * Creates a named timestamp in the browser's performance entry buffer between two specified marks (known as the start mark and end mark, respectively).
56 | *
57 | * @param {string} measureName a DOMString representing the name of the measure.
58 | * @param {string} [startMarkName] A DOMString representing the name of the measure's starting mark. May also be the name of a PerformanceTiming property.
59 | * @param {string} [endMarkName] A DOMString representing the name of the measure's ending mark. May also be the name of a PerformanceTiming property.
60 | * @memberof IPerformance
61 | */
62 | measure(measureName: string, startMarkName?: string, endMarkName?: string): void;
63 | }
64 |
--------------------------------------------------------------------------------
/src/platform.ts:
--------------------------------------------------------------------------------
1 | import { IPerformance } from './performance';
2 |
3 | /**
4 | * Represents the core APIs of the runtime environment.
5 | */
6 | export interface IPlatform {
7 | /**
8 | * The runtime environment's global.
9 | */
10 | global: any;
11 | /**
12 | * A function wich does nothing.
13 | */
14 | noop: Function;
15 | /**
16 | * The runtime's location API.
17 | */
18 | location: Object;
19 | /**
20 | * The runtime's history API.
21 | */
22 | history: Object;
23 | /**
24 | * The runtime's performance API
25 | */
26 | performance: IPerformance;
27 | /**
28 | * Registers a function to call when the system is ready to update (repaint) the display.
29 | * @param callback The function to call.
30 | * @return A long integer value, the request id, that uniquely identifies the entry in the callback list.
31 | */
32 | requestAnimationFrame(callback: (animationFrameStart: number) => void): number;
33 | /**
34 | * Iterate all modules loaded by the script loader.
35 | * @param callback A callback that will receive each module id along with the module object. Return true to end enumeration.
36 | */
37 | eachModule(callback: (key: string, value: Object) => boolean): void;
38 | /**
39 | * Add a global event listener.
40 | * @param eventName A string representing the event type to listen for.
41 | * @param callback The function that receives a notification when an event of the specified type occurs.
42 | * @param capture If true, useCapture indicates that the user wishes to initiate capture.
43 | */
44 | addEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
45 | /**
46 | * Remove a global event listener.
47 | * @param eventName A string representing the event type to listen for.
48 | * @param callback The function to remove from the event.
49 | * @param capture Specifies whether the listener to be removed was registered as a capturing listener or not.
50 | */
51 | removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject, capture?: boolean): void;
52 | /**
53 | * The runtime's XMLHttpRequest API.
54 | */
55 | XMLHttpRequest: typeof XMLHttpRequest;
56 | }
57 |
--------------------------------------------------------------------------------
/test/nodejs-dom.spec.ts:
--------------------------------------------------------------------------------
1 | import { initialize } from '../src/index';
2 | import { DOM, PLATFORM } from 'aurelia-pal';
3 | import { JSDOM } from 'jsdom';
4 |
5 | initialize();
6 |
7 | describe('NodeJs Dom', () => {
8 | it('should create a template from valid markup', () => {
9 | expect(() => DOM.createTemplateFromMarkup('this is valid!')).toBeDefined();
10 | });
11 |
12 | it('should throw an error when creating a template from text-only markup', () => {
13 | expect(() => DOM.createTemplateFromMarkup('throw an error!')).toThrow();
14 | });
15 |
16 | it('should throw an error when creating a template from markup where is not the root element', () => {
17 | expect(() => DOM.createTemplateFromMarkup('throw an error!
')).toThrow();
18 | });
19 |
20 | it('createElement is defined and creates valid element', () => {
21 | expect(DOM.createElement).toBeDefined();
22 | });
23 |
24 | it('createElement creates valid element', () => {
25 | let elmt = DOM.createElement("div");
26 | expect(elmt).not.toBeNull();
27 | expect(elmt.tagName).toBe("DIV");
28 | });
29 |
30 | it('createTextNode is defined', () => {
31 | expect(DOM.createTextNode).toBeDefined();
32 | });
33 |
34 | it('createTextNode creates valid text node', () => {
35 | let elmt = DOM.createTextNode("choo-choo!");
36 |
37 | expect(elmt).not.toBeNull();
38 | expect(elmt.textContent).toBe("choo-choo!");
39 | });
40 |
41 | it('adoptNode is defined', () => {
42 | expect(DOM.adoptNode).toBeDefined();
43 | });
44 |
45 | it('adoptNode returns adopted', () => {
46 | let external = new JSDOM(undefined, {}).window.document.createElement("DIV");
47 | let adopted = DOM.adoptNode(external);
48 |
49 | expect(adopted.nodeName).toBe("DIV");
50 | });
51 |
52 | it('appendNode is defined and appends node to other', () => {
53 | expect(DOM.appendNode).toBeDefined();
54 | });
55 |
56 | it('activeElement is defined', () => {
57 | expect(DOM.activeElement).toBeDefined();
58 | });
59 |
60 | it('createAttribute is defined', () => {
61 | expect(DOM.createAttribute).toBeDefined();
62 | });
63 |
64 | it('createMutationObserver is defined', () => {
65 | expect(DOM.createMutationObserver).toBeDefined();
66 | });
67 |
68 | it('createDocumentFragment is defined', () => {
69 | expect(DOM.createDocumentFragment).toBeDefined();
70 | });
71 |
72 | it('createTemplateFromMarkup is defined', () => {
73 | expect(DOM.createTemplateFromMarkup).toBeDefined();
74 | });
75 |
76 | it('createTemplateFromMarkup is defined', () => {
77 | expect(DOM.createMutationObserver).toBeDefined();
78 | });
79 |
80 | it('addEventListener is defined', () => {
81 | expect(DOM.addEventListener).toBeDefined();
82 | });
83 |
84 | it('addEventListener recieves custom events', () => {
85 | let elmt = DOM.createElement("div");
86 | var wasCalled = false;
87 |
88 | let event = DOM.createCustomEvent("Foo", { bubbles: true, cancelable: false, detail: {} });
89 |
90 | elmt.addEventListener("Foo", () => { wasCalled = true; }, true);
91 | elmt.dispatchEvent(event);
92 |
93 | expect(wasCalled).toBeTruthy();
94 | });
95 |
96 | it('removeEventListener is defined', () => {
97 | expect(DOM.removeEventListener).toBeDefined();
98 | });
99 |
100 | it('dispatchEvent is defined', () => {
101 | expect(DOM.dispatchEvent).toBeDefined();
102 | });
103 |
104 | it('NodeList is defined', () => {
105 | expect(PLATFORM.global.NodeList).toBeDefined();
106 | });
107 | });
108 |
--------------------------------------------------------------------------------
/test/nodejs-pal-builder.spec.ts:
--------------------------------------------------------------------------------
1 | import { buildPal } from '../src/nodejs-pal-builder';
2 |
3 | describe("pal-builder", () => {
4 | let pal;
5 |
6 | beforeEach(() => {
7 | pal = buildPal();
8 | });
9 |
10 | it('should be defined', () => {
11 | expect(pal.global).toBeDefined();
12 | expect(pal.platform).toBeDefined();
13 | expect(pal.dom).toBeDefined();
14 | expect(pal.feature).toBeDefined();
15 | });
16 |
17 | it('should ensure performance', () => {
18 | expect(pal.global.performance.now()).toBeGreaterThan(-1);
19 | expect(pal.global.performance.measure).toBeDefined();
20 | expect(pal.global.performance.mark).toBeDefined();
21 | expect(pal.global.performance.getEntriesByType).toBeDefined();
22 | expect(pal.global.performance.getEntriesByName).toBeDefined();
23 | expect(pal.global.performance.clearMeasures).toBeDefined();
24 | expect(pal.global.performance.clearMarks).toBeDefined();
25 | });
26 |
27 | it('should enusre mutation observer is loaded', () => {
28 | expect(pal.dom.createMutationObserver).toBeDefined();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/nodejs-platform.spec.ts:
--------------------------------------------------------------------------------
1 | import { initialize } from '../src/index';
2 | import { PLATFORM } from 'aurelia-pal';
3 |
4 | initialize();
5 |
6 | describe('NodeJs Platform', () => {
7 | it('addEventListener is defined', () => {
8 | expect(PLATFORM.addEventListener).toBeDefined();
9 | });
10 | it('removeEventListener is defined', () => {
11 | expect(PLATFORM.removeEventListener).toBeDefined();
12 | });
13 | it('global is defined', () => {
14 | expect(PLATFORM.global).toBeDefined();
15 | });
16 | it('history is defined', () => {
17 | expect(PLATFORM.history).toBeDefined();
18 | });
19 | it('location is defined', () => {
20 | expect(PLATFORM.location).toBeDefined();
21 | });
22 | it('noop is defined', () => {
23 | expect(PLATFORM.noop).toBeDefined();
24 | });
25 | it('performance is defined', () => {
26 | expect(PLATFORM.performance).toBeDefined();
27 | });
28 | it('XMLHttpRequest is defined', () => {
29 | expect(PLATFORM.XMLHttpRequest).toBeDefined();
30 | });
31 | it('requestAnimationFrame is defined', () => {
32 | expect(PLATFORM.requestAnimationFrame).toBeDefined();
33 | });
34 | it('eachModule is defined', () => {
35 | expect(PLATFORM.eachModule).toBeDefined();
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/test/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "test",
3 | "spec_files": [
4 | "**/*[sS]pec.ts"
5 | ],
6 | "helpers": [
7 | "helpers/**/*.ts"
8 | ],
9 | "stopSpecOnExpectationFailure": false,
10 | "random": false
11 | }
12 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "exclude": [
7 | "./test"
8 | ]
9 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "experimentalDecorators": true,
6 | "emitDecoratorMetadata": false,
7 | "moduleResolution": "node",
8 | "stripInternal": true,
9 | "preserveConstEnums": true,
10 | "removeComments": true,
11 | "lib": ["es2018"]
12 | },
13 | "exclude": [
14 | "node_modules"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/tsfmt.json:
--------------------------------------------------------------------------------
1 | {
2 | "convertTabsToSpaces": true,
3 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": true
4 | }
5 |
--------------------------------------------------------------------------------