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

Commit 3f7c02e

Browse files
committed
Set define as the top level
1 parent 71829e6 commit 3f7c02e

9 files changed

+104
-89
lines changed

README.md

Lines changed: 11 additions & 11 deletions
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 components = require("server-components");
27+
var customElements = require("server-components");
2828

2929
// Define a new class that extends a native HTML Element
30-
class NewElement extends components.HTMLElement {
30+
class NewElement extends customElements.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 components.HTMLElement {
3939
}
4040

4141
// Register the element with an element name
42-
components.customElements.define("my-new-element", NewElement);
42+
customElements.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 components = require("server-components");
50+
var customElements = 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-
components.renderPage(`
56+
customElements.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-
#### `components.HTMLElement`
86+
#### `customElements.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-
#### `components.customElements.define(componentName, Constructor)`
94+
#### `customElements.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-
#### `components.renderPage(html)`
106+
#### `customElements.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-
#### `components.renderFragment(html)`
114+
#### `customElements.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-
#### `components.dom`
122+
#### `customElements.dom`
123123

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.
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.
125125

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

component-examples.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ With the web component below, rendering `<my-greeting></my-greeting>` will resul
1414
`<my-greeting>Hi there</my-greeting>`.
1515

1616
```javascript
17-
var components = require("server-components");
17+
var customElements = require("server-components");
1818

19-
class StaticElement extends components.HTMLElement {
19+
class StaticElement extends customElements.HTMLElement {
2020
connectedCallback() {
2121
this.innerHTML = "Hi there"
2222
}
2323
}
24-
components.customElements.define("my-greeting", StaticElement);
24+
customElements.define("my-greeting", StaticElement);
2525
```
2626

2727
This is very basic, and toy cases like this aren't immediately useful, but this can be helpful for standard
@@ -40,17 +40,17 @@ example is below: a visitor counter. All the rage in the 90s, with web component
4040
comeback!
4141

4242
```javascript
43-
var components = require("server-components");
43+
var customElements = require("server-components");
4444

4545
var currentCount = 0;
4646

47-
class CounterElement extends components.HTMLElement {
47+
class CounterElement extends customElements.HTMLElement {
4848
connectedCallback() {
4949
currentCount += 1;
5050
this.innerHTML = "There have been " + currentCount + " visitors.";
5151
}
5252
}
53-
components.customElements.define("visitor-counter", CounterElement);
53+
customElements.define("visitor-counter", CounterElement);
5454
```
5555

5656
After a few visitors, this will render `<visitor-counter></visitor-counter>` into something like
@@ -81,16 +81,16 @@ Components can be parameterized in all sorts of ways. One interesting pattern is
8181
For example, you might want a component that wraps HTML, parses all the text within, and replaces URL strings with actual links (using the excellent [Linkify library](https://github.com/SoapBox/linkifyjs), but here in a server side DOM, not a real one):
8282

8383
```javascript
84-
var components = require("server-components");
84+
var customElements = require("server-components");
8585
var linkify = require("linkifyjs/element");
8686

87-
class LinkifyElement extends components.HTMLElement {
87+
class LinkifyElement extends customElements.HTMLElement {
8888
connectedCallback() {
8989
// Delegate the whole thing to a real front-end library!
9090
linkify(this, { target: () => null, linkClass: "autolinked" }, document);
9191
}
9292
}
93-
components.customElements.define("linkify-urls", LinkifyElement);
93+
customElements.define("linkify-urls", LinkifyElement);
9494
```
9595

9696
With this, we can pass HTML into Server Components that looks like

src/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ var CustomElementRegistry = require('./registry');
2020
exports.customElements = CustomElementRegistry.instance();
2121
exports.HTMLElement = CustomElementRegistry.HTMLElement;
2222

23+
24+
/**
25+
* Re-export methods for convenience
26+
*/
27+
exports.define = function (name, constructor, options) {
28+
return CustomElementRegistry.instance().define(name, constructor, options);
29+
};
30+
exports.get = function (name) {
31+
return CustomElementRegistry.instance().get(name);
32+
};
33+
exports.whenDefined = function (name) {
34+
return CustomElementRegistry.instance().whenDefined(name);
35+
};
36+
37+
2338
const _upgradedProp = '__$CE_upgraded';
2439

2540

test/asynchrony-test.js

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

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

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

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

24-
return components.renderFragment("<slow-element></slow-element>").then((output) => {
24+
return customElements.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 components.HTMLElement {
30+
class FailingElement extends customElements.HTMLElement {
3131
connectedCallback() {
3232
throw new Error();
3333
}
3434
}
35-
components.customElements.define("failing-element", FailingElement);
35+
customElements.define("failing-element", FailingElement);
3636

37-
return components.renderFragment(
37+
return customElements.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 components.HTMLElement {
45+
class FailingElement extends customElements.HTMLElement {
4646
connectedCallback() {
4747
return Promise.reject(new Error());
4848
}
4949
}
50-
components.customElements.define("failing-element", FailingElement);
50+
customElements.define("failing-element", FailingElement);
5151

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

test/basics-test.js

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

4-
var components = require("../src/index.js");
4+
var customElements = 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 components.renderFragment(input).then((output) => {
10+
return customElements.renderFragment(input).then((output) => {
1111
expect(output).to.equal(input);
1212
});
1313
});
1414

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

23-
return components.renderFragment("<my-element></my-element>").then((output) => {
23+
return customElements.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 components.HTMLElement {
29+
class PrefixedElement extends customElements.HTMLElement {
3030
connectedCallback() {
3131
this.innerHTML = "prefix:" + this.innerHTML;
3232
}
3333
}
34-
components.customElements.define("prefixed-element", PrefixedElement);
34+
customElements.define("prefixed-element", PrefixedElement);
3535

36-
return components.renderFragment(
36+
return customElements.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 components.HTMLElement {
44+
class BadgeElement extends customElements.HTMLElement {
4545
connectedCallback() {
4646
var name = this.getAttribute("name");
4747
this.innerHTML = "My name is: <div class='name'>" + name + "</div>";
4848
}
4949
}
50-
components.customElements.define("name-badge", BadgeElement);
50+
customElements.define("name-badge", BadgeElement);
5151

52-
return components.renderFragment(
52+
return customElements.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 components.HTMLElement {
60+
class SelfFindingElement extends customElements.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-
components.customElements.define("self-finding-element", SelfFindingElement);
67+
customElements.define("self-finding-element", SelfFindingElement);
6868

69-
return components.renderFragment(
69+
return customElements.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 components.renderPage("<empty-div></empty-div>").then((output) => {
77+
return customElements.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 components.renderFragment("<html><body><empty-div><head></head></empty-div></body></html>").then((output) => {
85+
return customElements.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

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

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

66
describe("Custom element validation", () => {
77
it("requires a non-empty name", () => {
88
class InvalidElement {}
99
expect(() => {
10-
components.customElements.define("", InvalidElement);
10+
customElements.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-
components.customElements.define("invalidname", InvalidElement);
19+
customElements.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-
components.customElements.define("-invalid-name", InvalidElement);
28+
customElements.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-
components.customElements.define("INVALID-NAME", InvalidElement);
37+
customElements.define("INVALID-NAME", InvalidElement);
3838
}).to.throw(
3939
/The element name 'INVALID-NAME' is not valid./
4040
);

0 commit comments

Comments
 (0)