diff --git a/.gitignore b/.gitignore index d124904..c9f949a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,14 @@ build .idea .packages .swp + +/**/bazel-bin +/**/bazel-captains_log* +/**/bazel-genfiles +/**/bazel-out +/**/bazel-testlogs +/**/.bazelify +/**/BUILD +/**/WORKSPACE +/**/packages.bzl + diff --git a/dev-workflow/captains_log_base/.analysis_options b/dev-workflow/captains_log_base/.analysis_options new file mode 100644 index 0000000..c290149 --- /dev/null +++ b/dev-workflow/captains_log_base/.analysis_options @@ -0,0 +1,20 @@ +# This file allows you to configure the Dart analyzer. +# +# The commented part below is just for inspiration. Read the guide here: +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer + +analyzer: +# strong-mode: +# implicit-casts: false +# implicit-dynamic: false + exclude: + - .bazelify/** + - bazel-bin/** + - bazel-captains_log_final/** + - bazel-genfiles/** + - bazel-out/** + - bazel-testlogs/** +# linter: +# rules: +# # see catalogue here: http://dart-lang.github.io/linter/lints/ +# - hash_and_equals diff --git a/dev-workflow/captains_log_base/.gitignore b/dev-workflow/captains_log_base/.gitignore new file mode 100644 index 0000000..04d4ee3 --- /dev/null +++ b/dev-workflow/captains_log_base/.gitignore @@ -0,0 +1,22 @@ +pubspec.lock +.buildlog +.packages +.project +.pub/ + +build/ +**/packages/ +web/gen +web/packages + +doc/api/ + +*.iml +*.ipr +*.iws +.idea/ +.DS_Store + +*.dart.js +*.info.json +*.js diff --git a/dev-workflow/captains_log_base/lib/captains_log.dart b/dev-workflow/captains_log_base/lib/captains_log.dart new file mode 100644 index 0000000..6b1da67 --- /dev/null +++ b/dev-workflow/captains_log_base/lib/captains_log.dart @@ -0,0 +1,109 @@ +import 'dart:html'; +// TODO: Add import + +// ignoring leap years +const int _secondsInAYear = 31536000; +const String _prompt = 'Something happened. Make it sound puzzling and heroic.'; +final List _templates = [ + 'We encountered what appeared to be a . It has ' + 'proven to be sentient and has taken control of our ship. Thus far, all ' + 'efforts at communication have failed...', + 'A warship from the has entered our ' + 'territory. It is currently speeding towards Earth. Thus far, all ' + 'efforts at peace have failed...', + 'The ship has been pulled into a . We are ' + 'observing the universe in the distant . Thus far, all ' + 'efforts to return to our timeline have failed...' +]; + +Map logEntries; +Element logElement; + +void init() { + // initialization + // TODO: Add Quill editor + + logElement = document.getElementById('log'); + logEntries = new Map(); + loadPreviousEntries(); + + // listeners + document.getElementById('save').onClick.listen(saveLog); + document.getElementById('templateSelect') as SelectElement + ..onChange.listen(useTemplate); +} + +/// Capture entry in editor, save to local storage and display in log. +void appendToLog(double stardate, HtmlElement logEntryElement) { + logEntries[stardate] = logEntryElement; + window.localStorage[stardate.toString()] = logEntryElement.innerHtml; + displayLogEntry(stardate, logEntryElement); +} + +/// Calculate the current stardate: . +double calculateStardate() { + var now = new DateTime.now(); + var beginningOfYear = new DateTime(now.year); + int secondsThisYear = now.difference(beginningOfYear).inSeconds; + return now.year + secondsThisYear / _secondsInAYear; +} + +/// Copy html elements from the editor view and return them inside a new +/// DivElement. +HtmlElement captureEditorView() { + Element contentElement = document.getElementById('editor').children.first; + + var logEntryElement = new DivElement()..innerHtml = contentElement.innerHtml; + + return logEntryElement; +} + +/// Update the dom with the provided log entry. +void displayLogEntry(double stardate, HtmlElement logEntryElement) { + if (logElement.children.isNotEmpty) { + logElement.insertAdjacentElement('afterBegin', new HRElement()); + } + + logElement.insertAdjacentElement('afterBegin', logEntryElement); + var stardateElement = new HeadingElement.h2() + ..text = 'Stardate: $stardate' + ..classes.add('stardate'); + logElement.insertAdjacentElement('afterBegin', stardateElement); +} + +/// Load all log entries from browser local storage. +void loadPreviousEntries() { + List keys = window.localStorage.keys.toList(); + keys.sort(); + for (String key in keys) { + var entryElement = new DivElement()..innerHtml = window.localStorage[key]; + logEntries[double.parse(key)] = entryElement; + } + updateDisplay(); +} + +/// Save the log entry that is currently in the editor. +void saveLog(Event _) { + // TODO: Need to save the text from the editor +} + +/// Update the dom to show all current log entries. +void updateDisplay() { + logElement.innerHtml = ''; + List starDates = logEntries.keys.toList(); + starDates.sort(); + for (double starDate in starDates) { + displayLogEntry(starDate, logEntries[starDate]); + } +} + +/// Updates the content of the editor using the selected template. +void useTemplate(Event _) { + SelectElement templateSelectElement = + document.getElementById('templateSelect') as SelectElement; + int selectedIndex = templateSelectElement.selectedIndex; + + if (selectedIndex == 0) return; + + // TODO: Need to clear the editor and insert the template +} diff --git a/dev-workflow/captains_log_base/pubspec.yaml b/dev-workflow/captains_log_base/pubspec.yaml new file mode 100644 index 0000000..cceeda4 --- /dev/null +++ b/dev-workflow/captains_log_base/pubspec.yaml @@ -0,0 +1,13 @@ +name: captains_log +version: 0.0.1 +description: > + A starship captain's log with a WYSIWYG editor. Uses an existing JavaScript + library with the new Dart JS-interop. + +environment: + sdk: '>=1.17.0 <2.0.0' + +dependencies: + func: ^0.1.0 + js: ^0.6.1 + browser: ^0.10.0 diff --git a/dev-workflow/captains_log_base/web/index.html b/dev-workflow/captains_log_base/web/index.html new file mode 100644 index 0000000..6dca7d4 --- /dev/null +++ b/dev-workflow/captains_log_base/web/index.html @@ -0,0 +1,32 @@ + + + + Captain's Log + + + + + + +
+

Captain's Log

