[dart] Upgrade to Dart 2.12 and its null-safety features
This commit is contained in:
parent
0e8e894056
commit
291fc9111b
@ -5,7 +5,7 @@ homepage: https://labs.phundrak.com/phundrak/org-website-backend
|
|||||||
author: Lucien Cartier-Tilet <lucien@phundrak.com>
|
author: Lucien Cartier-Tilet <lucien@phundrak.com>
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.7.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ final icons = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the current page’s title
|
// Get the current page’s title
|
||||||
String getPageTitle() => querySelector('title').text;
|
String getPageTitle() => querySelector('title')!.text!;
|
||||||
|
|
||||||
// Create the home button
|
// Create the home button
|
||||||
Future<Element> makeHome() async {
|
Future<Element> makeHome() async {
|
||||||
@ -45,7 +45,7 @@ Future<Element> makeHome() async {
|
|||||||
'afterBegin',
|
'afterBegin',
|
||||||
Element.a()
|
Element.a()
|
||||||
..attributes['href'] = '/'
|
..attributes['href'] = '/'
|
||||||
..append(makeIcon(icons['home'])));
|
..append(makeIcon(icons['home']!)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a clickable icon
|
// Create a clickable icon
|
||||||
@ -61,7 +61,7 @@ Future<Element> makePages() async {
|
|||||||
..append(Element.a()
|
..append(Element.a()
|
||||||
..attributes['tabindex'] = '-1'
|
..attributes['tabindex'] = '-1'
|
||||||
..attributes['href'] = 'javascript:void(0)'
|
..attributes['href'] = 'javascript:void(0)'
|
||||||
..append(makeIcon(icons['pages'])))
|
..append(makeIcon(icons['pages']!)))
|
||||||
..classes.addAll(['nav-item', 'has-dropdown'])
|
..classes.addAll(['nav-item', 'has-dropdown'])
|
||||||
..append(Element.ul()
|
..append(Element.ul()
|
||||||
..attributes['id'] = 'drop-page'
|
..attributes['id'] = 'drop-page'
|
||||||
@ -87,23 +87,23 @@ Future<Element> makeShare() async {
|
|||||||
..append(Element.a()
|
..append(Element.a()
|
||||||
..attributes['href'] = 'javascript:void(0)'
|
..attributes['href'] = 'javascript:void(0)'
|
||||||
..attributes['tabindex'] = '-1'
|
..attributes['tabindex'] = '-1'
|
||||||
..append(makeIcon(icons['share'])))
|
..append(makeIcon(icons['share']!)))
|
||||||
..append(Element.ul()
|
..append(Element.ul()
|
||||||
..classes.add('dropdown')
|
..classes.add('dropdown')
|
||||||
..attributes['id'] = 'drop-share'
|
..attributes['id'] = 'drop-share'
|
||||||
..append(makeShareLink(
|
..append(makeShareLink(
|
||||||
makeIcon(icons['twitter']),
|
makeIcon(icons['twitter']!),
|
||||||
'https://twitter.com/share?text=${getPageTitle()}'
|
'https://twitter.com/share?text=${getPageTitle()}'
|
||||||
'&url=${window.location.href}'))
|
'&url=${window.location.href}'))
|
||||||
..append(makeShareLink(makeIcon(icons['reddit']),
|
..append(makeShareLink(makeIcon(icons['reddit']!),
|
||||||
'https://www.reddit.com/submit?title=${getPageTitle()}s&url=${window.location.href}'))
|
'https://www.reddit.com/submit?title=${getPageTitle()}s&url=${window.location.href}'))
|
||||||
..append(makeShareLink(makeIcon(icons['email']),
|
..append(makeShareLink(makeIcon(icons['email']!),
|
||||||
'mailto:?subject=${getPageTitle}&body=${window.location.href}'))
|
'mailto:?subject=$getPageTitle&body=${window.location.href}'))
|
||||||
..append(makeShareLink(
|
..append(makeShareLink(
|
||||||
makeIcon(icons['linkedin']),
|
makeIcon(icons['linkedin']!),
|
||||||
'https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}'
|
'https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}'
|
||||||
'&title=${getPageTitle()}'))
|
'&title=${getPageTitle()}'))
|
||||||
..append(makeShareLink(makeIcon(icons['facebook']),
|
..append(makeShareLink(makeIcon(icons['facebook']!),
|
||||||
'https://www.facebook.com/sharer/sharer.php?u=${window.location.href}')));
|
'https://www.facebook.com/sharer/sharer.php?u=${window.location.href}')));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ Future<Element> makeThemeChanger() async {
|
|||||||
..attributes['tabindex'] = '-1'
|
..attributes['tabindex'] = '-1'
|
||||||
..append(Element.span()
|
..append(Element.span()
|
||||||
..style.verticalAlign = 'top'
|
..style.verticalAlign = 'top'
|
||||||
..append(makeIcon(icons['theme']))))
|
..append(makeIcon(icons['theme']!))))
|
||||||
..append(Element.ul()
|
..append(Element.ul()
|
||||||
..classes.add('dropdown')
|
..classes.add('dropdown')
|
||||||
..attributes['id'] = 'theme-dropdown'
|
..attributes['id'] = 'theme-dropdown'
|
||||||
@ -144,7 +144,7 @@ Future<Element> makeToc() async {
|
|||||||
..append(Element.a()
|
..append(Element.a()
|
||||||
..attributes['tabindex'] = '-1'
|
..attributes['tabindex'] = '-1'
|
||||||
..attributes['href'] = 'javascript:void(0)'
|
..attributes['href'] = 'javascript:void(0)'
|
||||||
..append(makeIcon(icons['toc'])));
|
..append(makeIcon(icons['toc']!)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a navbar atop of the HTML body, containing:
|
// Add a navbar atop of the HTML body, containing:
|
||||||
|
@ -15,29 +15,29 @@ Future<String> fetchRemoteSitemap() async {
|
|||||||
|
|
||||||
// Parse the list of elements and detect pages from this list
|
// Parse the list of elements and detect pages from this list
|
||||||
Map<String, String> detectPages(List<Element> t_sitemap,
|
Map<String, String> detectPages(List<Element> t_sitemap,
|
||||||
[String t_prefix, Map<String, String> t_links]) {
|
[String? t_prefix, Map<String, String>? t_links]) {
|
||||||
t_links ??= <String, String>{};
|
t_links ??= <String, String>{};
|
||||||
|
|
||||||
// parse each element in sitemap
|
// parse each element in sitemap
|
||||||
for (var elem in t_sitemap) {
|
for (var elem in t_sitemap) {
|
||||||
// if it’s a link
|
// if it’s a link
|
||||||
if (elem.innerHtml.startsWith('<a')) {
|
if (elem.innerHtml!.startsWith('<a')) {
|
||||||
elem = elem.firstChild;
|
elem = elem.children[0];
|
||||||
final url = elem.attributes['href'];
|
final url = elem.attributes['href']!;
|
||||||
final text = elem.firstChild.text;
|
final text = elem.children[0].text;
|
||||||
if (excluded_keywords.contains(text) ||
|
if (excluded_keywords.contains(text) ||
|
||||||
excluded_keywords.contains(url.substring(0, url.length - 5))) {
|
excluded_keywords.contains(url.substring(0, url.length - 5))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
t_links['/$url'] = (t_prefix == null) ? text : '$text ($t_prefix)';
|
t_links!['/$url'] = ((t_prefix == null) ? text : '$text ($t_prefix)')!;
|
||||||
} else {
|
} else {
|
||||||
final prefix = (t_prefix == null)
|
final prefix = (t_prefix == null)
|
||||||
? elem.firstChild.text.replaceAll('\n', '')
|
? elem.firstChild!.text!.replaceAll('\n', '')
|
||||||
: '$t_prefix / ${elem.firstChild.text}'.replaceAll('\n', '');
|
: '$t_prefix / ${elem.firstChild!.text}'.replaceAll('\n', '');
|
||||||
t_links = detectPages(elem.children[0].children, prefix, t_links);
|
t_links = detectPages(elem.children[0].children, prefix, t_links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t_links;
|
return t_links!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function returns a Map which contains all links to languages detected
|
// This function returns a Map which contains all links to languages detected
|
||||||
@ -45,13 +45,13 @@ Map<String, String> detectPages(List<Element> t_sitemap,
|
|||||||
Future<Map<String, String>> parseSitemap() async {
|
Future<Map<String, String>> parseSitemap() async {
|
||||||
final content = await fetchRemoteSitemap();
|
final content = await fetchRemoteSitemap();
|
||||||
final sitemap = Element.ul()..innerHtml = content;
|
final sitemap = Element.ul()..innerHtml = content;
|
||||||
final sitemapNodes = sitemap.querySelector('ul').children;
|
final sitemapNodes = sitemap.querySelector('ul')!.children;
|
||||||
return detectPages(sitemapNodes);
|
return detectPages(sitemapNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createSitemap() async {
|
Future<void> createSitemap() async {
|
||||||
final sitemap = await parseSitemap();
|
final sitemap = await parseSitemap();
|
||||||
final pages = querySelector('#drop-page');
|
final pages = querySelector('#drop-page')!;
|
||||||
sitemap.forEach((url, name) {
|
sitemap.forEach((url, name) {
|
||||||
final link = Element.li()
|
final link = Element.li()
|
||||||
..classes.add('dropdown-item')
|
..classes.add('dropdown-item')
|
||||||
|
@ -13,7 +13,7 @@ Future<Element> makeHeader() async {
|
|||||||
..attributes['alt'] = 'Logo'
|
..attributes['alt'] = 'Logo'
|
||||||
..attributes['height'] = '150px'
|
..attributes['height'] = '150px'
|
||||||
..attributes['width'] = '150px')
|
..attributes['width'] = '150px')
|
||||||
..append(querySelector('h1'));
|
..append(querySelector('h1')!);
|
||||||
final subt = header.querySelector('.subtitle');
|
final subt = header.querySelector('.subtitle');
|
||||||
if (subt != null) {
|
if (subt != null) {
|
||||||
header.append(subt);
|
header.append(subt);
|
||||||
@ -32,8 +32,8 @@ Future<void> wrapTables() async {
|
|||||||
// All images that are not nested inside a link will be linkified to themselves.
|
// All images that are not nested inside a link will be linkified to themselves.
|
||||||
Future<void> linkifyImg() async {
|
Future<void> linkifyImg() async {
|
||||||
querySelectorAll('img').forEach((img) {
|
querySelectorAll('img').forEach((img) {
|
||||||
if (img.parent.tagName == 'P') {
|
if (img.parent!.tagName == 'P') {
|
||||||
final link = Element.a()..attributes['href'] = img.attributes['src'];
|
final link = Element.a()..attributes['href'] = img.attributes['src']!;
|
||||||
img.insertAdjacentElement('beforeBegin', link);
|
img.insertAdjacentElement('beforeBegin', link);
|
||||||
link.append(img);
|
link.append(img);
|
||||||
}
|
}
|
||||||
@ -61,10 +61,10 @@ Future<void> reorganizeHtml() async {
|
|||||||
await linkifyImg();
|
await linkifyImg();
|
||||||
|
|
||||||
// Add navbar to page
|
// Add navbar to page
|
||||||
querySelector('body').insertAdjacentElement('afterBegin', navbar);
|
querySelector('body')!.insertAdjacentElement('afterBegin', navbar);
|
||||||
|
|
||||||
// Add headet to page
|
// Add headet to page
|
||||||
querySelector('#content').insertAdjacentElement('beforeBegin', header);
|
querySelector('#content')!.insertAdjacentElement('beforeBegin', header);
|
||||||
|
|
||||||
// Add correct class to TOC
|
// Add correct class to TOC
|
||||||
final toc = (querySelector('#table-of-contents') ??
|
final toc = (querySelector('#table-of-contents') ??
|
||||||
@ -72,7 +72,7 @@ Future<void> reorganizeHtml() async {
|
|||||||
..attributes['id'] = 'table-of-contents'
|
..attributes['id'] = 'table-of-contents'
|
||||||
..innerText = 'Table of Contents Unavailable'))
|
..innerText = 'Table of Contents Unavailable'))
|
||||||
..classes.add('dropdown');
|
..classes.add('dropdown');
|
||||||
navbar.querySelector('#toc-drop').append(toc);
|
navbar.querySelector('#toc-drop')!.append(toc);
|
||||||
|
|
||||||
// Remove all <br> tags from HTML
|
// Remove all <br> tags from HTML
|
||||||
querySelectorAll('br').forEach((br) => br.remove());
|
querySelectorAll('br').forEach((br) => br.remove());
|
||||||
|
@ -2,22 +2,19 @@ import 'dart:html' show window, querySelector;
|
|||||||
|
|
||||||
final localStorage = window.localStorage;
|
final localStorage = window.localStorage;
|
||||||
|
|
||||||
Future<void> setTheme([String theme]) async {
|
Future<void> setTheme([String? theme]) async {
|
||||||
final currentTheme = theme ?? localStorage['theme'] ??
|
theme ??= localStorage['theem'] ??
|
||||||
() {
|
(window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
final devicePrefersDark =
|
? 'dark'
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
: 'light');
|
||||||
return devicePrefersDark ? 'nord' : 'light';
|
localStorage['theme'] = theme;
|
||||||
}();
|
querySelector('body')!
|
||||||
localStorage['theme'] = currentTheme;
|
|
||||||
querySelector('body')
|
|
||||||
..classes.clear()
|
..classes.clear()
|
||||||
..classes.add(currentTheme);
|
..classes.add(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableThemeChanger() {
|
void enableThemeChanger() {
|
||||||
final themes = <String>['light', 'dark', 'nord', 'black'];
|
final themes = <String>['light', 'dark', 'nord', 'black'];
|
||||||
themes.forEach((theme) =>
|
themes.forEach((theme) =>
|
||||||
querySelector('#${theme}Btn').onClick.listen((_) => setTheme(theme))
|
querySelector('#${theme}Btn')!.onClick.listen((_) => setTheme(theme)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user