@@ -8,8 +8,6 @@ import 'dart:typed_data';
88import 'package:dwds/data/build_result.dart' ;
99// ignore: import_of_legacy_library_into_null_safe
1010import 'package:dwds/dwds.dart' ;
11- import 'package:html/dom.dart' ;
12- import 'package:html/parser.dart' ;
1311import 'package:logging/logging.dart' as logging;
1412import 'package:meta/meta.dart' ;
1513import 'package:mime/mime.dart' as mime;
@@ -29,14 +27,14 @@ import '../base/platform.dart';
2927import '../build_info.dart' ;
3028import '../build_system/targets/scene_importer.dart' ;
3129import '../build_system/targets/shader_compiler.dart' ;
32- import '../build_system/targets/web.dart' ;
3330import '../bundle_builder.dart' ;
3431import '../cache.dart' ;
3532import '../compile.dart' ;
3633import '../convert.dart' ;
3734import '../dart/package_map.dart' ;
3835import '../devfs.dart' ;
3936import '../globals.dart' as globals;
37+ import '../html_utils.dart' ;
4038import '../project.dart' ;
4139import '../vmservice.dart' ;
4240import '../web/bootstrap.dart' ;
@@ -136,9 +134,7 @@ class WebAssetServer implements AssetReader {
136134 this ._modules,
137135 this ._digests,
138136 this ._nullSafetyMode,
139- ) : basePath = _parseBasePathFromIndexHtml (globals.fs.currentDirectory
140- .childDirectory ('web' )
141- .childFile ('index.html' ));
137+ ) : basePath = _getIndexHtml ().getBaseHref ();
142138
143139 // Fallback to "application/octet-stream" on null which
144140 // makes no claims as to the structure of the data.
@@ -299,7 +295,7 @@ class WebAssetServer implements AssetReader {
299295 server,
300296 PackageUriMapper (packageConfig),
301297 digestProvider,
302- server.basePath! ,
298+ server.basePath,
303299 ).strategy,
304300 expressionCompiler: expressionCompiler,
305301 spawnDds: enableDds,
@@ -345,12 +341,11 @@ class WebAssetServer implements AssetReader {
345341 @visibleForTesting
346342 Uint8List ? getMetadata (String path) => _webMemoryFS.metadataFiles[path];
347343
348- @visibleForTesting
349-
350344 /// The base path to serve from.
351345 ///
352346 /// It should have no leading or trailing slashes.
353- String ? basePath = '' ;
347+ @visibleForTesting
348+ String basePath;
354349
355350 // handle requests for JavaScript source, dart sources maps, or asset files.
356351 @visibleForTesting
@@ -496,27 +491,20 @@ class WebAssetServer implements AssetReader {
496491 WebRendererMode webRenderer = WebRendererMode .html;
497492
498493 shelf.Response _serveIndex () {
494+
495+ final IndexHtml indexHtml = _getIndexHtml ();
496+
497+ indexHtml.applySubstitutions (
498+ // Currently, we don't support --base-href for the "run" command.
499+ baseHref: '/' ,
500+ serviceWorkerVersion: null ,
501+ );
502+
499503 final Map <String , String > headers = < String , String > {
500504 HttpHeaders .contentTypeHeader: 'text/html' ,
505+ HttpHeaders .contentLengthHeader: indexHtml.content.length.toString (),
501506 };
502- final File indexFile = globals.fs.currentDirectory
503- .childDirectory ('web' )
504- .childFile ('index.html' );
505-
506- if (indexFile.existsSync ()) {
507- String indexFileContent = indexFile.readAsStringSync ();
508- if (indexFileContent.contains (kBaseHrefPlaceholder)) {
509- indexFileContent = indexFileContent.replaceAll (kBaseHrefPlaceholder, '/' );
510- headers[HttpHeaders .contentLengthHeader] = indexFileContent.length.toString ();
511- return shelf.Response .ok (indexFileContent,headers: headers);
512- }
513- headers[HttpHeaders .contentLengthHeader] =
514- indexFile.lengthSync ().toString ();
515- return shelf.Response .ok (indexFile.openRead (), headers: headers);
516- }
517-
518- headers[HttpHeaders .contentLengthHeader] = _kDefaultIndex.length.toString ();
519- return shelf.Response .ok (_kDefaultIndex, headers: headers);
507+ return shelf.Response .ok (indexHtml.content, headers: headers);
520508 }
521509
522510 // Attempt to resolve `path` to a dart file.
@@ -783,9 +771,9 @@ class WebDevFS implements DevFS {
783771 webAssetServer.webRenderer = WebRendererMode .canvaskit;
784772 }
785773 if (hostname == 'any' ) {
786- _baseUri = Uri .http ('localhost:$selectedPort ' , webAssetServer.basePath! );
774+ _baseUri = Uri .http ('localhost:$selectedPort ' , webAssetServer.basePath);
787775 } else {
788- _baseUri = Uri .http ('$hostname :$selectedPort ' , webAssetServer.basePath! );
776+ _baseUri = Uri .http ('$hostname :$selectedPort ' , webAssetServer.basePath);
789777 }
790778 return _baseUri! ;
791779 }
@@ -977,12 +965,11 @@ class ReleaseAssetServer {
977965 final FileSystemUtils _fileSystemUtils;
978966 final Platform _platform;
979967
980- @visibleForTesting
981-
982968 /// The base path to serve from.
983969 ///
984970 /// It should have no leading or trailing slashes.
985- final String ? basePath;
971+ @visibleForTesting
972+ final String basePath;
986973
987974 // Locations where source files, assets, or source maps may be located.
988975 List <Uri > _searchPaths () => < Uri > [
@@ -1070,67 +1057,21 @@ Future<Directory> _loadDwdsDirectory(
10701057 return fileSystem.directory (packageConfig['dwds' ]! .packageUriRoot);
10711058}
10721059
1073- String ? _stripBasePath (String path, String ? basePath) {
1074- path = _stripLeadingSlashes (path);
1075- if (basePath != null && path.startsWith (basePath)) {
1060+ String ? _stripBasePath (String path, String basePath) {
1061+ path = stripLeadingSlash (path);
1062+ if (path.startsWith (basePath)) {
10761063 path = path.substring (basePath.length);
10771064 } else {
10781065 // The given path isn't under base path, return null to indicate that.
10791066 return null ;
10801067 }
1081- return _stripLeadingSlashes (path);
1082- }
1083-
1084- String _stripLeadingSlashes (String path) {
1085- while (path.startsWith ('/' )) {
1086- path = path.substring (1 );
1087- }
1088- return path;
1089- }
1090-
1091- String _stripTrailingSlashes (String path) {
1092- while (path.endsWith ('/' )) {
1093- path = path.substring (0 , path.length - 1 );
1094- }
1095- return path;
1068+ return stripLeadingSlash (path);
10961069}
10971070
1098- String ? _parseBasePathFromIndexHtml (File indexHtml) {
1071+ IndexHtml _getIndexHtml () {
1072+ final File indexHtml =
1073+ globals.fs.currentDirectory.childDirectory ('web' ).childFile ('index.html' );
10991074 final String htmlContent =
11001075 indexHtml.existsSync () ? indexHtml.readAsStringSync () : _kDefaultIndex;
1101- final Document document = parse (htmlContent);
1102- final Element ? baseElement = document.querySelector ('base' );
1103- String ? baseHref =
1104- baseElement? .attributes == null ? null : baseElement! .attributes['href' ];
1105-
1106- if (baseHref == null || baseHref == kBaseHrefPlaceholder) {
1107- baseHref = '' ;
1108- } else if (! baseHref.startsWith ('/' )) {
1109- throw ToolExit (
1110- 'Error: The base href in "web/index.html" must be absolute (i.e. start '
1111- 'with a "/"), but found: `${baseElement !.outerHtml }`.\n '
1112- '$basePathExample ' ,
1113- );
1114- } else if (! baseHref.endsWith ('/' )) {
1115- throw ToolExit (
1116- 'Error: The base href in "web/index.html" must end with a "/", but found: `${baseElement !.outerHtml }`.\n '
1117- '$basePathExample ' ,
1118- );
1119- } else {
1120- baseHref = _stripLeadingSlashes (_stripTrailingSlashes (baseHref));
1121- }
1122-
1123- return baseHref;
1076+ return IndexHtml (htmlContent);
11241077}
1125-
1126- const String basePathExample = '''
1127- For example, to serve from the root use:
1128-
1129- <base href="/">
1130-
1131- To serve from a subpath "foo" (i.e. http://localhost:8080/foo/ instead of http://localhost:8080/) use:
1132-
1133- <base href="/foo/">
1134-
1135- For more information, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
1136- ''' ;
0 commit comments