11[ ![ Pub Package] ( https://img.shields.io/pub/v/universal_html.svg )] ( https://pub.dartlang.org/packages/universal_html )
2- [ ![ Github Actions CI] ( https://github.com/dint-dev/universal_html/workflows/Dart%20CI/badge.svg )] ( https://github.com/dint-dev/universal_html/actions?query=workflow%3A%22Dart+CI%22 )
2+ [ ![ package publisher] ( https://img.shields.io/pub/publisher/universal_html.svg )] ( https://pub.dev/packages/universal_html/publisher )
3+ [ ![ Github Actions CI] ( https://github.com/dint-dev/universal_html/workflows/Dart%20CI/badge.svg )] ( https://github.com/dint-dev/universal_html/actions )
34
45# Introduction
56A cross-platform ` dart:html ` :
67 * __ Eases cross-platform development__
7- * You can use this package in browsers, mobile, desktop, and server-side VM, and server-side
8- Javascript (Node.JS, Cloud Functions, etc.).
8+ * You can use this package in browsers, mobile, desktop, and server-side VM, and Node.JS.
99 * Just replace ` dart:html ` imports with ` package:universal_html/html.dart ` . Normal
1010 _ dart: html_ will continue to be used when application run in browsers.
1111 * __ Extensive support for processing HTML and XML documents__
12- * Parse, manipulate, and print [ DOM nodes] ( https://pub. dev/documentation/universal_html/latest/universal_html /Node-class.html ) .
13- * Find DOM nodes with [ querySelectorAll] ( https://pub. dev/documentation/universal_html/latest/universal_html /querySelectorAll.html )
12+ * Parse, manipulate, and print [ DOM nodes] ( https://api.dart. dev/stable/2.19.3/dart-html /Node-class.html ) .
13+ * Find DOM nodes with [ querySelectorAll] ( https://api.dart. dev/stable/2.19.3/dart-html /querySelectorAll.html )
1414 and other CSS query methods.
15- * Submit forms and more.
1615 * __ EventSource streaming support__
17- * Implements _ dart: html_ [ EventSource API] ( https://developer.mozilla.org/en-US/docs/Web/API/EventSource ) .
16+ * Cross-platform _ dart: html_ ` EventSource ` ("application/event-stream").
17+ * If you want to customize EventSource HTTP headers outside browsers, see
18+ [ EventSourceOutsideBrowser] ( https://pub.dev/documentation/universal_html/latest/universal_html/EventSourceOutsideBrowser-class.html ) .
1819
1920The project is licensed under the [ Apache License 2.0] ( LICENSE ) . Some of the source code was adopted
20- from the original [ dart: html ] ( https://github.com/dart-lang/sdk/tree/master/tools/dom ) , which is
21- documented in the relevant files.
21+ from the original [ dart: html ] ( https://github.com/dart-lang/sdk/tree/master/tools/dom ) in Dart SDK,
22+ which is documented in the relevant files.
2223
2324## Documentation
2425 * [ API reference] ( https://pub.dev/documentation/universal_html/latest/ )
@@ -34,7 +35,7 @@ documented in the relevant files.
3435In ` pubspec.yaml ` :
3536``` yaml
3637dependencies :
37- universal_html : ^2.0.8
38+ universal_html : ^2.2.3
3839` ` `
3940
4041## 2. Use
@@ -58,20 +59,6 @@ void main() {
5859}
5960```
6061
61- ## Implemented APIs
62- ### Summary
63- * __ Document node classes__
64- * __ DOM parsing__
65- * Use _ element.innerHtml_ setter, _ DomParser_ , or _ package: universal_html /parsing.dart_ .
66- * HTML parsing uses [ package: html ] ( https://pub.dev/packages/html ) , CSS parsing uses
67- [ package: csslib ] ( https://pub.dev/packages/csslib ) , and XML parsing uses our own parser.
68- * __ DOM printing__
69- * Use _ element.innerHtml_ or _ element.outerHtml_ .
70- * __ DOM events__
71- * For example, _ element.onClick.listen(...)_ receives invocation of _ element.click()_ .
72- * __ CSS classes__ (_ CssStyleDeclaration_ , etc.)
73- * __ Most CSS queries__
74-
7562# Examples
7663## Parsing HTML
7764Use [ parseHtmlDocument] ( https://pub.dev/documentation/universal_html/latest/universal_html.parsing/parseHtmlDocument.html ) :
@@ -99,19 +86,99 @@ void main() {
9986Load a _ Window_ with [ WindowController] ( https://pub.dev/documentation/universal_html/latest/universal_html.controller/WindowController-class.html ) :
10087
10188``` dart
89+ import 'dart:io' show Cookie;
10290import 'package:universal_html/controller.dart';
10391
10492Future main() async {
10593 // Load a document.
10694 final controller = WindowController();
95+ controller.defaultHttpClient.userAgent = 'My Hacker News client';
10796 await controller.openHttp(
97+ method: 'GET',
10898 uri: Uri.parse("https://news.ycombinator.com/"),
99+ onRequest: (HttpClientRequest request) {
100+ // Add custom headers
101+ request.headers.set('Authorization', 'headerValue');
102+ request.cookies.add(Cookie('cookieName', 'cookieValue'));
103+ },
104+ onResponse: (HttpClientResponse response) {
105+ print('Status code: ${response.statusCode}');
106+ },
109107 );
110108
111109 // Select the top story using a CSS query
112- final topStoryTitle = controller.document.querySelectorAll(".athing > .title").first.text;
110+ final titleElements = controller.document.querySelectorAll(".athing > .title");
111+ final topStoryTitle = titleElements.first.text;
113112
114113 // Print result
115114 print("Top Hacker News story is: $topStoryTitle");
116115}
116+ ```
117+
118+ ## EventSource
119+ ` EventSource ` ([ see mozilla.org] ( https://developer.mozilla.org/en-US/docs/Web/API/EventSource ) )
120+ is a browser API for reading "application/event-stream" streams. It has been supported by browsers
121+ for a long time.
122+
123+ ``` dart
124+ import 'package:universal_html/html.dart';
125+
126+ Future<void> main() async {
127+ final eventSource = EventSource('http://example.com/events');
128+ await for (var message in event.onMessage) {
129+ print('Event type: ${message.type}');
130+ print('Event data: ${message.data}');
131+ }
132+ }
133+ ```
134+
135+ EventSource requests from real browsers are typically authenticated using cookies.
136+ If you want to add cookies or customize other HTTP headers, you need to use
137+ [ EventSourceOutsideBrowser] ( https://pub.dev/documentation/universal_html/latest/universal_html/EventSourceOutsideBrowser-class.html ) :
138+ ``` dart
139+ import 'package:universal_html/universal_html.dart';
140+ import 'dart:io' show Cookie;
141+
142+ Future<void> main() async {
143+ final eventSource = EventSource('http://example.com/events');
144+
145+ // The following block will NOT be executed in browsers.
146+ // Because compiler can infer instances of EventSourceOutsideBrowser are never constructed,
147+ // it will not appear in Javascript either.
148+ if (eventSource is EventSourceOutsideBrowser) {
149+ eventSource.onHttpClientRequest = (eventSource, request) {
150+ request.headers.set('Authorization', 'example');
151+ request.cookies.add(Cookie('name', 'value'));
152+ };
153+ eventSource.onHttpClientResponse = (eventSource, request, response) {
154+ // ...
155+ };
156+ }
157+
158+ await for (var message in eventSource.onMessage) {
159+ print('Event:');
160+ print(' type: ${message.type}');
161+ print(' data: ${message.data}');
162+ }
163+ }
164+ ```
165+
166+ ## Testing
167+ ``` dart
168+ import 'package:universal_html/controller.dart';
169+ import 'package:test/test.dart';
170+
171+ void main() {
172+ setUp(() {
173+ WindowController.instance = WindowController();
174+ });
175+
176+ test('test #1', () {
177+ // ...
178+ });
179+
180+ test('test #2', () {
181+ // ...
182+ });
183+ }
117184```
0 commit comments