universal_html 1.1.0

Pub Package

Introduction #

Cross-platform dart:html. Works in browser, server-side (Dart VM or Node.JS), and Flutter.

The project is licensed under the Apache License 2.0.

Contributing #

  • This is an open-source project that welcomes new contributors. Don't be afraid to change things. Both small and big changes are welcome.
  • Bugs and enhancements are discussed in the Github issue tracker.
  • Have a contribution? Create a pull request. A contributor may be welcomed to become an administrator who can push changes without code review process.

Credits #

Similar projects #

Getting started #

1. Add dependency #

In pubspec.yaml:

dependencies:
  universal_html: ^1.1.0

Now you can replace usage of "dart:html" with "package:universal_html/html.dart".

2. Choose library #

Option 1 #

import 'package:universal_html/prefer_sdk/html.dart';

This library exports dart:html by default. The library exports our implementation only when dart:io is available.

If you use this library, your package will not compile in Node.JS. Dart tools may also mistakenly think that your package is not compatible with VM/Flutter.

Option 2 #

import 'package:universal_html/prefer_universal/html.dart';

This library exports our implementation by default. The library exports dart:html only in browsers.

Getting warnings? In some cases, when you mix universal_io classes with dart:html classes, your IDE produces type warnings ("universal_html Element is not dart:html Element"). Your application should still compile (in Dart2js, universal_html classes will be dart:html classes).

Proposed future method #

Dart SDK feature request #37232 proposes that developers could supply missing dart:html in VM/Flutter in pubspec.yaml.

3. That's it! #

import "package:universal_html/html.dart";

void main() {
  // Create a DOM tree
  final divElement = new DivElement();
  divElement.append(new Element.tag("h1")
    ..classes.add("greeting")
    ..appendText("Hello world!"));

  // Print outer HTML
  print(divElement.outerHtml);
  // --> <div><h1>Hello world</h1></div>

  // Do a CSS query
  print(divElement.querySelector("div > .greeting").text);
  // --> Hello world
}

Manual #

Server-side rendering #

The package comes with ServerSideRenderer, which is a web server for rendering your web application in the server-side.

import 'package:universal_html/driver.dart';
import 'package:universal_html/html.dart';

void main() {
  final renderer = new ServerSideRenderer(webAppMain);
  renderer.bind("localhost", 12345);
}

void webAppMain() {
  document.body.appendText("Hello world!");
}

Creating and using browser simulators #

import 'package:universal_html/driver.dart';
import 'package:universal_html/html.dart';

Future main() async {
  // Construct a driver
  final driver = new HtmlDriver(userAgent:"My Hacker News bot");
  
  // Load a document.
  await driver.setDocumentFromUri(Uri.parse("https://news.ycombinator.com/"));
  
  // Select top story
  final topStoryTitle = driver.document.querySelectorAll(".athing > .title").first.text;
  print("Top Hacker News story is: ${topStoryTitle}");
}

Implemented APIs #

Strategy #

  • Our goal is that universal_html behaves identically to dart:html running in Chrome.
  • DIFFERENCES.md contains automatically generated list of dart:html APIs that are not yet declared by this package.
  • Some APIs are declared, but not implemented. These will either throw UnimplementedError or (when appropriate) fail silently.

HTML #

  • Document nodes
    • All core classes (Node, Element, etc.)
    • All HtmlElement subclasses (AnchorElement, ResetButtonElement, etc.)
    • Most class members. For example, anchorElement.href returns the resolved URI. Only a few class members are still missing (see DIFFERENCES.md).
  • DOM parsing
  • DOM printing
    • element.innerHtml, element.outerHtml
  • DOM events
    • For example, element.onClick.listen(...) receives invocation of element.click().

CSS #

  • Much of the CSS classes (CssStyleDeclaration, etc.)
  • CSS queries
    • Methods element.querySelector(..), element.querySelectorAll(..), element.matchesSelector(..)
    • Element name (table)
    • Element ID (#id)
    • Element class (.classA.classB)
    • Combinators:
      • element.class#id
      • s0 s1 s2
      • s0 s1 s2
      • s0 > s1 > s2
      • s0 ~ s1 ~ s2
      • s0 + s1 + s2
    • Pseudoselectors:
      • :disabled
      • :first-child
      • :last-child
      • :not(x)
      • :nth-child(5)
      • :nth-child(even)
      • :nth-child(3n+1)
      • :only-child
      • :root
    • Attribute selectors:
      • [name]
      • [name=value]
      • [name~=value]
      • [name|=value]
      • [name^=value]
      • [name$=value]
      • [name*=value]

Layout #

Currently, the library does not attempt to calculate layout for the elements.

Every DOM element has a private field RenderData, which you can get with BrowserImplementationUtils.getRenderData(...)). When a property such as element.offset is called, the RenderData instance is responsible for evaluating the answer. The default implementation generally returns 0. If you want to implement layout engine, you can override BrowserImplementation.newRenderData(element).

Networking #

Currently, networking classes don't implement same-origin policies, CORS, and other security specifications. We hope to fix this in future.

The package supports:

  • HttpRequest
    • Full support.
  • EventSource
    • Full support.

Various browser APIs #

  • Navigator
    • locale, userAgent, etc.
  • Window
    • console
    • history
      • back(...), pushState(...), etc.
    • location
      • origin, href, etc.
    • localStorage / sessionStorage
      • Stores values in the heap.

Other SDK libraries #

We wrote mock implementation of the following SDK libraries:

  • dart:indexed_db
  • dart:js
  • dart:js_util
  • dart:svg
  • dart:web_gl

