Files
Paul Berry f4ff72aadd Migrate analyzer_utilities package to new constructor decl syntax.
This change migrates the analyzer_utilities package to use the new
constructor declaration syntax, described in
https://github.com/dart-lang/language/blob/main/accepted/future-releases/primary-constructors/feature-specification.md#abbreviations-of-in-body-constructor-declarations.

This change was performed in an automated fashion, by (a) bumping the
packages' SDK constraints to `3.13.0-0`, (b) enabling the lints
`unnecessary_type_name_in_constructor` and
`unnecessary_const_in_enum_constructor`, (c) fixing the resulting lint
failures using `dart fix`, and then (d) reformatting the affected
files.

To ease code review, I've reverted unrelated formatting changes.

Since this change requires bumping SDK constaints to `3.13.0-0`, it
was only performed on packages that are *not* published on
pub. (Packages that *are* published on pub should remain on lower
language versions until at least after the stable version of 3.13 is
released, so that we don't block users on the stable channel from
receiving updates to those packages.)

Change-Id: Ib9564fe588b1118f7e810bd39ff9c6576a6a6964
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505066
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2026-05-21 12:49:15 -07:00

106 lines
2.4 KiB
Dart

// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// A lightweight DOM model.
library;
import 'dart:convert';
const _htmlEscape = HtmlEscape(HtmlEscapeMode.element);
class Document extends Element {
static const Set<String> selfClosing = {'br', 'link', 'meta'};
new() : super.tag('');
/// Return the full HTML text for the document.
String get outerHtml {
var buf = StringBuffer();
void emitNode(Node node) {
if (node is Element) {
buf.write('<${node.name}');
for (var attr in node.attributes.keys) {
buf.write(' $attr="${node.attributes[attr]}"');
}
if (node.nodes.length == 1 &&
node.nodes.first is Text &&
!(node.nodes.first as Text).text.contains('\n')) {
buf.write('>');
var text = node.nodes.first as Text;
buf.write(_htmlEscape.convert(text.text));
buf.write('</${node.name}>');
} else {
buf.write('>');
for (var child in node.nodes) {
emitNode(child);
}
if (!selfClosing.contains(node.name)) {
buf.write('</${node.name}>');
}
}
} else if (node is Text) {
buf.write(_htmlEscape.convert(node.text));
} else {
throw 'unknown node type: $node';
}
}
buf.write('<!DOCTYPE html>');
for (var child in nodes) {
emitNode(child);
}
buf.writeln();
return buf.toString();
}
}
class Element extends Node {
final String name;
Map<String, String> attributes = {};
new tag(this.name);
List<Element> get children => nodes.whereType<Element>().toList();
List<String> get classes {
var classes = attributes['class'];
if (classes != null) {
return classes.split(' ').toList();
} else {
return const [];
}
}
void append(Node child) {
child.parent = this;
nodes.add(child);
}
}
abstract class Node {
Element? parent;
final List<Node> nodes = [];
}
class Text extends Node {
static final RegExp tagRegex = RegExp(r'<[^>]+>');
final String text;
new(this.text);
@override
List<Node> get nodes => const [];
String get textRemoveTags {
return text.replaceAll(tagRegex, '');
}
}