Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REFACTOR: Using html parser to update index.html file #396

Merged
merged 6 commits into from Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion example/pubspec.lock
Expand Up @@ -64,6 +64,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.2"
cupertino_icons:
dependency: "direct main"
description:
Expand Down Expand Up @@ -96,7 +103,7 @@ packages:
path: ".."
relative: true
source: path
version: "2.2.4"
version: "2.2.5"
flutter_test:
dependency: "direct dev"
description: flutter
Expand All @@ -107,6 +114,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.15.0"
image:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions lib/cli_commands.dart
Expand Up @@ -3,6 +3,7 @@
/// This is the main entry point for the Flutter Native Splash package.
library flutter_native_splash_cli;

import 'package:html/parser.dart' as html_parser;
import 'package:image/image.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
Expand Down
30 changes: 15 additions & 15 deletions lib/templates.dart
Expand Up @@ -501,21 +501,21 @@ body {
}
''';

const List<String> _indexHtmlPicture = [
' <picture id="splash">',
' <source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">',
' <source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">',
' <img class="[IMAGEMODE]" aria-hidden="true" src="splash/img/light-1x.png" alt=""/>',
' </picture>',
];

const List<String> _indexHtmlBrandingPicture = [
' <picture id="splash-branding">',
' <source srcset="splash/img/branding-1x.png 1x, splash/img/branding-2x.png 2x, splash/img/branding-3x.png 3x, splash/img/branding-4x.png 4x" media="(prefers-color-scheme: light)">',
' <source srcset="splash/img/branding-dark-1x.png 1x, splash/img/branding-dark-2x.png 2x, splash/img/branding-dark-3x.png 3x, splash/img/branding-dark-4x.png 4x" media="(prefers-color-scheme: dark)">',
' <img class="[BRANDINGMODE]" aria-hidden="true" src="splash/img/branding-1x.png" alt=""/>',
' </picture>',
];
const String _indexHtmlPicture = '''
<picture id="splash">
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">
<img class="[IMAGEMODE]" aria-hidden="true" src="splash/img/light-1x.png" alt=""/>
</picture>
''';

const String _indexHtmlBrandingPicture = '''
<picture id="splash-branding">
<source srcset="splash/img/branding-1x.png 1x, splash/img/branding-2x.png 2x, splash/img/branding-3x.png 3x, splash/img/branding-4x.png 4x" media="(prefers-color-scheme: light)">
<source srcset="splash/img/branding-dark-1x.png 1x, splash/img/branding-dark-2x.png 2x, splash/img/branding-dark-3x.png 3x, splash/img/branding-dark-4x.png 4x" media="(prefers-color-scheme: dark)">
<img class="[BRANDINGMODE]" aria-hidden="true" src="splash/img/branding-1x.png" alt=""/>
</picture>
''';

const String _webJS = '''
function removeSplashFromWeb() {
Expand Down
140 changes: 55 additions & 85 deletions lib/web.dart
Expand Up @@ -88,7 +88,7 @@ void _createWebSplash({
backgroundImage: backgroundImage,
);
_createSplashJs();
updateIndex(
_updateHtml(
imageMode: imageMode,
imagePath: imagePath,
brandingMode: brandingMode,
Expand Down Expand Up @@ -204,103 +204,73 @@ void _createSplashJs() {
file.writeAsStringSync(_webJS);
}

void updateIndex({
void _updateHtml({
required String imageMode,
required String? imagePath,
required String brandingMode,
required String? brandingImagePath,
}) {
print('[Web] Updating index.html');
final webIndex = File(_webIndex);
final lines = webIndex.readAsLinesSync();
final document = html_parser.parse(webIndex.readAsStringSync());

var foundExistingStyleSheet = false;
bool foundExistingMetaViewport = false;
bool foundExistingJs = false;
var headCloseTagLine = 0;
var bodyOpenTagLine = 0;
var existingPictureLine = 0;
var existingBrandingPictureLine = 0;

const styleSheetLink =
'<link rel="stylesheet" type="text/css" href="splash/style.css">';
const metaViewport =
'<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>';
const jsLink = '<script src="splash/splash.js"></script>';
for (var x = 0; x < lines.length; x++) {
final line = lines[x];
// Add style sheet if it doesn't exist
document.querySelector(
'link[rel="stylesheet"][type="text/css"][href="splash/style.css"]',
) ??
document.head?.append(
html_parser.parseFragment(
' <link rel="stylesheet" type="text/css" href="splash/style.css">\n',
container: '',
),
);

if (line.contains(styleSheetLink)) {
foundExistingStyleSheet = true;
}
if (line.contains(metaViewport)) {
foundExistingMetaViewport = true;
}
if (line.contains(jsLink)) {
foundExistingJs = true;
}
// Add meta viewport if it doesn't exist
document.querySelector(
'meta[content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"][name="viewport"]',
) ??
document.head?.append(
html_parser.parseFragment(
' <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">\n',
container: '',
),
);

if (line.contains('</head>')) {
headCloseTagLine = x;
} else if (line.contains('<body')) {
bodyOpenTagLine = x;
} else if (line.contains('<picture id="splash">')) {
existingPictureLine = x;
} else if (line.contains('<picture id="splash-branding">')) {
existingBrandingPictureLine = x;
}
}
// Add javascript if it doesn't exist
document.querySelector(
'script[src="splash/splash.js"]',
) ??
document.head?.append(
html_parser.parseFragment(
' <script src="splash/splash.js"></script>\n',
container: '',
),
);

if (!foundExistingStyleSheet) {
lines[headCloseTagLine] = ' $styleSheetLink\n${lines[headCloseTagLine]}';
}
if (!foundExistingMetaViewport) {
lines[headCloseTagLine] = ' $metaViewport\n${lines[headCloseTagLine]}';
// Update splash image
document.querySelector('picture#splash')?.remove();
if (imagePath != null) {
document.body?.insertBefore(
html_parser.parseFragment(
_indexHtmlPicture.replaceAll('[IMAGEMODE]', imageMode),
container: '',
),
document.body?.firstChild,
);
}

if (!foundExistingJs) {
lines[headCloseTagLine] = ' $jsLink\n${lines[headCloseTagLine]}';
// Update branding image
document.querySelector('picture#splash-branding')?.remove();
if (brandingImagePath != null) {
document.body?.insertBefore(
html_parser.parseFragment(
_indexHtmlBrandingPicture.replaceAll('[BRANDINGMODE]', brandingMode),
container: '',
),
document.body?.firstChild,
);
}

if (existingPictureLine == 0) {
if (imagePath != null) {
for (var x = _indexHtmlPicture.length - 1; x >= 0; x--) {
lines[bodyOpenTagLine + 1] =
'${_indexHtmlPicture[x].replaceFirst('[IMAGEMODE]', imageMode)}\n${lines[bodyOpenTagLine + 1]}';
}
}
} else {
if (imagePath != null) {
for (var x = 0; x < _indexHtmlPicture.length; x++) {
lines[existingPictureLine + x] =
_indexHtmlPicture[x].replaceFirst('[IMAGEMODE]', imageMode);
}
} else {
lines.removeRange(
existingPictureLine,
existingPictureLine + _indexHtmlPicture.length,
);
}
}
if (existingBrandingPictureLine == 0) {
if (brandingImagePath != null) {
for (var x = _indexHtmlBrandingPicture.length - 1; x >= 0; x--) {
lines[bodyOpenTagLine + 1] =
'${_indexHtmlBrandingPicture[x].replaceFirst('[BRANDINGMODE]', brandingMode)}\n${lines[bodyOpenTagLine + 1]}';
}
}
} else {
if (brandingImagePath != null) {
for (var x = 0; x < _indexHtmlBrandingPicture.length; x++) {
lines[existingBrandingPictureLine + x] = _indexHtmlBrandingPicture[x]
.replaceFirst('[BRANDINGMODE]', brandingMode);
}
} else {
lines.removeRange(
existingBrandingPictureLine,
existingBrandingPictureLine + _indexHtmlBrandingPicture.length,
);
}
}
webIndex.writeAsStringSync('${lines.join('\n')}\n');
// Write the updated index.html
webIndex.writeAsStringSync(document.outerHtml);
}
1 change: 1 addition & 0 deletions pubspec.yaml
Expand Up @@ -14,6 +14,7 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
html: ^0.15.0
image: ^3.1.3
js: ^0.6.4
lint: ^1.8.2
Expand Down