Any attempt to use these APIs will ead to UnimplementedException. The libraries are available in:

  • package:universal_html/(libraryName).dart
  • package:universal_html/prefer_sdk/(libraryName).dart
  • package:universal_html/prefer_universal/(libraryName).dart

1.1.0 #

  • The sole copyright owner (except for code derived from the Dart SDK as noted in the relevant files) decided to publish the source code the Apache License 2.0. to make the project more enterprise-happy. Previous versions were published under the MIT License.
  • Many new tests and bug fixes.
  • Many new dart:html APIs.
  • Removed class factory APIs in HtmlDriver in favor of separate BrowserImplementation and BrowserImplementationUtils.
  • Deprecated "package:universal_html/browser/(library).dart" in favor of more descriptive "package:universal_html/prefer_sdk/(library).dart". Deprecated APIs will be removed in future.
  • Added "package:universal_html/prefer_universal/(library).dart".

1.0.13 #

  • Fixed dependencies.

1.0.12 #

  • A fix related to Dart SDK 2.5.

1.0.11 #

  • Fixes compatibility with Dart SDK 2.5.
  • EventSource support.

1.0.10 #

  • Eliminated the following error that Dart build system threw in some cases: Unsupported conditional import of dart:html found in universal_html|lib/html.dart

1.0.9 #

  • Fixed bugs related to XML handling.

1.0.8 #

  • Fixed various bugs.

1.0.7 #

  • Fixed various bugs.

1.0.6 #

  • Fixed various bugs.
  • Added browser/html.dart and related documentation.
  • Added ServerSideRenderer.

1.0.5 #

  • Fixed a dependency.

1.0.4 #

  • Fixed various bugs and added dart:html APIs.

1.0.3 #

  • Fixed various bugs.

1.0.2 #

  • Added dart:html APIs (HttpRequest, etc.) and new libraries (js.dart, js_util.dart, etc.).

1.0.1 #

  • Fixed various bugs and added dart:html APIs.

0.0.1 #

  • Initial release

example/example.dart

import "package:universal_html/html.dart";

void main() {
  // Create a DOM tree
  final divElement = DivElement();
  divElement.append(Element.tag("h1")
    ..classes.add("greeting")
    ..appendText("Hello world!"));

  // Print outer HTML
  print(divElement.outerHtml);
  // --> <div><h1>Hello world</h1></div>

  // Do a CSS query
  print(divElement.querySelector("div > .greeting").text);
  // --> Hello world
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  universal_html: ^1.1.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:universal_html/html.dart';
import 'package:universal_html/prefer_universal/html.dart';
import 'package:universal_html/prefer_universal/svg.dart';
import 'package:universal_html/prefer_universal/web_gl.dart';
import 'package:universal_html/prefer_universal/js.dart';
import 'package:universal_html/prefer_universal/js_util.dart';
import 'package:universal_html/prefer_universal/indexed_db.dart';
import 'package:universal_html/svg.dart';
import 'package:universal_html/web_gl.dart';
import 'package:universal_html/driver.dart';
import 'package:universal_html/browser/html.dart';
import 'package:universal_html/browser/svg.dart';
import 'package:universal_html/browser/web_gl.dart';
import 'package:universal_html/browser/js.dart';
import 'package:universal_html/browser/js_util.dart';
import 'package:universal_html/browser/indexed_db.dart';
import 'package:universal_html/js.dart';
import 'package:universal_html/js_util.dart';
import 'package:universal_html/indexed_db.dart';
import 'package:universal_html/prefer_sdk/html.dart';
import 'package:universal_html/prefer_sdk/svg.dart';
import 'package:universal_html/prefer_sdk/web_gl.dart';
import 'package:universal_html/prefer_sdk/js.dart';
import 'package:universal_html/prefer_sdk/js_util.dart';
import 'package:universal_html/prefer_sdk/indexed_db.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
62
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
81
Learn more about scoring.

We analyzed this package on Aug 18, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19

Platforms

Detected platforms: web

Platform components identified in package: html, js.

Health suggestions

Format lib/src/html.dart.

Run dartfmt to format lib/src/html.dart.

Format lib/src/html/canvas.dart.

Run dartfmt to format lib/src/html/canvas.dart.

Format lib/src/html/css_class_set.dart.

Run dartfmt to format lib/src/html/css_class_set.dart.

Fix additional 5 files with analysis or formatting issues.

Additional issues in the following files:

  • lib/src/html/css_style_declaration_base.dart (Run dartfmt to format lib/src/html/css_style_declaration_base.dart.)
  • lib/src/html/document.dart (Run dartfmt to format lib/src/html/document.dart.)
  • lib/src/html/node_printing.dart (Run dartfmt to format lib/src/html/node_printing.dart.)
  • lib/src/html/rtc.dart (Run dartfmt to format lib/src/html/rtc.dart.)
  • lib/src/html/window.dart (Run dartfmt to format lib/src/html/window.dart.)

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.4.0 <3.0.0
async ^2.3.0 2.3.0
charcode ^1.1.2 1.1.2
collection ^1.14.11 1.14.12
csslib ^0.16.0 0.16.1
html ^0.14.0 0.14.0+2
meta ^1.1.7 1.1.7
typed_data ^1.1.6 1.1.6
universal_io >=0.7.3 <0.9.0 0.8.1
xml ^3.5.0 3.5.0
zone_local ^0.1.1 0.1.1
Transitive dependencies
convert 2.1.1
path 1.6.4
petitparser 2.4.0
source_span 1.5.5
term_glyph 1.1.0
Dev dependencies
pedantic ^1.8.0
stream_channel ^2.0.0
test ^1.6.3