mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-03 04:18:25 +08:00
docs: Flutter-app directive can now also show the listings of code (#1500)
This commit is contained in:
@ -10,6 +10,7 @@ button.flutter-app-button {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
line-height: 1em;
|
||||
margin-right: 1em;
|
||||
min-height: 26pt;
|
||||
min-width: 120pt;
|
||||
}
|
||||
@ -33,8 +34,45 @@ button.flutter-app-button:after {
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.flutter-app-code {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.flutter-app-code.active {
|
||||
background: #282828;
|
||||
box-shadow: 0 0 30px 0 #000;
|
||||
box-sizing: border-box;
|
||||
display: initial;
|
||||
height: 80vh;
|
||||
left: 50%;
|
||||
overflow-y: scroll;
|
||||
padding: 1em 2em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 80vw;
|
||||
}
|
||||
|
||||
.flutter-app-code .filename {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
margin: 1.5em 0 -0.5em 0;
|
||||
}
|
||||
|
||||
.flutter-app-code div.highlight span.linenos {
|
||||
color: #444;
|
||||
margin-right: 8pt;
|
||||
}
|
||||
|
||||
#flutter-app-overlay {
|
||||
background: #00000050;
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#000000bb 0px,
|
||||
#000000bb 5px,
|
||||
#000000aa 5px,
|
||||
#000000aa 10px
|
||||
);
|
||||
display: none;
|
||||
height: 100vh;
|
||||
left: 0;
|
||||
@ -49,8 +87,8 @@ button.flutter-app-button:after {
|
||||
}
|
||||
|
||||
#flutter-app-overlay.active iframe {
|
||||
border: none;
|
||||
box-shadow: 0px 0px 30px 0px #ffffff26;
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0px 0px 30px 0px #000;
|
||||
display: none;
|
||||
height: 80vh;
|
||||
left: 50%;
|
||||
|
||||
@ -4,13 +4,7 @@
|
||||
/// creates an (x) button to hide the overlay.
|
||||
function run_flutter_app(url) {
|
||||
let id = compute_iframe_id(url);
|
||||
if (!$('#flutter-app-overlay').length) {
|
||||
$('body').append($(`
|
||||
<div id="flutter-app-overlay">
|
||||
<button id="flutter-app-close-button" onclick="close_flutter_app()">✖</button>
|
||||
</div>`
|
||||
));
|
||||
}
|
||||
create_overlay();
|
||||
if (!$('#' + id).length) {
|
||||
$('#flutter-app-overlay').append($(
|
||||
`<iframe id="${id}" class="flutter-app" src="${url}"></iframe>`
|
||||
@ -20,9 +14,29 @@ function run_flutter_app(url) {
|
||||
$('#' + id).addClass('active');
|
||||
}
|
||||
|
||||
function open_code_listings(id) {
|
||||
create_overlay();
|
||||
if (!$('#flutter-app-overlay #' + id).length) {
|
||||
$('#' + id).appendTo($('#flutter-app-overlay'));
|
||||
}
|
||||
$('#flutter-app-overlay').addClass('active');
|
||||
$('#' + id).addClass('active');
|
||||
}
|
||||
|
||||
function create_overlay() {
|
||||
if (!$('#flutter-app-overlay').length) {
|
||||
$('body').append($(`
|
||||
<div id="flutter-app-overlay">
|
||||
<button id="flutter-app-close-button" onclick="close_flutter_app()">✖</button>
|
||||
</div>`
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler for the (x) close button on an app iframe.
|
||||
function close_flutter_app() {
|
||||
$('#flutter-app-overlay iframe').removeClass('active');
|
||||
$('#flutter-app-overlay > iframe').removeClass('active');
|
||||
$('#flutter-app-overlay > div').removeClass('active');
|
||||
$('#flutter-app-overlay').removeClass('active');
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
@ -46,7 +47,8 @@ class FlutterAppDirective(SphinxDirective):
|
||||
"popup", and "code". Each of these modes produces a different output:
|
||||
"widget" - an iframe shown directly inside the docs page;
|
||||
"popup" - a [Run] button which opens the app to (almost) fullscreen;
|
||||
"code" - (NYI) opens a popup showing the code that was compiled.
|
||||
"code" - a [Code] button which opens a popup with the code that was
|
||||
compiled.
|
||||
"""
|
||||
has_content = False
|
||||
required_arguments = 0
|
||||
@ -91,7 +93,14 @@ class FlutterAppDirective(SphinxDirective):
|
||||
onclick=f'run_flutter_app("{iframe_url}")',
|
||||
))
|
||||
if 'code' in self.modes:
|
||||
pass
|
||||
code_id = self.app_name + "-source"
|
||||
result.append(self._generate_code_listings(code_id))
|
||||
result.append(Button(
|
||||
'',
|
||||
nodes.Text('Code'),
|
||||
classes=['flutter-app-button', 'code'],
|
||||
onclick=f'open_code_listings("{code_id}")',
|
||||
))
|
||||
if 'widget' in self.modes:
|
||||
result.append(IFrame(src=iframe_url))
|
||||
return result
|
||||
@ -132,7 +141,7 @@ class FlutterAppDirective(SphinxDirective):
|
||||
self.logger.info('Compiling Flutter app ' + self.app_name)
|
||||
self._compile_source()
|
||||
self._copy_compiled()
|
||||
self._create_index()
|
||||
self._create_index_html()
|
||||
self.logger.info(' + copied into ' + self.target_dir)
|
||||
assert os.path.isfile(self.target_dir + '/main.dart.js')
|
||||
assert os.path.isfile(self.target_dir + '/index.html')
|
||||
@ -167,17 +176,38 @@ class FlutterAppDirective(SphinxDirective):
|
||||
dirs_exist_ok=True,
|
||||
)
|
||||
|
||||
def _create_index(self):
|
||||
def _create_index_html(self):
|
||||
target_file = os.path.join(self.target_dir, 'index.html')
|
||||
with open(target_file, 'wt') as out:
|
||||
out.write('<!DOCTYPE html>\n')
|
||||
out.write('<html>\n<head>\n')
|
||||
out.write('<base href="%s%s/">\n' % (_doc_root(), self.html_dir))
|
||||
out.write('<title>%s</title>\n' % self.app_name)
|
||||
out.write('<style>body { background: black; }</style>\n')
|
||||
out.write('</head>\n<body>\n')
|
||||
out.write('<script src="main.dart.js"></script>\n')
|
||||
out.write('</body>\n</html>\n')
|
||||
|
||||
def _generate_code_listings(self, code_id):
|
||||
code_dir = self.source_dir + '/lib/' + self.options.get('page', '')
|
||||
if not os.path.isdir(code_dir):
|
||||
raise self.error('Cannot find source directory ' + code_dir)
|
||||
files = glob.glob(code_dir + '/**', recursive=True)
|
||||
|
||||
result = nodes.container(classes=['flutter-app-code'], ids=[code_id])
|
||||
for filename in sorted(files):
|
||||
if os.path.isfile(filename):
|
||||
simple_filename = os.path.relpath(filename, code_dir)
|
||||
result += nodes.container(
|
||||
'', nodes.Text(simple_filename), classes=['filename']
|
||||
)
|
||||
with open(filename, 'rt') as f:
|
||||
self.state.nested_parse(
|
||||
['``````{code-block} dart\n:lineno-start: 1\n'] +
|
||||
[line.rstrip() for line in f] +
|
||||
['``````\n'], 0, result)
|
||||
return result
|
||||
|
||||
|
||||
def _doc_root():
|
||||
root = os.environ.get('PUBLISH_PATH', '')
|
||||
|
||||
@ -258,7 +258,7 @@ the card objects, which are the most important visual objects in this game.
|
||||
```{flutter-app}
|
||||
:sources: ../tutorials/klondike/app
|
||||
:page: step2
|
||||
:show: popup
|
||||
:show: popup code
|
||||
```
|
||||
|
||||
[World]: ../../flame/camera_component.md#world
|
||||
|
||||
Reference in New Issue
Block a user