Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 1a9c7d3

Browse files
committed
customElements -> components
1 parent 374b24f commit 1a9c7d3

8 files changed

+84
-81
lines changed

README.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ You can take the same ideas (and standards), apply them directly server side, to
2424
#### Define a component
2525

2626
```javascript
27-
var customElements = require("server-components");
27+
var components = require("server-components");
2828

2929
// Define a new class that extends a native HTML Element
30-
class NewElement extends customElements.HTMLElement {
30+
class NewElement extends components.HTMLElement {
3131
// When the element is created during DOM parsing, you can transform the HTML inside it.
3232
// This can be configurable too, either by setting attributes or adding HTML content
3333
// inside it or elsewhere in the page it can interact with. Elements can fire events
@@ -39,21 +39,21 @@ class NewElement extends customElements.HTMLElement {
3939
}
4040

4141
// Register the element with an element name
42-
customElements.define("my-new-element", NewElement);
42+
components.define("my-new-element", NewElement);
4343
```
4444

4545
For examples of more complex component definitions, take a look at the [example components](https://github.com/pimterry/server-components/blob/master/component-examples.md)
4646

4747
#### Use your components
4848

4949
```javascript
50-
var customElements = require("server-components");
50+
var components = require("server-components");
5151

5252
// Render the HTML, and receive a promise for the resulting HTML string.
5353
// The result is a promise because elements can render asynchronously, by returning
5454
// promises from their callbacks. This allows elements to render content from
5555
// external web services, your database, or anything else you can imagine.
56-
customElements.renderPage(`
56+
components.renderPage(`
5757
<html>
5858
<head></head>
5959
<body>
@@ -83,15 +83,15 @@ There aren't many published sharable components to drop in quite yet, as it's st
8383

8484
### Top-level API
8585

86-
#### `customElements.HTMLElement`
86+
#### `components.HTMLElement`
8787

8888
Creates a returns a new custom HTML element prototype, extending the HTMLElement prototype.
8989

9090
Note that this does *not* register the element. To do that, call `components.registerElement` with an element name, and options (typically including the prototype returned here as your 'prototype' value).
9191

9292
This is broadly equivalent to `Object.create(HTMLElement.prototype)` in browser land, and exactly equivalent here to `Object.create(components.dom.HTMLElement.prototype)`. You can call that yourself instead if you like, but it's a bit of a mouthful.
9393

94-
#### `customElements.define(componentName, Constructor)`
94+
#### `components.define(componentName, Constructor)`
9595

9696
Registers an element, so that it will be used when the given element name is found during parsing.
9797

@@ -103,25 +103,25 @@ This returns the constructor for the new element, so you can construct and inser
103103

104104
This is broadly equivalent to `document.registerElement` in browser land.
105105

106-
#### `customElements.renderPage(html)`
106+
#### `components.renderPage(html)`
107107

108108
Takes an HTML string for a full page, and returns a promise for the HTML string of the rendered result. Server Components parses the HTML, and for each registered element within calls its various callbacks (see the Component API) below as it does so.
109109

110110
Unrecognized elements are left unchanged. When calling custom element callbacks any returned promises are collected, and this call will not return until all these promises have completed. If any promises are rejected, this renderPage call will be rejected too.
111111

112112
To support the full DOM Document API, this method requires that you are rendering a full page (including `<html>`, `<head>` and `<body>` tags). If you don't pass in content wrapped in those tags then they'll be automatically added, ensuring your resulting HTML has a full valid page structure. If that's not what you want, take a look at `renderFragment` below.
113113

114-
#### `customElements.renderFragment(html)`
114+
#### `components.renderFragment(html)`
115115

116116
Takes an HTML string for part of a page, and returns a promise for the HTML string of the rendered result. Server Components parses the HTML, and for each registered element within calls its various callbacks (see the Component API) below as it does so.
117117

118118
Unrecognized elements are left unchanged. When calling custom element callbacks any returned promises are collected, and this call will not return until all these promises have completed. If any promises are rejected, this renderFragment call will be rejected too.
119119

120120
This method renders the content as a [Document Fragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment), a sub-part of a full document. This means if you there are any `<html>`, `<head>` or `<body>` tags in your input, they'll be stripped, as they're not legal within a fragment of a document. Note that this means the provided `document` object in your components will actually be a `DocumentFragment`, not a true `Document` object (although in most cases you can merrily ignore this). If you want to render a full page, take a look at `renderPage` above.
121121

122-
#### `customElements.dom`
122+
#### `components.dom`
123123

124-
The DOM object (customElements.dom) exposes traditional DOM objects (normally globally available in browsers) such as the CustomEvent and various HTMLElement classes, typically use inside your component implementations.
124+
The DOM object (components.dom) exposes traditional DOM objects (normally globally available in browsers) such as the CustomEvent and various HTMLElement classes, typically use inside your component implementations.
125125

126126
This is (very) broadly equivalent to `window` in browser land.
127127

src/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ exports.get = function (name) {
3333
exports.whenDefined = function (name) {
3434
return CustomElementRegistry.instance().whenDefined(name);
3535
};
36+
exports.reset = function (name) {
37+
return CustomElementRegistry.instance().reset();
38+
};
3639

3740

3841
const _upgradedProp = '__$CE_upgraded';

test/asynchrony-test.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
"use strict";
22
var expect = require('chai').expect;
33

4-
var customElements = require("../src/index.js");
4+
var components = require("../src/index.js");
55

66
describe("An asynchronous element", () => {
77
beforeEach(() => {
8-
customElements.customElements.reset();
8+
components.reset();
99
});
1010

1111
it("blocks rendering until they complete", () => {
12-
class SlowElement extends customElements.HTMLElement {
12+
class SlowElement extends components.HTMLElement {
1313
connectedCallback() {
1414
return new Promise((resolve, reject) => {
1515
setTimeout(() => {
@@ -19,37 +19,37 @@ describe("An asynchronous element", () => {
1919
});
2020
}
2121
}
22-
customElements.define("slow-element", SlowElement);
22+
components.define("slow-element", SlowElement);
2323

24-
return customElements.renderFragment("<slow-element></slow-element>").then((output) => {
24+
return components.renderFragment("<slow-element></slow-element>").then((output) => {
2525
expect(output).to.equal("<slow-element>loaded!</slow-element>");
2626
});
2727
});
2828

2929
it("throw an async error if a component fails to render synchronously", () => {
30-
class FailingElement extends customElements.HTMLElement {
30+
class FailingElement extends components.HTMLElement {
3131
connectedCallback() {
3232
throw new Error();
3333
}
3434
}
35-
customElements.define("failing-element", FailingElement);
35+
components.define("failing-element", FailingElement);
3636

37-
return customElements.renderFragment(
37+
return components.renderFragment(
3838
"<failing-element></failing-element>"
3939
).then((output) => {
4040
throw new Error("Should not successfully render");
4141
}).catch(() => { /* All good. */ });
4242
});
4343

4444
it("throw an async error if a component fails to render asynchronously", () => {
45-
class FailingElement extends customElements.HTMLElement {
45+
class FailingElement extends components.HTMLElement {
4646
connectedCallback() {
4747
return Promise.reject(new Error());
4848
}
4949
}
50-
customElements.define("failing-element", FailingElement);
50+
components.define("failing-element", FailingElement);
5151

52-
return customElements.renderFragment(
52+
return components.renderFragment(
5353
"<failing-element></failing-element>"
5454
).then((output) => {
5555
throw new Error("Should not successfully render");

test/basics-test.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,88 @@
11
"use strict";
22
var expect = require('chai').expect;
33

4-
var customElements = require("../src/index.js");
4+
var components = require("../src/index.js");
55

66
describe("Basic component functionality", () => {
77
it("does nothing with vanilla HTML", () => {
88
var input = "<div></div>";
99

10-
return customElements.renderFragment(input).then((output) => {
10+
return components.renderFragment(input).then((output) => {
1111
expect(output).to.equal(input);
1212
});
1313
});
1414

15-
it("replaces customElements with their rendered result", () => {
16-
class NewElement extends customElements.HTMLElement {
15+
it("replaces components with their rendered result", () => {
16+
class NewElement extends components.HTMLElement {
1717
connectedCallback() {
1818
this.textContent = "hi there";
1919
}
2020
}
21-
customElements.define("my-element", NewElement);
21+
components.define("my-element", NewElement);
2222

23-
return customElements.renderFragment("<my-element></my-element>").then((output) => {
23+
return components.renderFragment("<my-element></my-element>").then((output) => {
2424
expect(output).to.equal("<my-element>hi there</my-element>");
2525
});
2626
});
2727

2828
it("can wrap existing content", () => {
29-
class PrefixedElement extends customElements.HTMLElement {
29+
class PrefixedElement extends components.HTMLElement {
3030
connectedCallback() {
3131
this.innerHTML = "prefix:" + this.innerHTML;
3232
}
3333
}
34-
customElements.define("prefixed-element", PrefixedElement);
34+
components.define("prefixed-element", PrefixedElement);
3535

36-
return customElements.renderFragment(
36+
return components.renderFragment(
3737
"<prefixed-element>existing-content</prefixed-element>"
3838
).then((output) => expect(output).to.equal(
3939
"<prefixed-element>prefix:existing-content</prefixed-element>"
4040
));
4141
});
4242

4343
it("allows attribute access", () => {
44-
class BadgeElement extends customElements.HTMLElement {
44+
class BadgeElement extends components.HTMLElement {
4545
connectedCallback() {
4646
var name = this.getAttribute("name");
4747
this.innerHTML = "My name is: <div class='name'>" + name + "</div>";
4848
}
4949
}
50-
customElements.define("name-badge", BadgeElement);
50+
components.define("name-badge", BadgeElement);
5151

52-
return customElements.renderFragment(
52+
return components.renderFragment(
5353
'<name-badge name="Tim Perry"></name-badge>'
5454
).then((output) => expect(output).to.equal(
5555
'<name-badge name="Tim Perry">My name is: <div class="name">Tim Perry</div></name-badge>'
5656
));
5757
});
5858

5959
it("can use normal document methods like QuerySelector", () => {
60-
class SelfFindingElement extends customElements.HTMLElement {
60+
class SelfFindingElement extends components.HTMLElement {
6161
connectedCallback(document) {
6262
var hopefullyThis = document.querySelector("self-finding-element");
6363
if (hopefullyThis === this) this.innerHTML = "Found!";
6464
else this.innerHTML = "Not found, found " + hopefullyThis;
6565
}
6666
}
67-
customElements.define("self-finding-element", SelfFindingElement);
67+
components.define("self-finding-element", SelfFindingElement);
6868

69-
return customElements.renderFragment(
69+
return components.renderFragment(
7070
'<self-finding-element></self-finding-element>'
7171
).then((output) => expect(output).to.equal(
7272
'<self-finding-element>Found!</self-finding-element>'
7373
));
7474
});
7575

7676
it("wraps content in valid page content, if rendering a page", () => {
77-
return customElements.renderPage("<empty-div></empty-div>").then((output) => {
77+
return components.renderPage("<empty-div></empty-div>").then((output) => {
7878
expect(output).to.equal(
7979
"<html><head></head><body><empty-div></empty-div></body></html>"
8080
);
8181
});
8282
});
8383

8484
it("strips <html>, <head> and <body> tags, if only rendering a fragment", () => {
85-
return customElements.renderFragment("<html><body><empty-div><head></head></empty-div></body></html>").then((output) => {
85+
return components.renderFragment("<html><body><empty-div><head></head></empty-div></body></html>").then((output) => {
8686
expect(output).to.equal(
8787
"<empty-div></empty-div>"
8888
);

test/element-validation-test.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"use strict";
22
var expect = require('chai').expect;
33

4-
var customElements = require("../src/index.js");
4+
var components = require("../src/index.js");
55

66
describe("Custom element validation", () => {
77
it("requires a non-empty name", () => {
88
class InvalidElement {}
99
expect(() => {
10-
customElements.define("", InvalidElement);
10+
components.define("", InvalidElement);
1111
}).to.throw(
1212
/The element name '' is not valid./
1313
);
@@ -16,7 +16,7 @@ describe("Custom element validation", () => {
1616
it("requires a hyphen in the element name", () => {
1717
class InvalidElement {}
1818
expect(() => {
19-
customElements.define("invalidname", InvalidElement);
19+
components.define("invalidname", InvalidElement);
2020
}).to.throw(
2121
/The element name 'invalidname' is not valid./
2222
);
@@ -25,7 +25,7 @@ describe("Custom element validation", () => {
2525
it("doesn't allow elements to start with a hyphen", () => {
2626
class InvalidElement {}
2727
expect(() => {
28-
customElements.define("-invalid-name", InvalidElement);
28+
components.define("-invalid-name", InvalidElement);
2929
}).to.throw(
3030
/The element name '-invalid-name' is not valid./
3131
);
@@ -34,7 +34,7 @@ describe("Custom element validation", () => {
3434
it("requires element names to be lower case", () => {
3535
class InvalidElement {}
3636
expect(() => {
37-
customElements.define("INVALID-NAME", InvalidElement);
37+
components.define("INVALID-NAME", InvalidElement);
3838
}).to.throw(
3939
/The element name 'INVALID-NAME' is not valid./
4040
);

test/example-components.js

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
"use strict";
22
var expect = require('chai').expect;
3-
var customElements = require("../src/index.js");
3+
var components = require("../src/index.js");
44

55
var linkify = require("linkifyjs/element");
66

77
describe("An example component:", () => {
88
beforeEach(() => {
9-
customElements.customElements.reset();
9+
components.reset();
1010
});
1111

1212
describe("using static rendering", () => {
1313
beforeEach(() => {
14-
class StaticElement extends customElements.HTMLElement {
14+
class StaticElement extends components.HTMLElement {
1515
connectedCallback() {
1616
this.innerHTML = "Hi there";
1717
}
1818
}
19-
customElements.define("my-greeting", StaticElement);
19+
components.define("my-greeting", StaticElement);
2020
});
2121

2222
it("replaces its content with the given text", () => {
23-
return customElements.renderFragment("<my-greeting></my-greeting>").then((output) => {
23+
return components.renderFragment("<my-greeting></my-greeting>").then((output) => {
2424
expect(output).to.equal("<my-greeting>Hi there</my-greeting>");
2525
});
2626
});
@@ -30,21 +30,21 @@ describe("An example component:", () => {
3030
beforeEach(() => {
3131
var currentCount = 0;
3232

33-
class CounterElement extends customElements.HTMLElement {
33+
class CounterElement extends components.HTMLElement {
3434
connectedCallback() {
3535
currentCount += 1;
3636
this.innerHTML = "There have been " + currentCount + " visitors.";
3737
}
3838
}
39-
customElements.define("visitor-counter", CounterElement);
39+
components.define("visitor-counter", CounterElement);
4040
});
4141

4242
it("dynamically changes its content", () => {
43-
customElements.renderFragment("<visitor-counter></visitor-counter>");
44-
customElements.renderFragment("<visitor-counter></visitor-counter>");
45-
customElements.renderFragment("<visitor-counter></visitor-counter>");
43+
components.renderFragment("<visitor-counter></visitor-counter>");
44+
components.renderFragment("<visitor-counter></visitor-counter>");
45+
components.renderFragment("<visitor-counter></visitor-counter>");
4646

47-
return customElements.renderFragment("<visitor-counter></visitor-counter>").then((output) => {
47+
return components.renderFragment("<visitor-counter></visitor-counter>").then((output) => {
4848
expect(output).to.equal(
4949
"<visitor-counter>There have been 4 visitors.</visitor-counter>"
5050
);
@@ -54,17 +54,17 @@ describe("An example component:", () => {
5454

5555
describe("parameterised by HTML content", () => {
5656
beforeEach(() => {
57-
class LinkifyElement extends customElements.HTMLElement {
57+
class LinkifyElement extends components.HTMLElement {
5858
connectedCallback(document) {
5959
// Delegate the whole thing to a real front-end library!
6060
linkify(this, { target: () => null, linkClass: "autolinked" }, document);
6161
}
6262
}
63-
customElements.define("linkify-urls", LinkifyElement);
63+
components.define("linkify-urls", LinkifyElement);
6464
});
6565

6666
it("should be able to parse and manipulate it's content", () => {
67-
return customElements.renderFragment(
67+
return components.renderFragment(
6868
"<linkify-urls>Have you heard of www.facebook.com?</linkify-urls>"
6969
).then((output) => expect(output).to.equal(
7070
'<linkify-urls>Have you heard of <a href="http://www.facebook.com" class="autolinked">www.facebook.com</a>?</linkify-urls>'

0 commit comments

Comments
 (0)