+
+
+ +
+ +
+
+
+ + + + diff --git a/dev-workflow/captains_log_base/web/main.dart b/dev-workflow/captains_log_base/web/main.dart new file mode 100644 index 0000000..88f5451 --- /dev/null +++ b/dev-workflow/captains_log_base/web/main.dart @@ -0,0 +1,5 @@ +import 'package:captains_log/captains_log.dart'; + +void main() { + init(); +} \ No newline at end of file diff --git a/dev-workflow/captains_log_base/web/styles.css b/dev-workflow/captains_log_base/web/styles.css new file mode 100644 index 0000000..901432e --- /dev/null +++ b/dev-workflow/captains_log_base/web/styles.css @@ -0,0 +1,107 @@ +body { + padding: 0em; + margin: 0em; +} + +html { + background: #222; + color: white; + font-family: 'Jura', sans-serif; +} + +h1.title { + font-family: 'Orbitron', sans-serif; + font-size: 4em; + margin: 0em; + padding: 0.67em; +} + +h2.stardate { + font-family: 'Bungee Hairline', cursive; +} + +.buttons { + display: flex; + justify-content: space-between; + align-items: center; +} + +select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: #222; + border: none; + color: inherit; + font-size: inherit; + padding: 5px; + padding-right: 18px; +} + +select:focus { + outline: none; +} + +select:active { + background-color: #222; +} + +div.select { + border-bottom: 1px solid gray; + display: inline-block; + height: 100%; + position: relative; +} + +div.select::after { + font-family: 'Material Icons'; + content: '\E5C5'; + position: absolute; + right: 2px; + top: 6px; + pointer-events: none; +} + +button { + background-color: #06c; + color: white; + border-color: #06c; + border-radius: 0.25em; + font-family: inherit; + font-size: 1.1em; + margin-top: .5em; + margin-left: 0.5em; + margin-bottom: 0.5em; + padding: .5em; +} + +#editor .ql-editor.ql-blank::before { + color: white; +} + +.ql-toolbar .ql-stroke { + stroke: white; +} + +.ql-toolbar .ql-fill { + fill: white; +} + +.ql-toolbar.ql-snow .ql-picker-label { + color: white; +} + +#content { + margin-left: 20%; + margin-right: 20%; + padding-left: 20px; + padding-right: 20px; + padding-bottom: 20px; + background: rgba(22, 22, 22, 0.9); + background-clip: padding-box; +} + +#editor { + height: 20em; + font-size: 1.1em; +} diff --git a/dev-workflow/captains_log_final/.analysis_options b/dev-workflow/captains_log_final/.analysis_options new file mode 100644 index 0000000..fb95d07 --- /dev/null +++ b/dev-workflow/captains_log_final/.analysis_options @@ -0,0 +1,21 @@ +# This file allows you to configure the Dart analyzer. +# +# The commented part below is just for inspiration. Read the guide here: +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer + +analyzer: + strong-mode: + implicit-casts: false + implicit-dynamic: false + exclude: + - lib/quill.dart + - .bazelify/** + - bazel-bin/** + - bazel-captains_log_final/** + - bazel-genfiles/** + - bazel-out/** + - bazel-testlogs/** +# linter: +# rules: +# # see catalogue here: http://dart-lang.github.io/linter/lints/ +# - hash_and_equals diff --git a/dev-workflow/captains_log_final/.gitignore b/dev-workflow/captains_log_final/.gitignore new file mode 100644 index 0000000..04d4ee3 --- /dev/null +++ b/dev-workflow/captains_log_final/.gitignore @@ -0,0 +1,22 @@ +pubspec.lock +.buildlog +.packages +.project +.pub/ + +build/ +**/packages/ +web/gen +web/packages + +doc/api/ + +*.iml +*.ipr +*.iws +.idea/ +.DS_Store + +*.dart.js +*.info.json +*.js diff --git a/dev-workflow/captains_log_final/lib/captains_log.dart b/dev-workflow/captains_log_final/lib/captains_log.dart new file mode 100644 index 0000000..37cc4bd --- /dev/null +++ b/dev-workflow/captains_log_final/lib/captains_log.dart @@ -0,0 +1,117 @@ +import 'dart:html'; + +import 'package:captains_log/quill.dart' as quill; + +// ignoring leap years +const int _secondsInAYear = 31536000; +const String _prompt = 'Something happened. Make it sound puzzling and heroic.'; +final List _templates = [ + 'We encountered what appeared to be a . It has ' + 'proven to be sentient and has taken control of our ship. Thus far, all ' + 'efforts at communication have failed...', + 'A warship from the has entered our ' + 'territory. It is currently speeding towards Earth. Thus far, all ' + 'efforts at peace have failed...', + 'The ship has been pulled into a . We are ' + 'observing the universe in the distant . Thus far, all ' + 'efforts to return to our timeline have failed...' +]; + +quill.QuillStatic quillEditor; +Map logEntries; +Element logElement; + +void init() { + // initialization + quillEditor = new quill.QuillStatic('#editor', + new quill.QuillOptionsStatic(theme: 'snow', placeholder: _prompt)); + logElement = document.getElementById('log'); + logEntries = new Map(); + loadPreviousEntries(); + + // listeners + document.getElementById('save').onClick.listen(saveLog); + document.getElementById('templateSelect') as SelectElement + ..onChange.listen(useTemplate); +} + +/// Capture entry in editor, save to local storage and display in log. +void appendToLog(double stardate, HtmlElement logEntryElement) { + logEntries[stardate] = logEntryElement; + window.localStorage[stardate.toString()] = logEntryElement.innerHtml; + displayLogEntry(stardate, logEntryElement); +} + +/// Calculate the current stardate: . +double calculateStardate() { + var now = new DateTime.now(); + var beginningOfYear = new DateTime(now.year); + int secondsThisYear = now.difference(beginningOfYear).inSeconds; + return now.year + secondsThisYear / _secondsInAYear; +} + +/// Copy html elements from the editor view and return them inside a new +/// DivElement. +HtmlElement captureEditorView() { + Element contentElement = document.getElementById('editor').children.first; + + var logEntryElement = new DivElement()..innerHtml = contentElement.innerHtml; + + return logEntryElement; +} + +/// Update the dom with the provided log entry. +void displayLogEntry(double stardate, HtmlElement logEntryElement) { + if (logElement.children.isNotEmpty) { + logElement.insertAdjacentElement('afterBegin', new HRElement()); + } + + logElement.insertAdjacentElement('afterBegin', logEntryElement); + var stardateElement = new HeadingElement.h2() + ..text = 'Stardate: $stardate' + ..classes.add('stardate'); + logElement.insertAdjacentElement('afterBegin', stardateElement); +} + +/// Load all log entries from browser local storage. +void loadPreviousEntries() { + List keys = window.localStorage.keys.toList(); + keys.sort(); + for (String key in keys) { + var entryElement = new DivElement()..innerHtml = window.localStorage[key]; + logEntries[double.parse(key)] = entryElement; + } + updateDisplay(); +} + +/// Save the log entry that is currently in the editor. +void saveLog(Event _) { + HtmlElement logEntryElement = captureEditorView(); + appendToLog(calculateStardate(), logEntryElement); + + // Clear the editor. + quillEditor.deleteText(0, quillEditor.getLength()); +} + +/// Update the dom to show all current log entries. +void updateDisplay() { + logElement.innerHtml = ''; + List starDates = logEntries.keys.toList(); + starDates.sort(); + for (double starDate in starDates) { + displayLogEntry(starDate, logEntries[starDate]); + } +} + +/// Updates the content of the editor using the selected template. +void useTemplate(Event _) { + SelectElement templateSelectElement = + document.getElementById('templateSelect') as SelectElement; + int selectedIndex = templateSelectElement.selectedIndex; + + if (selectedIndex == 0) return; + + quillEditor.deleteText(0, quillEditor.getLength()); + String templateText = _templates[templateSelectElement.selectedIndex - 1]; + quillEditor.insertText(0, templateText, 'api'); +} diff --git a/dev-workflow/captains_log_final/lib/quill.dart b/dev-workflow/captains_log_final/lib/quill.dart new file mode 100644 index 0000000..4e36c3d --- /dev/null +++ b/dev-workflow/captains_log_final/lib/quill.dart @@ -0,0 +1,175 @@ +@JS() +library quill; + +import "package:js/js.dart"; +import "dart:html" show Element; +import "package:func/func.dart"; + +/// Type definitions for Quill v1.0.3 +/// Project: http://quilljs.com +/// Definitions by: Sumit +/// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// Module QuillJS +@anonymous +@JS() +abstract class QuillOptionsStatic { + external String get debug; + external set debug(String v); + external dynamic /*JSMap of */ get modules; + external set modules(dynamic /*JSMap of */ v); + external String get placeholder; + external set placeholder(String v); + external bool get readOnly; + external set readOnly(bool v); + external String get theme; + external set theme(String v); + external factory QuillOptionsStatic( + {String debug, + dynamic /*JSMap of */ modules, + String placeholder, + bool readOnly, + String theme}); +} + +@anonymous +@JS() +abstract class BoundsStatic { + external num get left; + external set left(num v); + external num get top; + external set top(num v); + external num get height; + external set height(num v); + external num get width; + external set width(num v); + external factory BoundsStatic({num left, num top, num height, num width}); +} + +@anonymous +@JS() +abstract class DeltaStatic { + external List get ops; + external set ops(List v); + external dynamic get retain; + external set retain(dynamic v); + external dynamic get delete; + external set delete(dynamic v); + external dynamic get insert; + external set insert(dynamic v); + external dynamic get attributes; + external set attributes(dynamic v); + external factory DeltaStatic( + {List ops, + dynamic retain, + dynamic delete, + dynamic insert, + dynamic attributes}); +} + +@anonymous +@JS() +abstract class RangeStatic { + // Constructors on anonymous interfaces are not yet supported. + /*external factory RangeStatic();*/ + external num get index; + external set index(num v); + external num get length; + external set length(num v); +} + +/*type sourceType = "api" | "user" | "silent";*/ +@anonymous +@JS() +abstract class formatsType { + /* Index signature is not yet supported by JavaScript interop. */ +} + +@JS("Quill") +abstract class QuillStatic { + external factory QuillStatic(dynamic /*String|Element*/ container, + [QuillOptionsStatic options]); + external void deleteText(num start, num end, + [String /*'api'|'user'|'silent'*/ source]); + external void disable(); + external void enable([bool enabled]); + external DeltaStatic getContents([num start, num end]); + external num getLength(); + external String getText([num start, num end]); + external void insertEmbed(num index, String type, String url, + [String /*'api'|'user'|'silent'*/ source]); + /*external void insertText(num index, String text, ['api'|'user'|'silent' source]);*/ + /*external void insertText(num index, String text, String format, String value, ['api'|'user'|'silent' source]);*/ + /*external void insertText(num index, String text, formatsType formats, ['api'|'user'|'silent' source]);*/ + external void insertText(num index, String text, + [String /*'api'|'user'|'silent'|String*/ source_format_formats, + String /*String|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external String pasteHTML(num index, String html, ['api'|'user'|'silent' source]);*/ + /*external String pasteHTML(String html, ['api'|'user'|'silent' source]);*/ + external String pasteHTML(dynamic /*num|String*/ index_html, + [String /*String|'api'|'user'|'silent'*/ html_source, + String /*'api'|'user'|'silent'*/ source]); + external void setContents(DeltaStatic delta, + [String /*'api'|'user'|'silent'*/ source]); + external void setText(String text, [String /*'api'|'user'|'silent'*/ source]); + external void update([String source]); + external void updateContents(DeltaStatic delta, + [String /*'api'|'user'|'silent'*/ source]); + external void format(String name, dynamic value, + [String /*'api'|'user'|'silent'*/ source]); + /*external void formatLine(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void formatLine(num index, num length, String format, dynamic value, ['api'|'user'|'silent' source]);*/ + /*external void formatLine(num index, num length, formatsType formats, ['api'|'user'|'silent' source]);*/ + external void formatLine(num index, num length, + [String /*'api'|'user'|'silent'|String*/ source_format_formats, + dynamic /*dynamic|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external void formatText(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void formatText(num index, num length, String format, dynamic value, ['api'|'user'|'silent' source]);*/ + /*external void formatText(num index, num length, formatsType formats, ['api'|'user'|'silent' source]);*/ + external void formatText(num index, num length, + [String /*'api'|'user'|'silent'|String*/ source_format_formats, + dynamic /*dynamic|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external formatsType getFormat([RangeStatic range]);*/ + /*external formatsType getFormat(num index, [num length]);*/ + external getFormat([dynamic /*RangeStatic|num*/ range_index, num length]); + external void removeFormat(num index, num length, + [String /*'api'|'user'|'silent'*/ source]); + external void blur(); + external void focus(); + external BoundsStatic getBounds(num index, [num length]); + external RangeStatic getSelection([bool focus]); + external bool hasFocus(); + /*external void setSelection(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void setSelection(RangeStatic range, ['api'|'user'|'silent' source]);*/ + external void setSelection(dynamic /*num|RangeStatic*/ index_range, + [dynamic /*num|'api'|'user'|'silent'*/ length_source, + String /*'api'|'user'|'silent'*/ source]); + external QuillStatic on(String eventName, + dynamic /*VoidFunc3|(name: string, ...args: any[]) => void*/ callback); + external QuillStatic once( + String eventName, void callback(DeltaStatic delta, String source)); + external QuillStatic off( + String eventName, void callback(DeltaStatic delta, String source)); + external void debug(String level); + external dynamic JS$import(String path); + /*external void register(String path, dynamic def, [bool suppressWarning]);*/ + /*external void register(formatsType defs, [bool suppressWarning]);*/ + external void register(String path_defs, + [dynamic /*dynamic|bool*/ def_suppressWarning, bool suppressWarning]); + external dynamic addContainer(String className, [dynamic refNode]); + external dynamic getModule(String name); +} + +// End module QuillJS +@JS() +external QuillStatic get Quill; +@JS() +external set Quill(QuillStatic v); +// Module quill +/* WARNING: export assignment not yet supported. */ + +// End module quill + diff --git a/dev-workflow/captains_log_final/pubspec.yaml b/dev-workflow/captains_log_final/pubspec.yaml new file mode 100644 index 0000000..cceeda4 --- /dev/null +++ b/dev-workflow/captains_log_final/pubspec.yaml @@ -0,0 +1,13 @@ +name: captains_log +version: 0.0.1 +description: > + A starship captain's log with a WYSIWYG editor. Uses an existing JavaScript + library with the new Dart JS-interop. + +environment: + sdk: '>=1.17.0 <2.0.0' + +dependencies: + func: ^0.1.0 + js: ^0.6.1 + browser: ^0.10.0 diff --git a/dev-workflow/captains_log_final/web/index.html b/dev-workflow/captains_log_final/web/index.html new file mode 100644 index 0000000..a2770c4 --- /dev/null +++ b/dev-workflow/captains_log_final/web/index.html @@ -0,0 +1,35 @@ + + + + Captain's Log + + + + + + + +
+

Captain's Log

+
+
+
+ +
+ +
+
+
+ + + + + diff --git a/dev-workflow/captains_log_final/web/main.dart b/dev-workflow/captains_log_final/web/main.dart new file mode 100644 index 0000000..88f5451 --- /dev/null +++ b/dev-workflow/captains_log_final/web/main.dart @@ -0,0 +1,5 @@ +import 'package:captains_log/captains_log.dart'; + +void main() { + init(); +} \ No newline at end of file diff --git a/dev-workflow/captains_log_final/web/styles.css b/dev-workflow/captains_log_final/web/styles.css new file mode 100644 index 0000000..59cda9b --- /dev/null +++ b/dev-workflow/captains_log_final/web/styles.css @@ -0,0 +1,108 @@ +body { + background: url(https://cdn.spacetelescope.org/archives/images/wallpaper2/heic0601a.jpg) no-repeat center center fixed; + background-size: cover; + padding: 0em; + margin: 0em; +} + +html { + color: white; + font-family: 'Jura', sans-serif; +} + +h1.title { + font-family: 'Orbitron', sans-serif; + font-size: 4em; + margin: 0em; + padding: 0.67em; +} + +h2.stardate { + font-family: 'Bungee Hairline', cursive; +} + +.buttons { + display: flex; + justify-content: space-between; + align-items: center; +} + +select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: #222; + border: none; + color: inherit; + font-size: inherit; + padding: 5px; + padding-right: 18px; +} + +select:focus { + outline: none; +} + +select:active { + background-color: #222; +} + +div.select { + border-bottom: 1px solid gray; + display: inline-block; + height: 100%; + position: relative; +} + +div.select::after { + font-family: 'Material Icons'; + content: '\E5C5'; + position: absolute; + right: 2px; + top: 6px; + pointer-events: none; +} + +button { + background-color: #06c; + color: white; + border-color: #06c; + border-radius: 0.25em; + font-family: inherit; + font-size: 1.1em; + margin-top: .5em; + margin-left: 0.5em; + margin-bottom: 0.5em; + padding: .5em; +} + +#editor .ql-editor.ql-blank::before { + color: white; +} + +.ql-toolbar .ql-stroke { + stroke: white; +} + +.ql-toolbar .ql-fill { + fill: white; +} + +.ql-toolbar.ql-snow .ql-picker-label { + color: white; +} + +#content { + margin-left: 20%; + margin-right: 20%; + padding-left: 20px; + padding-right: 20px; + padding-bottom: 20px; + background: rgba(22, 22, 22, 0.9); + background-clip: padding-box; +} + +#editor { + height: 20em; + font-size: 1.1em; +} diff --git a/dev-workflow/captains_log_working/.analysis_options b/dev-workflow/captains_log_working/.analysis_options new file mode 100644 index 0000000..c290149 --- /dev/null +++ b/dev-workflow/captains_log_working/.analysis_options @@ -0,0 +1,20 @@ +# This file allows you to configure the Dart analyzer. +# +# The commented part below is just for inspiration. Read the guide here: +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer + +analyzer: +# strong-mode: +# implicit-casts: false +# implicit-dynamic: false + exclude: + - .bazelify/** + - bazel-bin/** + - bazel-captains_log_final/** + - bazel-genfiles/** + - bazel-out/** + - bazel-testlogs/** +# linter: +# rules: +# # see catalogue here: http://dart-lang.github.io/linter/lints/ +# - hash_and_equals diff --git a/dev-workflow/captains_log_working/.gitignore b/dev-workflow/captains_log_working/.gitignore new file mode 100644 index 0000000..04d4ee3 --- /dev/null +++ b/dev-workflow/captains_log_working/.gitignore @@ -0,0 +1,22 @@ +pubspec.lock +.buildlog +.packages +.project +.pub/ + +build/ +**/packages/ +web/gen +web/packages + +doc/api/ + +*.iml +*.ipr +*.iws +.idea/ +.DS_Store + +*.dart.js +*.info.json +*.js diff --git a/dev-workflow/captains_log_working/lib/captains_log.dart b/dev-workflow/captains_log_working/lib/captains_log.dart new file mode 100644 index 0000000..6b1da67 --- /dev/null +++ b/dev-workflow/captains_log_working/lib/captains_log.dart @@ -0,0 +1,109 @@ +import 'dart:html'; +// TODO: Add import + +// ignoring leap years +const int _secondsInAYear = 31536000; +const String _prompt = 'Something happened. Make it sound puzzling and heroic.'; +final List _templates = [ + 'We encountered what appeared to be a . It has ' + 'proven to be sentient and has taken control of our ship. Thus far, all ' + 'efforts at communication have failed...', + 'A warship from the has entered our ' + 'territory. It is currently speeding towards Earth. Thus far, all ' + 'efforts at peace have failed...', + 'The ship has been pulled into a . We are ' + 'observing the universe in the distant . Thus far, all ' + 'efforts to return to our timeline have failed...' +]; + +Map logEntries; +Element logElement; + +void init() { + // initialization + // TODO: Add Quill editor + + logElement = document.getElementById('log'); + logEntries = new Map(); + loadPreviousEntries(); + + // listeners + document.getElementById('save').onClick.listen(saveLog); + document.getElementById('templateSelect') as SelectElement + ..onChange.listen(useTemplate); +} + +/// Capture entry in editor, save to local storage and display in log. +void appendToLog(double stardate, HtmlElement logEntryElement) { + logEntries[stardate] = logEntryElement; + window.localStorage[stardate.toString()] = logEntryElement.innerHtml; + displayLogEntry(stardate, logEntryElement); +} + +/// Calculate the current stardate: . +double calculateStardate() { + var now = new DateTime.now(); + var beginningOfYear = new DateTime(now.year); + int secondsThisYear = now.difference(beginningOfYear).inSeconds; + return now.year + secondsThisYear / _secondsInAYear; +} + +/// Copy html elements from the editor view and return them inside a new +/// DivElement. +HtmlElement captureEditorView() { + Element contentElement = document.getElementById('editor').children.first; + + var logEntryElement = new DivElement()..innerHtml = contentElement.innerHtml; + + return logEntryElement; +} + +/// Update the dom with the provided log entry. +void displayLogEntry(double stardate, HtmlElement logEntryElement) { + if (logElement.children.isNotEmpty) { + logElement.insertAdjacentElement('afterBegin', new HRElement()); + } + + logElement.insertAdjacentElement('afterBegin', logEntryElement); + var stardateElement = new HeadingElement.h2() + ..text = 'Stardate: $stardate' + ..classes.add('stardate'); + logElement.insertAdjacentElement('afterBegin', stardateElement); +} + +/// Load all log entries from browser local storage. +void loadPreviousEntries() { + List keys = window.localStorage.keys.toList(); + keys.sort(); + for (String key in keys) { + var entryElement = new DivElement()..innerHtml = window.localStorage[key]; + logEntries[double.parse(key)] = entryElement; + } + updateDisplay(); +} + +/// Save the log entry that is currently in the editor. +void saveLog(Event _) { + // TODO: Need to save the text from the editor +} + +/// Update the dom to show all current log entries. +void updateDisplay() { + logElement.innerHtml = ''; + List starDates = logEntries.keys.toList(); + starDates.sort(); + for (double starDate in starDates) { + displayLogEntry(starDate, logEntries[starDate]); + } +} + +/// Updates the content of the editor using the selected template. +void useTemplate(Event _) { + SelectElement templateSelectElement = + document.getElementById('templateSelect') as SelectElement; + int selectedIndex = templateSelectElement.selectedIndex; + + if (selectedIndex == 0) return; + + // TODO: Need to clear the editor and insert the template +} diff --git a/dev-workflow/captains_log_working/pubspec.yaml b/dev-workflow/captains_log_working/pubspec.yaml new file mode 100644 index 0000000..cceeda4 --- /dev/null +++ b/dev-workflow/captains_log_working/pubspec.yaml @@ -0,0 +1,13 @@ +name: captains_log +version: 0.0.1 +description: > + A starship captain's log with a WYSIWYG editor. Uses an existing JavaScript + library with the new Dart JS-interop. + +environment: + sdk: '>=1.17.0 <2.0.0' + +dependencies: + func: ^0.1.0 + js: ^0.6.1 + browser: ^0.10.0 diff --git a/dev-workflow/captains_log_working/web/index.html b/dev-workflow/captains_log_working/web/index.html new file mode 100644 index 0000000..6dca7d4 --- /dev/null +++ b/dev-workflow/captains_log_working/web/index.html @@ -0,0 +1,32 @@ + + + + Captain's Log + + + + + + +
+

Captain's Log

+
+
+ +
+ +
+
+
+ + + + diff --git a/dev-workflow/captains_log_working/web/main.dart b/dev-workflow/captains_log_working/web/main.dart new file mode 100644 index 0000000..88f5451 --- /dev/null +++ b/dev-workflow/captains_log_working/web/main.dart @@ -0,0 +1,5 @@ +import 'package:captains_log/captains_log.dart'; + +void main() { + init(); +} \ No newline at end of file diff --git a/dev-workflow/captains_log_working/web/styles.css b/dev-workflow/captains_log_working/web/styles.css new file mode 100644 index 0000000..901432e --- /dev/null +++ b/dev-workflow/captains_log_working/web/styles.css @@ -0,0 +1,107 @@ +body { + padding: 0em; + margin: 0em; +} + +html { + background: #222; + color: white; + font-family: 'Jura', sans-serif; +} + +h1.title { + font-family: 'Orbitron', sans-serif; + font-size: 4em; + margin: 0em; + padding: 0.67em; +} + +h2.stardate { + font-family: 'Bungee Hairline', cursive; +} + +.buttons { + display: flex; + justify-content: space-between; + align-items: center; +} + +select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: #222; + border: none; + color: inherit; + font-size: inherit; + padding: 5px; + padding-right: 18px; +} + +select:focus { + outline: none; +} + +select:active { + background-color: #222; +} + +div.select { + border-bottom: 1px solid gray; + display: inline-block; + height: 100%; + position: relative; +} + +div.select::after { + font-family: 'Material Icons'; + content: '\E5C5'; + position: absolute; + right: 2px; + top: 6px; + pointer-events: none; +} + +button { + background-color: #06c; + color: white; + border-color: #06c; + border-radius: 0.25em; + font-family: inherit; + font-size: 1.1em; + margin-top: .5em; + margin-left: 0.5em; + margin-bottom: 0.5em; + padding: .5em; +} + +#editor .ql-editor.ql-blank::before { + color: white; +} + +.ql-toolbar .ql-stroke { + stroke: white; +} + +.ql-toolbar .ql-fill { + fill: white; +} + +.ql-toolbar.ql-snow .ql-picker-label { + color: white; +} + +#content { + margin-left: 20%; + margin-right: 20%; + padding-left: 20px; + padding-right: 20px; + padding-bottom: 20px; + background: rgba(22, 22, 22, 0.9); + background-clip: padding-box; +} + +#editor { + height: 20em; + font-size: 1.1em; +} diff --git a/dev-workflow/webpage/.analysis_options b/dev-workflow/webpage/.analysis_options new file mode 100644 index 0000000..6237a10 --- /dev/null +++ b/dev-workflow/webpage/.analysis_options @@ -0,0 +1,14 @@ +# This file allows you to configure the Dart analyzer. +# +# The commented part below is just for inspiration. Read the guide here: +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer + + analyzer: + strong-mode: true + exclude: + - web/quill.dart +# linter: +# rules: +# # see catalogue here: http://dart-lang.github.io/linter/lints/ +# - hash_and_equals + diff --git a/dev-workflow/webpage/.gitignore b/dev-workflow/webpage/.gitignore new file mode 100644 index 0000000..04d4ee3 --- /dev/null +++ b/dev-workflow/webpage/.gitignore @@ -0,0 +1,22 @@ +pubspec.lock +.buildlog +.packages +.project +.pub/ + +build/ +**/packages/ +web/gen +web/packages + +doc/api/ + +*.iml +*.ipr +*.iws +.idea/ +.DS_Store + +*.dart.js +*.info.json +*.js diff --git a/dev-workflow/webpage/pubspec.yaml b/dev-workflow/webpage/pubspec.yaml new file mode 100644 index 0000000..2ff75a3 --- /dev/null +++ b/dev-workflow/webpage/pubspec.yaml @@ -0,0 +1,15 @@ +name: captains_log +version: 0.0.1 +description: > + A starship captain's log with a WYSIWYG editor. Uses an existing JavaScript + library with the new Dart JS-interop. + +environment: + sdk: '>=1.17.0 <2.0.0' + +dependencies: + func: ^0.1.0 + js: ^0.6.1 + browser: ^0.10.0 + html: ^0.13.0 + dart_to_js_script_rewriter: ^1.0.1 diff --git a/dev-workflow/webpage/web/fonts.css b/dev-workflow/webpage/web/fonts.css new file mode 100644 index 0000000..404c29a --- /dev/null +++ b/dev-workflow/webpage/web/fonts.css @@ -0,0 +1,95 @@ +/* vietnamese */ +@font-face { + font-family: 'Bungee Hairline'; + font-style: normal; + font-weight: 400; + src: local('Bungee Hairline'), local('BungeeHairline-Regular'), url(https://fonts.gstatic.com/s/bungeehairline/v2/8Li3dr3whdkxuk7pmLaZaVT_xyho_HQDwuvp8oi4gGs.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Bungee Hairline'; + font-style: normal; + font-weight: 400; + src: local('Bungee Hairline'), local('BungeeHairline-Regular'), url(https://fonts.gstatic.com/s/bungeehairline/v2/8Li3dr3whdkxuk7pmLaZae5Tv6dvitgoLnEdohVtlEc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Bungee Hairline'; + font-style: normal; + font-weight: 400; + src: local('Bungee Hairline'), local('BungeeHairline-Regular'), url(https://fonts.gstatic.com/s/bungeehairline/v2/8Li3dr3whdkxuk7pmLaZaZ16wW5UEL6hOOm3lnIQ28I.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Jura'; + font-style: normal; + font-weight: 400; + src: local('Jura Regular'), local('Jura-Regular'), url(https://fonts.gstatic.com/s/jura/v7/peeOujaUvaongbCNNZf9vhTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Jura'; + font-style: normal; + font-weight: 400; + src: local('Jura Regular'), local('Jura-Regular'), url(https://fonts.gstatic.com/s/jura/v7/3RhRLLA8iUiXvCRJ3yKaoRTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Jura'; + font-style: normal; + font-weight: 400; + src: local('Jura Regular'), local('Jura-Regular'), url(https://fonts.gstatic.com/s/jura/v7/o9ZdJ9iClqel-A7qj79PTxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* latin-ext */ +@font-face { + font-family: 'Jura'; + font-style: normal; + font-weight: 400; + src: local('Jura Regular'), local('Jura-Regular'), url(https://fonts.gstatic.com/s/jura/v7/37n9C5gDFvS63oS93z1vXxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Jura'; + font-style: normal; + font-weight: 400; + src: local('Jura Regular'), local('Jura-Regular'), url(https://fonts.gstatic.com/s/jura/v7/tz5D0xJo5Gt86C-ZjNRkTfesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* fallback */ +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: local('Material Icons'), local('MaterialIcons-Regular'), url(https://fonts.gstatic.com/s/materialicons/v18/2fcrYFNaTjcS6g4U3t-Y5UEw0lE80llgEseQY3FEmqw.woff2) format('woff2'); +} +/* latin */ +@font-face { + font-family: 'Orbitron'; + font-style: normal; + font-weight: 400; + src: local('Orbitron-Light'), local('Orbitron-Regular'), url(https://fonts.gstatic.com/s/orbitron/v7/HmnHiRzvcnQr8CjBje6GQnYhjbSpvc47ee6xR_80Hnw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; +} diff --git a/dev-workflow/webpage/web/index.html b/dev-workflow/webpage/web/index.html new file mode 100644 index 0000000..dadabe7 --- /dev/null +++ b/dev-workflow/webpage/web/index.html @@ -0,0 +1,35 @@ + + + + Captain's Log + + + + + + + +
+

Captain's Log

+
+
+
+ +
+ +
+
+
+ + + + + diff --git a/dev-workflow/webpage/web/main.dart b/dev-workflow/webpage/web/main.dart new file mode 100644 index 0000000..b24d88e --- /dev/null +++ b/dev-workflow/webpage/web/main.dart @@ -0,0 +1,117 @@ +import 'dart:html'; + +import 'quill.dart' as quill; + +// ignoring leap years +const int _secondsInAYear = 31536000; +const String _prompt = 'Something happened. Make it sound puzzling and heroic.'; +final List _templates = [ + 'We encountered what appeared to be a . It has ' + 'proven to be sentient and has taken control of our ship. Thus far, all ' + 'efforts at communication have failed...', + 'A warship from the has entered our ' + 'territory. It is currently speeding towards Earth. Thus far, all ' + 'efforts at peace have failed...', + 'The ship has been pulled into a . We are ' + 'observing the universe in the distant . Thus far, all ' + 'efforts to return to our timeline have failed...' +]; + +quill.QuillStatic quillEditor; +Map logEntries; +HtmlElement logElement; + +main() { + // initialization + quillEditor = new quill.QuillStatic('#editor', + new quill.QuillOptionsStatic(theme: 'snow', placeholder: _prompt)); + logElement = document.getElementById('log'); + logEntries = new Map(); + loadPreviousEntries(); + + // listeners + document.getElementById('save').onClick.listen(saveLog); + document.getElementById('templateSelect') as SelectElement + ..onChange.listen(useTemplate); +} + +/// Capture entry in editor, save to local storage and display in log. +void appendToLog(double stardate, HtmlElement logEntryElement) { + logEntries[stardate] = logEntryElement; + window.localStorage[stardate.toString()] = logEntryElement.innerHtml; + displayLogEntry(stardate, logEntryElement); +} + +/// Calculate the current stardate: . +double calculateStardate() { + var now = new DateTime.now(); + var beginningOfYear = new DateTime(now.year); + int secondsThisYear = now.difference(beginningOfYear).inSeconds; + return now.year + secondsThisYear / _secondsInAYear; +} + +/// Copy html elements from the editor view and return them inside a new +/// DivElement. +HtmlElement captureEditorView() { + Element contentElement = document.getElementById('editor').firstChild; + + var logEntryElement = new DivElement()..innerHtml = contentElement.innerHtml; + + return logEntryElement; +} + +/// Update the dom with the provided log entry. +void displayLogEntry(double stardate, HtmlElement logEntryElement) { + if (logElement.children.isNotEmpty) { + logElement.insertAdjacentElement('afterBegin', new HRElement()); + } + + logElement.insertAdjacentElement('afterBegin', logEntryElement); + var stardateElement = new HeadingElement.h2() + ..text = 'Stardate: $stardate' + ..classes.add('stardate'); + logElement.insertAdjacentElement('afterBegin', stardateElement); +} + +/// Load all log entries from browser local storage. +void loadPreviousEntries() { + List keys = window.localStorage.keys.toList(); + keys.sort(); + for (String key in keys) { + var entryElement = new DivElement()..innerHtml = window.localStorage[key]; + logEntries[double.parse(key)] = entryElement; + } + updateDisplay(); +} + +/// Save the log entry that is currently in the editor. +void saveLog(Event _) { + DivElement logEntryElement = captureEditorView(); + appendToLog(calculateStardate(), logEntryElement); + + // Clear the editor. + quillEditor.deleteText(0, quillEditor.getLength()); +} + +/// Update the dom to show all current log entries. +void updateDisplay() { + logElement.innerHtml = ''; + List starDates = logEntries.keys.toList(); + starDates.sort(); + for (double starDate in starDates) { + displayLogEntry(starDate, logEntries[starDate]); + } +} + +/// Updates the content of the editor using the selected template. +void useTemplate(Event _) { + SelectElement templateSelectElement = + document.getElementById('templateSelect'); + int selectedIndex = templateSelectElement.selectedIndex; + + if (selectedIndex == 0) return; + + quillEditor.deleteText(0, quillEditor.getLength()); + String templateText = _templates[templateSelectElement.selectedIndex - 1]; + quillEditor.insertText(0, templateText, 'api'); +} diff --git a/dev-workflow/webpage/web/quill.dart b/dev-workflow/webpage/web/quill.dart new file mode 100644 index 0000000..c0c6dcc --- /dev/null +++ b/dev-workflow/webpage/web/quill.dart @@ -0,0 +1,168 @@ +// This version is autogenerated and contains some other small polish tweaks. For example see +// how String /*'api'|'user'|'silent'*/ source is handled. + +@JS() +library quill; + +import "package:js/js.dart"; +import "package:func/func.dart"; + +/// Type definitions for Quill v1.0.3 +/// Project: http://quilljs.com +/// Definitions by: Sumit +/// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// Module QuillJS +@anonymous +@JS() +abstract class QuillOptionsStatic { + external String get debug; + external set debug(String v); + external dynamic /*JSMap of */ get modules; + external set modules(dynamic /*JSMap of */ v); + external String get placeholder; + external set placeholder(String v); + external bool get readOnly; + external set readOnly(bool v); + external String get theme; + external set theme(String v); + external factory QuillOptionsStatic( + {String debug, + dynamic /*JSMap of */ modules, + String placeholder, + bool readOnly, + String theme}); +} + +@anonymous +@JS() +abstract class BoundsStatic { + external num get left; + external set left(num v); + external num get top; + external set top(num v); + external num get height; + external set height(num v); + external num get width; + external set width(num v); + external factory BoundsStatic({num left, num top, num height, num width}); +} + +@anonymous +@JS() +abstract class DeltaStatic { + external List get ops; + external set ops(List v); + external dynamic get retain; + external set retain(dynamic v); + external dynamic get delete; + external set delete(dynamic v); + external dynamic get insert; + external set insert(dynamic v); + external dynamic get attributes; + external set attributes(dynamic v); + external factory DeltaStatic( + {List ops, + dynamic retain, + dynamic delete, + dynamic insert, + dynamic attributes}); +} + +@anonymous +@JS() +abstract class RangeStatic { + external factory RangeStatic(); + external num get index; + external set index(num v); + external num get length; + external set length(num v); +} + +@JS("Quill") +abstract class QuillStatic { + external factory QuillStatic(String selector, [QuillOptionsStatic options]); + external void deleteText(num start, num end, + [String /*'api'|'user'|'silent'*/ source]); + external void disable(); + external void enable([bool enabled]); + external DeltaStatic getContents([num start, num end]); + external num getLength(); + external String getText([num start, num end]); + external void insertEmbed(num index, String type, String url, + [String /*'api'|'user'|'silent'*/ source]); + /*external void insertText(num index, String text, ['api'|'user'|'silent' source]);*/ + /*external void insertText(num index, String text, String format, String value, ['api'|'user'|'silent' source]);*/ + /*external void insertText(num index, String text, JSMap of formats, ['api'|'user'|'silent' source]);*/ + external void insertText(num index, String text, + [dynamic /*'api'|'user'|'silent'|String|JSMap of */ source_format_formats, + String /*String|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external String pasteHTML(num index, String html, ['api'|'user'|'silent' source]);*/ + /*external String pasteHTML(String html, ['api'|'user'|'silent' source]);*/ + external String pasteHTML(dynamic /*num|String*/ index_html, + [String /*String|'api'|'user'|'silent'*/ html_source, + String /*'api'|'user'|'silent'*/ source]); + external void setContents(DeltaStatic delta, + [String /*'api'|'user'|'silent'*/ source]); + external void setText(String text, [String /*'api'|'user'|'silent'*/ source]); + external void update([String source]); + external void updateContents(DeltaStatic delta, + [String /*'api'|'user'|'silent'*/ source]); + external void format(String name, dynamic value, + [String /*'api'|'user'|'silent'*/ source]); + /*external void formatLine(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void formatLine(num index, num length, String format, dynamic value, ['api'|'user'|'silent' source]);*/ + /*external void formatLine(num index, num length, JSMap of formats, ['api'|'user'|'silent' source]);*/ + external void formatLine(num index, num length, + [dynamic /*'api'|'user'|'silent'|String|JSMap of */ source_format_formats, + dynamic /*dynamic|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external void formatText(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void formatText(num index, num length, String format, dynamic value, ['api'|'user'|'silent' source]);*/ + /*external void formatText(num index, num length, JSMap of formats, ['api'|'user'|'silent' source]);*/ + external void formatText(num index, num length, + [dynamic /*'api'|'user'|'silent'|String|JSMap of */ source_format_formats, + dynamic /*dynamic|'api'|'user'|'silent'*/ value_source, + String /*'api'|'user'|'silent'*/ source]); + /*external JSMap of getFormat([RangeStatic range]);*/ + /*external JSMap of getFormat(num index, [num length]);*/ + external dynamic /*JSMap of */ getFormat( + [dynamic /*RangeStatic|num*/ range_index, num length]); + external void removeFormat(num index, num length, + [String /*'api'|'user'|'silent'*/ source]); + external void blur(); + external void focus(); + external BoundsStatic getBounds(num index, [num length]); + external RangeStatic getSelection([bool focus]); + external bool hasFocus(); + /*external void setSelection(num index, num length, ['api'|'user'|'silent' source]);*/ + /*external void setSelection(RangeStatic range, ['api'|'user'|'silent' source]);*/ + external void setSelection(dynamic /*num|RangeStatic*/ index_range, + [dynamic /*num|'api'|'user'|'silent'*/ length_source, + String /*'api'|'user'|'silent'*/ source]); + external QuillStatic on(String eventName, + dynamic /*VoidFunc3|(name: string, ...args: any[]) => void*/ callback); + external QuillStatic once( + String eventName, void callback(DeltaStatic delta, String source)); + external QuillStatic off( + String eventName, void callback(DeltaStatic delta, String source)); + external void debug(String level); + external dynamic JS$import(String path); + /*external void register(String path, dynamic def, [bool suppressWarning]);*/ + /*external void register(JSMap of defs, [bool suppressWarning]);*/ + external void register(dynamic /*String|JSMap of */ path_defs, + [dynamic /*dynamic|bool*/ def_suppressWarning, bool suppressWarning]); + external dynamic addContainer(String className, [dynamic refNode]); + external dynamic getModule(String name); +} + +// End module QuillJS +@JS("Quill") +external QuillStatic get Quill; +@JS("Quill") +external set Quill(QuillStatic v); +// Module Quill +/* WARNING: export assignment not yet supported. */ + +// End module Quill \ No newline at end of file diff --git a/dev-workflow/webpage/web/quill.snow.css b/dev-workflow/webpage/web/quill.snow.css new file mode 100644 index 0000000..efc002b --- /dev/null +++ b/dev-workflow/webpage/web/quill.snow.css @@ -0,0 +1,883 @@ +/*! + * Quill Editor v1.0.4 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */ +.ql-container { + box-sizing: border-box; + font-family: Helvetica, Arial, sans-serif; + font-size: 13px; + height: 100%; + margin: 0px; + position: relative; +} +.ql-clipboard { + left: -100000px; + height: 1px; + overflow-y: hidden; + position: absolute; + top: 50%; +} +.ql-clipboard p { + margin: 0; + padding: 0; +} +.ql-editor { + box-sizing: border-box; + cursor: text; + line-height: 1.42; + height: 100%; + outline: none; + overflow-y: auto; + padding: 12px 15px; + tab-size: 4; + -moz-tab-size: 4; + text-align: left; + white-space: pre-wrap; + word-wrap: break-word; +} +.ql-editor p, +.ql-editor ol, +.ql-editor ul, +.ql-editor pre, +.ql-editor blockquote, +.ql-editor h1, +.ql-editor h2, +.ql-editor h3, +.ql-editor h4, +.ql-editor h5, +.ql-editor h6 { + margin: 0; + padding: 0; + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol, +.ql-editor ul { + padding-left: 1.5em; +} +.ql-editor ol > li, +.ql-editor ul > li { + list-style-type: none; +} +.ql-editor ul > li::before { + content: '\25CF'; +} +.ql-editor li::before { + display: inline-block; + margin-right: 0.3em; + text-align: right; + white-space: nowrap; + width: 1.2em; +} +.ql-editor li:not(.ql-direction-rtl)::before { + margin-left: -1.5em; +} +.ql-editor ol li, +.ql-editor ul li { + padding-left: 1.5em; +} +.ql-editor ol li { + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + counter-increment: list-num; +} +.ql-editor ol li:before { + content: counter(list-num, decimal) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-increment: list-1; +} +.ql-editor ol li.ql-indent-1:before { + content: counter(list-1, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-2 { + counter-increment: list-2; +} +.ql-editor ol li.ql-indent-2:before { + content: counter(list-2, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-2 { + counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-3 { + counter-increment: list-3; +} +.ql-editor ol li.ql-indent-3:before { + content: counter(list-3, decimal) '. '; +} +.ql-editor ol li.ql-indent-3 { + counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-4 { + counter-increment: list-4; +} +.ql-editor ol li.ql-indent-4:before { + content: counter(list-4, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-4 { + counter-reset: list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-5 { + counter-increment: list-5; +} +.ql-editor ol li.ql-indent-5:before { + content: counter(list-5, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-5 { + counter-reset: list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-6 { + counter-increment: list-6; +} +.ql-editor ol li.ql-indent-6:before { + content: counter(list-6, decimal) '. '; +} +.ql-editor ol li.ql-indent-6 { + counter-reset: list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-7 { + counter-increment: list-7; +} +.ql-editor ol li.ql-indent-7:before { + content: counter(list-7, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-7 { + counter-reset: list-8 list-9; +} +.ql-editor ol li.ql-indent-8 { + counter-increment: list-8; +} +.ql-editor ol li.ql-indent-8:before { + content: counter(list-8, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-8 { + counter-reset: list-9; +} +.ql-editor ol li.ql-indent-9 { + counter-increment: list-9; +} +.ql-editor ol li.ql-indent-9:before { + content: counter(list-9, decimal) '. '; +} +.ql-editor .ql-indent-1:not(.ql-direction-rtl) { + padding-left: 3em; +} +.ql-editor li.ql-indent-1:not(.ql-direction-rtl) { + padding-left: 4.5em; +} +.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 3em; +} +.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 4.5em; +} +.ql-editor .ql-indent-2:not(.ql-direction-rtl) { + padding-left: 6em; +} +.ql-editor li.ql-indent-2:not(.ql-direction-rtl) { + padding-left: 7.5em; +} +.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 6em; +} +.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 7.5em; +} +.ql-editor .ql-indent-3:not(.ql-direction-rtl) { + padding-left: 9em; +} +.ql-editor li.ql-indent-3:not(.ql-direction-rtl) { + padding-left: 10.5em; +} +.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 9em; +} +.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 10.5em; +} +.ql-editor .ql-indent-4:not(.ql-direction-rtl) { + padding-left: 12em; +} +.ql-editor li.ql-indent-4:not(.ql-direction-rtl) { + padding-left: 13.5em; +} +.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 12em; +} +.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 13.5em; +} +.ql-editor .ql-indent-5:not(.ql-direction-rtl) { + padding-left: 15em; +} +.ql-editor li.ql-indent-5:not(.ql-direction-rtl) { + padding-left: 16.5em; +} +.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 15em; +} +.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 16.5em; +} +.ql-editor .ql-indent-6:not(.ql-direction-rtl) { + padding-left: 18em; +} +.ql-editor li.ql-indent-6:not(.ql-direction-rtl) { + padding-left: 19.5em; +} +.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 18em; +} +.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 19.5em; +} +.ql-editor .ql-indent-7:not(.ql-direction-rtl) { + padding-left: 21em; +} +.ql-editor li.ql-indent-7:not(.ql-direction-rtl) { + padding-left: 22.5em; +} +.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 21em; +} +.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 22.5em; +} +.ql-editor .ql-indent-8:not(.ql-direction-rtl) { + padding-left: 24em; +} +.ql-editor li.ql-indent-8:not(.ql-direction-rtl) { + padding-left: 25.5em; +} +.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 24em; +} +.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 25.5em; +} +.ql-editor .ql-indent-9:not(.ql-direction-rtl) { + padding-left: 27em; +} +.ql-editor li.ql-indent-9:not(.ql-direction-rtl) { + padding-left: 28.5em; +} +.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 27em; +} +.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 28.5em; +} +.ql-editor .ql-video { + display: block; + max-width: 100%; +} +.ql-editor .ql-video.ql-align-center { + margin: 0 auto; +} +.ql-editor .ql-video.ql-align-right { + margin: 0 0 0 auto; +} +.ql-editor .ql-bg-black { + background-color: #000; +} +.ql-editor .ql-bg-red { + background-color: #e60000; +} +.ql-editor .ql-bg-orange { + background-color: #f90; +} +.ql-editor .ql-bg-yellow { + background-color: #ff0; +} +.ql-editor .ql-bg-green { + background-color: #008a00; +} +.ql-editor .ql-bg-blue { + background-color: #06c; +} +.ql-editor .ql-bg-purple { + background-color: #93f; +} +.ql-editor .ql-color-white { + color: #fff; +} +.ql-editor .ql-color-red { + color: #e60000; +} +.ql-editor .ql-color-orange { + color: #f90; +} +.ql-editor .ql-color-yellow { + color: #ff0; +} +.ql-editor .ql-color-green { + color: #008a00; +} +.ql-editor .ql-color-blue { + color: #06c; +} +.ql-editor .ql-color-purple { + color: #93f; +} +.ql-editor .ql-font-serif { + font-family: Georgia, Times New Roman, serif; +} +.ql-editor .ql-font-monospace { + font-family: Monaco, Courier New, monospace; +} +.ql-editor .ql-size-small { + font-size: 0.75em; +} +.ql-editor .ql-size-large { + font-size: 1.5em; +} +.ql-editor .ql-size-huge { + font-size: 2.5em; +} +.ql-editor .ql-direction-rtl { + direction: rtl; + text-align: inherit; +} +.ql-editor .ql-align-center { + text-align: center; +} +.ql-editor .ql-align-justify { + text-align: justify; +} +.ql-editor .ql-align-right { + text-align: right; +} +.ql-editor.ql-blank::before { + color: rgba(0,0,0,0.6); + content: attr(data-placeholder); + font-style: italic; + pointer-events: none; + position: absolute; +} +.ql-snow.ql-toolbar:after, +.ql-snow .ql-toolbar:after { + clear: both; + content: ''; + display: table; +} +.ql-snow.ql-toolbar button, +.ql-snow .ql-toolbar button { + background: none; + border: none; + cursor: pointer; + display: inline-block; + float: left; + height: 24px; + outline: none; + padding: 3px 5px; + width: 28px; +} +.ql-snow.ql-toolbar button svg, +.ql-snow .ql-toolbar button svg { + float: left; + height: 100%; +} +.ql-snow.ql-toolbar input.ql-image[type=file], +.ql-snow .ql-toolbar input.ql-image[type=file] { + display: none; +} +.ql-snow.ql-toolbar button:hover, +.ql-snow .ql-toolbar button:hover, +.ql-snow.ql-toolbar button.ql-active, +.ql-snow .ql-toolbar button.ql-active, +.ql-snow.ql-toolbar .ql-picker-label:hover, +.ql-snow .ql-toolbar .ql-picker-label:hover, +.ql-snow.ql-toolbar .ql-picker-label.ql-active, +.ql-snow .ql-toolbar .ql-picker-label.ql-active, +.ql-snow.ql-toolbar .ql-picker-item:hover, +.ql-snow .ql-toolbar .ql-picker-item:hover, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected { + color: #06c; +} +.ql-snow.ql-toolbar button:hover .ql-fill, +.ql-snow .ql-toolbar button:hover .ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill { + fill: #06c; +} +.ql-snow.ql-toolbar button:hover .ql-stroke, +.ql-snow .ql-toolbar button:hover .ql-stroke, +.ql-snow.ql-toolbar button.ql-active .ql-stroke, +.ql-snow .ql-toolbar button.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow.ql-toolbar button:hover .ql-stroke-mitter, +.ql-snow .ql-toolbar button:hover .ql-stroke-mitter, +.ql-snow.ql-toolbar button.ql-active .ql-stroke-mitter, +.ql-snow .ql-toolbar button.ql-active .ql-stroke-mitter, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-mitter, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-mitter, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-mitter, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-mitter, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-mitter, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-mitter, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-mitter, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-mitter { + stroke: #06c; +} +.ql-snow { + box-sizing: border-box; +} +.ql-snow * { + box-sizing: border-box; +} +.ql-snow .ql-hidden { + display: none; +} +.ql-snow .ql-out-bottom, +.ql-snow .ql-out-top { + visibility: hidden; +} +.ql-snow .ql-tooltip { + position: absolute; +} +.ql-snow .ql-tooltip a { + cursor: pointer; + text-decoration: none; +} +.ql-snow .ql-formats { + display: inline-block; + vertical-align: middle; +} +.ql-snow .ql-formats:after { + clear: both; + content: ''; + display: table; +} +.ql-snow .ql-toolbar.snow, +.ql-snow .ql-stroke { + fill: none; + stroke: #444; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 2; +} +.ql-snow .ql-stroke-mitter { + fill: none; + stroke: #444; + stroke-mitterlimit: 10; + stroke-width: 2; +} +.ql-snow .ql-fill, +.ql-snow .ql-stroke.ql-fill { + fill: #444; +} +.ql-snow .ql-empty { + fill: none; +} +.ql-snow .ql-even { + fill-rule: evenodd; +} +.ql-snow .ql-thin, +.ql-snow .ql-stroke.ql-thin { + stroke-width: 1; +} +.ql-snow .ql-transparent { + opacity: 0.4; +} +.ql-snow .ql-direction svg:last-child { + display: none; +} +.ql-snow .ql-direction.ql-active svg:last-child { + display: inline; +} +.ql-snow .ql-direction.ql-active svg:first-child { + display: none; +} +.ql-snow .ql-editor h1 { + font-size: 2em; +} +.ql-snow .ql-editor h2 { + font-size: 1.5em; +} +.ql-snow .ql-editor h3 { + font-size: 1.17em; +} +.ql-snow .ql-editor h4 { + font-size: 1em; +} +.ql-snow .ql-editor h5 { + font-size: 0.83em; +} +.ql-snow .ql-editor h6 { + font-size: 0.67em; +} +.ql-snow .ql-editor a { + text-decoration: underline; +} +.ql-snow .ql-editor blockquote { + border-left: 4px solid #ccc; + margin-bottom: 5px; + margin-top: 5px; + padding-left: 16px; +} +.ql-snow .ql-editor code, +.ql-snow .ql-editor pre { + background-color: #f0f0f0; + border-radius: 3px; +} +.ql-snow .ql-editor pre { + white-space: pre-wrap; + margin-bottom: 5px; + margin-top: 5px; + padding: 5px 10px; +} +.ql-snow .ql-editor code { + font-size: 85%; + padding-bottom: 2px; + padding-top: 2px; +} +.ql-snow .ql-editor code:before, +.ql-snow .ql-editor code:after { + content: "\A0"; + letter-spacing: -2px; +} +.ql-snow .ql-editor pre.ql-syntax { + background-color: #23241f; + color: #f8f8f2; + overflow: visible; +} +.ql-snow .ql-editor img { + max-width: 100%; +} +.ql-snow .ql-picker { + color: #444; + display: inline-block; + float: left; + font-size: 14px; + font-weight: 500; + height: 24px; + position: relative; + vertical-align: middle; +} +.ql-snow .ql-picker-label { + cursor: pointer; + display: inline-block; + height: 100%; + padding-left: 8px; + padding-right: 2px; + position: relative; + width: 100%; +} +.ql-snow .ql-picker-label::before { + display: inline-block; + line-height: 22px; +} +.ql-snow .ql-picker-options { + background-color: #fff; + display: none; + min-width: 100%; + padding: 4px 8px; + position: absolute; + white-space: nowrap; +} +.ql-snow .ql-picker-options .ql-picker-item { + cursor: pointer; + display: block; + padding-bottom: 5px; + padding-top: 5px; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label { + color: #ccc; + z-index: 2; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill { + fill: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke { + stroke: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-options { + display: block; + margin-top: -1px; + top: 100%; + z-index: 1; +} +.ql-snow .ql-color-picker, +.ql-snow .ql-icon-picker { + width: 28px; +} +.ql-snow .ql-color-picker .ql-picker-label, +.ql-snow .ql-icon-picker .ql-picker-label { + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-label svg, +.ql-snow .ql-icon-picker .ql-picker-label svg { + right: 4px; +} +.ql-snow .ql-icon-picker .ql-picker-options { + padding: 4px 0px; +} +.ql-snow .ql-icon-picker .ql-picker-item { + height: 24px; + width: 24px; + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-options { + padding: 3px 5px; + width: 152px; +} +.ql-snow .ql-color-picker .ql-picker-item { + border: 1px solid transparent; + float: left; + height: 16px; + margin: 2px; + padding: 0px; + width: 16px; +} +.ql-snow .ql-color-picker .ql-picker-item.ql-primary-color { + margin-bottom: toolbarPadding; +} +.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg { + position: absolute; + margin-top: -9px; + right: 0; + top: 50%; + width: 18px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before { + content: attr(data-label); +} +.ql-snow .ql-picker.ql-header { + width: 98px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label::before, +.ql-snow .ql-picker.ql-header .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + content: 'Heading 1'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + content: 'Heading 2'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + content: 'Heading 3'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + content: 'Heading 4'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + content: 'Heading 5'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + content: 'Heading 6'; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + font-size: 2em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + font-size: 1.5em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + font-size: 1.17em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + font-size: 1em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + font-size: 0.83em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + font-size: 0.67em; +} +.ql-snow .ql-picker.ql-font { + width: 108px; +} +.ql-snow .ql-picker.ql-font .ql-picker-label::before, +.ql-snow .ql-picker.ql-font .ql-picker-item::before { + content: 'Sans Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + content: 'Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + content: 'Monospace'; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + font-family: Georgia, Times New Roman, serif; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + font-family: Monaco, Courier New, monospace; +} +.ql-snow .ql-picker.ql-size { + width: 98px; +} +.ql-snow .ql-picker.ql-size .ql-picker-label::before, +.ql-snow .ql-picker.ql-size .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + content: 'Small'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + content: 'Large'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + content: 'Huge'; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + font-size: 10px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + font-size: 18px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + font-size: 32px; +} +.ql-snow .ql-color-picker.ql-background .ql-picker-item { + background-color: #fff; +} +.ql-snow .ql-color-picker.ql-color .ql-picker-item { + background-color: #000; +} +.ql-toolbar.ql-snow { + border: 1px solid #ccc; + box-sizing: border-box; + font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + padding: 8px; +} +.ql-toolbar.ql-snow .ql-formats { + margin-right: 15px; +} +.ql-toolbar.ql-snow .ql-picker-label { + border: 1px solid transparent; +} +.ql-toolbar.ql-snow .ql-picker-options { + border: 1px solid transparent; + box-shadow: rgba(0,0,0,0.2) 0 2px 8px; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected, +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover { + border-color: #000; +} +.ql-toolbar.ql-snow + .ql-container.ql-snow { + border-top: 0px; +} +.ql-snow .ql-tooltip { + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0px 0px 5px #ddd; + color: #444; + margin-top: 10px; + padding: 5px 12px; + white-space: nowrap; +} +.ql-snow .ql-tooltip::before { + content: "Visit URL:"; + line-height: 26px; + margin-right: 8px; +} +.ql-snow .ql-tooltip input[type=text] { + display: none; + border: 1px solid #ccc; + font-size: 13px; + height: 26px; + margin: 0px; + padding: 3px 5px; + width: 170px; +} +.ql-snow .ql-tooltip a.ql-preview { + display: inline-block; + max-width: 200px; + overflow-x: hidden; + text-overflow: ellipsis; + vertical-align: top; +} +.ql-snow .ql-tooltip a.ql-action::after { + border-right: 1px solid #ccc; + content: 'Edit'; + margin-left: 16px; + padding-right: 8px; +} +.ql-snow .ql-tooltip a.ql-remove::before { + content: 'Remove'; + margin-left: 8px; +} +.ql-snow .ql-tooltip a { + line-height: 26px; +} +.ql-snow .ql-tooltip.ql-editing a.ql-preview, +.ql-snow .ql-tooltip.ql-editing a.ql-remove { + display: none; +} +.ql-snow .ql-tooltip.ql-editing input[type=text] { + display: inline-block; +} +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { + border-right: 0px; + content: 'Save'; + padding-right: 0px; +} +.ql-snow .ql-tooltip[data-mode=link]::before { + content: "Enter link:"; +} +.ql-snow .ql-tooltip[data-mode=formula]::before { + content: "Enter formula:"; +} +.ql-snow .ql-tooltip[data-mode=video]::before { + content: "Enter video:"; +} +.ql-snow a { + color: #06c; +} +.ql-container.ql-snow { + border: 1px solid #ccc; +} diff --git a/dev-workflow/webpage/web/styles.css b/dev-workflow/webpage/web/styles.css new file mode 100644 index 0000000..8223bd9 --- /dev/null +++ b/dev-workflow/webpage/web/styles.css @@ -0,0 +1,108 @@ +body { + padding: 0em; + margin: 0em; +} + +html { + background: url(https://cdn.spacetelescope.org/archives/images/wallpaper2/heic0601a.jpg) no-repeat center center fixed; + background-size: cover; + color: white; + font-family: 'Jura', sans-serif; +} + +h1.title { + font-family: 'Orbitron', sans-serif; + font-size: 3em; + margin: 0em; + padding: 0.67em; +} + +h2.stardate { + font-family: 'Bungee Hairline', cursive; +} + +.buttons { + display: flex; + justify-content: space-between; + align-items: center; +} + +select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: #222; + border: none; + color: inherit; + font-size: inherit; + padding: 5px; + padding-right: 18px; +} + +select:focus { + outline: none; +} + +select:active { + background-color: #222; +} + +div.select { + border-bottom: 1px solid gray; + display: inline-block; + height: 100%; + position: relative; +} + +div.select::after { + font-family: 'Material Icons'; + content: '\E5C5'; + position: absolute; + right: 2px; + top: 6px; + pointer-events: none; +} + +button { + background-color: #06c; + color: white; + border-color: #06c; + border-radius: 0.25em; + font-family: inherit; + font-size: 1.1em; + margin-top: .5em; + margin-left: 0.5em; + margin-bottom: 0.5em; + padding: .5em; +} + +#editor .ql-editor.ql-blank::before { + color: white; +} + +.ql-toolbar .ql-stroke { + stroke: white; +} + +.ql-toolbar .ql-fill { + fill: white; +} + +.ql-toolbar.ql-snow .ql-picker-label { + color: white; +} + +#content { + margin-left: 20%; + margin-right: 20%; + padding-left: 20px; + padding-right: 20px; + padding-bottom: 20px; + background: rgba(22, 22, 22, 0.9); + background-clip: padding-box; +} + +#editor { + height: 20em; + font-size: 1.1em; +}