You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2022/11/15 16:04:08 UTC
[beam] branch master updated: Configure flutter_code_editor options with Hugo shortcode (#23926) (#24031)
This is an automated email from the ASF dual-hosted git repository.
pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new f349f41010c Configure flutter_code_editor options with Hugo shortcode (#23926) (#24031)
f349f41010c is described below
commit f349f41010c5b238ff6020f7de718f938eef3c5e
Author: alexeyinkin <al...@akvelon.com>
AuthorDate: Tue Nov 15 20:04:01 2022 +0400
Configure flutter_code_editor options with Hugo shortcode (#23926) (#24031)
* Configure flutter_code_editor options with Hugo shortcode (#23926)
* Minor fixes (#23926)
* Refactor after review (#23926)
---
learning/tour-of-beam/frontend/pubspec.lock | 2 +-
.../example_list/example_item_actions.dart | 4 +-
.../examples_loading_descriptor_factory.dart | 35 +++-
.../examples/models/example_token_type.dart | 7 +
.../lib/playground_components.dart | 2 +
.../example_loaders/empty_example_loader.dart | 8 +-
.../example_loaders/examples_loader.dart | 2 +
...xample_loader.dart => http_example_loader.dart} | 35 ++--
.../example_loaders/standard_example_loader.dart | 4 +-
.../lib/src/controllers/playground_controller.dart | 1 +
.../controllers/snippet_editing_controller.dart | 44 +++-
.../lib/src/enums/complexity.dart | 9 +-
.../lib/src/models/example.dart | 44 ++--
.../lib/src/models/example_base.dart | 28 +--
.../content_example_loading_descriptor.dart | 11 +-
.../example_loading_descriptor.dart | 8 +-
...r.dart => http_example_loading_descriptor.dart} | 18 +-
.../standard_example_loading_descriptor.dart | 6 +-
.../user_shared_example_loading_descriptor.dart | 6 +-
.../lib/src/models/example_view_options.dart | 72 +++++++
.../repositories/complexity_grpc_extension.dart | 4 +-
.../repositories/models/get_snippet_response.dart | 8 +-
.../string.dart} | 10 +-
.../lib/src/widgets/editor_textarea.dart | 13 +-
.../frontend/playground_components/pubspec.yaml | 3 +-
.../example_loaders/http_example_loader_test.dart | 58 ++++++
playground/frontend/pubspec.lock | 4 +-
.../examples_loading_descriptor_factory_test.dart | 224 +++++++++++++++++++++
.../examples/models/example_token_type_test.dart | 48 +++++
.../www/site/layouts/shortcodes/playground.html | 33 ++-
.../layouts/shortcodes/playground_snippet.html | 36 +++-
31 files changed, 660 insertions(+), 127 deletions(-)
diff --git a/learning/tour-of-beam/frontend/pubspec.lock b/learning/tour-of-beam/frontend/pubspec.lock
index 9983b9bb530..e1ed198ef56 100644
--- a/learning/tour-of-beam/frontend/pubspec.lock
+++ b/learning/tour-of-beam/frontend/pubspec.lock
@@ -278,7 +278,7 @@ packages:
name: flutter_code_editor
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.1"
+ version: "0.1.4"
flutter_driver:
dependency: transitive
description: flutter
diff --git a/playground/frontend/lib/modules/examples/components/example_list/example_item_actions.dart b/playground/frontend/lib/modules/examples/components/example_list/example_item_actions.dart
index d02e27eec61..30b67fa0edd 100644
--- a/playground/frontend/lib/modules/examples/components/example_list/example_item_actions.dart
+++ b/playground/frontend/lib/modules/examples/components/example_list/example_item_actions.dart
@@ -36,8 +36,8 @@ class ExampleItemActions extends StatelessWidget {
return Row(
children: [
if (example.isMultiFile) multifilePopover,
- if (example.complexity != Complexity.unspecified)
- ComplexityWidget(complexity: example.complexity),
+ if (example.complexity != null)
+ ComplexityWidget(complexity: example.complexity!),
descriptionPopover,
],
);
diff --git a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory.dart b/playground/frontend/lib/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory.dart
index 7b3854d6f31..a73b16d7cfd 100644
--- a/playground/frontend/lib/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory.dart
+++ b/playground/frontend/lib/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory.dart
@@ -18,6 +18,7 @@
import 'dart:convert';
+import 'package:flutter/foundation.dart';
import 'package:playground/constants/params.dart';
import 'package:playground/modules/examples/models/example_token_type.dart';
import 'package:playground_components/playground_components.dart';
@@ -115,7 +116,7 @@ class ExamplesLoadingDescriptorFactory {
return null;
}
- return _parseSingleExample(token);
+ return _parseSingleExample(token, params);
}
static ExamplesLoadingDescriptor? _tryParseOfCatalogDefaultExamples(
@@ -135,15 +136,32 @@ class ExamplesLoadingDescriptorFactory {
);
}
- static ExampleLoadingDescriptor _parseSingleExample(String token) {
+ static ExampleLoadingDescriptor _parseSingleExample(
+ String token,
+ Map<String, dynamic> params,
+ ) {
+ final viewOptions = ExampleViewOptions.fromShortMap(params);
final tokenType = ExampleTokenType.fromToken(token);
switch (tokenType) {
+ case ExampleTokenType.http:
+ return HttpExampleLoadingDescriptor(
+ sdk: Sdk.parseOrCreate(params['sdk']),
+ uri: Uri.parse(token),
+ viewOptions: viewOptions,
+ );
+
case ExampleTokenType.standard:
- return StandardExampleLoadingDescriptor(path: token);
+ return StandardExampleLoadingDescriptor(
+ path: token,
+ viewOptions: viewOptions,
+ );
case ExampleTokenType.userShared:
- return UserSharedExampleLoadingDescriptor(snippetId: token);
+ return UserSharedExampleLoadingDescriptor(
+ snippetId: token,
+ viewOptions: viewOptions,
+ );
}
}
@@ -166,22 +184,23 @@ class ExamplesLoadingDescriptorFactory {
return _emptyLazyLoadDescriptors;
}
- return _defaultLazyLoadDescriptors;
+ return defaultLazyLoadDescriptors;
}
static Map<Sdk, List<ExampleLoadingDescriptor>>
get _emptyLazyLoadDescriptors {
return {
for (final sdk in Sdk.known)
- sdk: [EmptyExampleLoadingDescriptor(sdk: sdk)]
+ sdk: [EmptyExampleLoadingDescriptor(sdk: sdk)],
};
}
+ @visibleForTesting
static Map<Sdk, List<ExampleLoadingDescriptor>>
- get _defaultLazyLoadDescriptors {
+ get defaultLazyLoadDescriptors {
return {
for (final sdk in Sdk.known)
- sdk: [CatalogDefaultExampleLoadingDescriptor(sdk: sdk)]
+ sdk: [CatalogDefaultExampleLoadingDescriptor(sdk: sdk)],
};
}
}
diff --git a/playground/frontend/lib/modules/examples/models/example_token_type.dart b/playground/frontend/lib/modules/examples/models/example_token_type.dart
index 48c7c580635..ee274563fae 100644
--- a/playground/frontend/lib/modules/examples/models/example_token_type.dart
+++ b/playground/frontend/lib/modules/examples/models/example_token_type.dart
@@ -19,11 +19,18 @@
import 'package:playground_components/playground_components.dart';
enum ExampleTokenType {
+ /// A URI to load the plain content from.
+ http,
+
standard,
userShared,
;
static ExampleTokenType fromToken(String token) {
+ if (token.startsWith(RegExp('http(s)?://'))) {
+ return http;
+ }
+
final sdk = Sdk.tryParseExamplePath(token);
if (sdk != null) {
return standard;
diff --git a/playground/frontend/playground_components/lib/playground_components.dart b/playground/frontend/playground_components/lib/playground_components.dart
index 24837c8fc0b..c738710bde7 100644
--- a/playground/frontend/playground_components/lib/playground_components.dart
+++ b/playground/frontend/playground_components/lib/playground_components.dart
@@ -36,8 +36,10 @@ export 'src/models/example_loading_descriptors/content_example_loading_descripto
export 'src/models/example_loading_descriptors/empty_example_loading_descriptor.dart';
export 'src/models/example_loading_descriptors/example_loading_descriptor.dart';
export 'src/models/example_loading_descriptors/examples_loading_descriptor.dart';
+export 'src/models/example_loading_descriptors/http_example_loading_descriptor.dart';
export 'src/models/example_loading_descriptors/standard_example_loading_descriptor.dart';
export 'src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart';
+export 'src/models/example_view_options.dart';
export 'src/models/intents.dart';
export 'src/models/outputs.dart';
export 'src/models/sdk.dart';
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
index faef4c0098f..a2d178c5fcd 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
@@ -17,7 +17,6 @@
*/
import '../../cache/example_cache.dart';
-import '../../enums/complexity.dart';
import '../../models/example.dart';
import '../../models/example_base.dart';
import '../../models/example_loading_descriptors/empty_example_loading_descriptor.dart';
@@ -34,14 +33,11 @@ class EmptyExampleLoader extends ExampleLoader {
@override
Future<Example> get future async => Example(
- sdk: descriptor.sdk,
name: 'Embedded_Example',
path: '',
- description: '',
+ sdk: descriptor.sdk,
+ source: '',
tags: [],
type: ExampleType.example,
- source: '',
- pipelineOptions: '',
- complexity: Complexity.unspecified,
);
}
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart
index 6d872e67751..d2b1799f02b 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart
@@ -26,6 +26,7 @@ import 'catalog_default_example_loader.dart';
import 'content_example_loader.dart';
import 'empty_example_loader.dart';
import 'example_loader_factory.dart';
+import 'http_example_loader.dart';
import 'standard_example_loader.dart';
import 'user_shared_example_loader.dart';
@@ -38,6 +39,7 @@ class ExamplesLoader {
defaultFactory.add(CatalogDefaultExampleLoader.new);
defaultFactory.add(ContentExampleLoader.new);
defaultFactory.add(EmptyExampleLoader.new);
+ defaultFactory.add(HttpExampleLoader.new);
defaultFactory.add(StandardExampleLoader.new);
defaultFactory.add(UserSharedExampleLoader.new);
}
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
similarity index 63%
copy from playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
copy to playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
index faef4c0098f..b36fa2ef99d 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/empty_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/http_example_loader.dart
@@ -16,32 +16,35 @@
* limitations under the License.
*/
+import 'package:collection/collection.dart';
+import 'package:http/http.dart' as http;
+
import '../../cache/example_cache.dart';
-import '../../enums/complexity.dart';
import '../../models/example.dart';
import '../../models/example_base.dart';
-import '../../models/example_loading_descriptors/empty_example_loading_descriptor.dart';
+import '../../models/example_loading_descriptors/http_example_loading_descriptor.dart';
import 'example_loader.dart';
-class EmptyExampleLoader extends ExampleLoader {
- final EmptyExampleLoadingDescriptor descriptor;
+class HttpExampleLoader extends ExampleLoader {
+ final HttpExampleLoadingDescriptor descriptor;
- const EmptyExampleLoader({
+ const HttpExampleLoader({
required this.descriptor,
// TODO(alexeyinkin): Remove when this lands: https://github.com/dart-lang/language/issues/1813
required ExampleCache exampleCache,
});
@override
- Future<Example> get future async => Example(
- sdk: descriptor.sdk,
- name: 'Embedded_Example',
- path: '',
- description: '',
- tags: [],
- type: ExampleType.example,
- source: '',
- pipelineOptions: '',
- complexity: Complexity.unspecified,
- );
+ Future<Example> get future async {
+ final response = await http.get(descriptor.uri);
+
+ return Example(
+ name: descriptor.uri.path.split('/').lastOrNull ?? 'HTTP Example',
+ path: descriptor.uri.toString(),
+ sdk: descriptor.sdk,
+ source: response.body,
+ type: ExampleType.example,
+ viewOptions: descriptor.viewOptions,
+ );
+ }
}
diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
index 23c429ebab1..83e3c5c46ba 100644
--- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart
@@ -27,7 +27,7 @@ import 'example_loader.dart';
/// Loads a given example from the local cache, then adds info from network.
///
-/// This loader assumes that [ExampleState] is loading all examples to
+/// This loader assumes that [ExampleCache] is loading all examples to
/// its cache. So it only completes if this is successful.
class StandardExampleLoader extends ExampleLoader {
final StandardExampleLoadingDescriptor descriptor;
@@ -41,7 +41,7 @@ class StandardExampleLoader extends ExampleLoader {
required this.descriptor,
required this.exampleCache,
}) {
- _load();
+ unawaited(_load());
}
Future<void> _load() async {
diff --git a/playground/frontend/playground_components/lib/src/controllers/playground_controller.dart b/playground/frontend/playground_components/lib/src/controllers/playground_controller.dart
index f3f1f52ba09..2937c2c5eb3 100644
--- a/playground/frontend/playground_components/lib/src/controllers/playground_controller.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/playground_controller.dart
@@ -175,6 +175,7 @@ class PlaygroundController with ChangeNotifier {
}
}
+ // TODO(alexeyinkin): Remove, used only in tests, refactor them.
void setSource(String source) {
final controller = requireSnippetEditingController();
controller.setSource(source);
diff --git a/playground/frontend/playground_components/lib/src/controllers/snippet_editing_controller.dart b/playground/frontend/playground_components/lib/src/controllers/snippet_editing_controller.dart
index 8bb285eff42..7ed145e3ac7 100644
--- a/playground/frontend/playground_components/lib/src/controllers/snippet_editing_controller.dart
+++ b/playground/frontend/playground_components/lib/src/controllers/snippet_editing_controller.dart
@@ -19,36 +19,57 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_code_editor/flutter_code_editor.dart';
-import '../enums/complexity.dart';
import '../models/example.dart';
import '../models/example_loading_descriptors/content_example_loading_descriptor.dart';
import '../models/example_loading_descriptors/example_loading_descriptor.dart';
+import '../models/example_view_options.dart';
import '../models/sdk.dart';
class SnippetEditingController extends ChangeNotifier {
final Sdk sdk;
final CodeController codeController;
Example? _selectedExample;
- String _pipelineOptions;
+ String _pipelineOptions = '';
SnippetEditingController({
required this.sdk,
- Example? selectedExample,
- String pipelineOptions = '',
- }) : codeController = CodeController(
+ }) : codeController = CodeController(
language: sdk.highlightMode,
+ namedSectionParser: const BracketsStartEndNamedSectionParser(),
webSpaceFix: false,
- ),
- _selectedExample = selectedExample,
- _pipelineOptions = pipelineOptions;
+ );
set selectedExample(Example? value) {
_selectedExample = value;
setSource(_selectedExample?.source ?? '');
+
+ final viewOptions = value?.viewOptions;
+ if (viewOptions != null) {
+ _applyViewOptions(viewOptions);
+ }
+
_pipelineOptions = _selectedExample?.pipelineOptions ?? '';
notifyListeners();
}
+ void _applyViewOptions(ExampleViewOptions options) {
+ codeController.readOnlySectionNames = options.readOnlySectionNames.toSet();
+ codeController.visibleSectionNames = options.showSectionNames.toSet();
+
+ if (options.foldCommentAtLineZero) {
+ codeController.foldCommentAtLineZero();
+ }
+
+ if (options.foldImports) {
+ codeController.foldImports();
+ }
+
+ final unfolded = options.unfoldSectionNames;
+ if (unfolded.isNotEmpty) {
+ codeController.foldOutsideSections(unfolded);
+ }
+ }
+
Example? get selectedExample => _selectedExample;
set pipelineOptions(String value) {
@@ -82,15 +103,18 @@ class SnippetEditingController extends ChangeNotifier {
// user-shared examples, and an empty editor,
// https://github.com/apache/beam/issues/23252
return ContentExampleLoadingDescriptor(
+ complexity: _selectedExample?.complexity,
content: codeController.fullText,
name: _selectedExample?.name,
- complexity: _selectedExample?.complexity ?? Complexity.unspecified,
sdk: sdk,
);
}
void setSource(String source) {
- codeController.text = source;
+ codeController.readOnlySectionNames = const {};
+ codeController.visibleSectionNames = const {};
+
+ codeController.fullText = source;
codeController.historyController.deleteHistory();
}
}
diff --git a/playground/frontend/playground_components/lib/src/enums/complexity.dart b/playground/frontend/playground_components/lib/src/enums/complexity.dart
index e8e675b34ff..59da4941087 100644
--- a/playground/frontend/playground_components/lib/src/enums/complexity.dart
+++ b/playground/frontend/playground_components/lib/src/enums/complexity.dart
@@ -19,8 +19,6 @@
import 'package:json_annotation/json_annotation.dart';
enum Complexity {
- @JsonValue('UNSPECIFIED')
- unspecified,
@JsonValue('BASIC')
basic,
@JsonValue('MEDIUM')
@@ -29,7 +27,7 @@ enum Complexity {
advanced,
;
- static Complexity fromString(String complexity) {
+ static Complexity? fromString(String? complexity) {
switch (complexity) {
case 'basic':
return Complexity.basic;
@@ -37,9 +35,8 @@ enum Complexity {
return Complexity.medium;
case 'advanced':
return Complexity.advanced;
- case 'unspecified':
- return Complexity.unspecified;
}
- throw Exception('Unknown complexity: $complexity');
+
+ return null;
}
}
diff --git a/playground/frontend/playground_components/lib/src/models/example.dart b/playground/frontend/playground_components/lib/src/models/example.dart
index 2654ecb6461..33e2b65a973 100644
--- a/playground/frontend/playground_components/lib/src/models/example.dart
+++ b/playground/frontend/playground_components/lib/src/models/example.dart
@@ -20,46 +20,48 @@ import 'example_base.dart';
/// A [ExampleBase] that also has all large fields fetched.
class Example extends ExampleBase {
- final String source;
- final String? outputs;
- final String? logs;
final String? graph;
+ final String? logs;
+ final String? outputs;
+ final String source;
const Example({
+ required this.source,
+ required super.name,
required super.sdk,
- required super.tags,
required super.type,
- required super.name,
required super.path,
- required super.description,
+ this.graph,
+ this.logs,
+ this.outputs,
+ super.complexity,
super.contextLine,
+ super.description,
super.isMultiFile,
super.link,
- required super.pipelineOptions,
- required this.source,
- this.outputs,
- this.logs,
- this.graph,
- required super.complexity,
+ super.pipelineOptions,
+ super.tags,
+ super.viewOptions,
});
Example.fromBase(
ExampleBase example, {
- required this.source,
- required this.outputs,
required this.logs,
+ required this.outputs,
+ required this.source,
this.graph,
}) : super(
- sdk: example.sdk,
- name: example.name,
- path: example.path,
- description: example.description,
- tags: example.tags,
- type: example.type,
+ complexity: example.complexity,
contextLine: example.contextLine,
+ description: example.description,
isMultiFile: example.isMultiFile,
link: example.link,
+ name: example.name,
+ path: example.path,
pipelineOptions: example.pipelineOptions,
- complexity: example.complexity,
+ sdk: example.sdk,
+ tags: example.tags,
+ type: example.type,
+ viewOptions: example.viewOptions,
);
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_base.dart b/playground/frontend/playground_components/lib/src/models/example_base.dart
index 62968579b27..dd9b7fcb34c 100644
--- a/playground/frontend/playground_components/lib/src/models/example_base.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_base.dart
@@ -20,6 +20,7 @@ import 'package:equatable/equatable.dart';
import '../enums/complexity.dart';
import '../repositories/example_repository.dart';
+import 'example_view_options.dart';
import 'sdk.dart';
enum ExampleType {
@@ -48,32 +49,35 @@ extension ExampleTypeToString on ExampleType {
/// and other large fields.
/// These objects are fetched as lists from [ExampleRepository].
class ExampleBase with Comparable<ExampleBase>, EquatableMixin {
- final Sdk sdk;
- final List<String> tags;
- final ExampleType type;
- final String name;
- final String path;
- final String description;
+ final Complexity? complexity;
final int contextLine;
+ final String description;
final bool isMultiFile;
final String? link;
+ final String name;
+ final String path;
final String pipelineOptions;
- final Complexity complexity;
+ final Sdk sdk;
+ final List<String> tags;
+ final ExampleType type;
+ final ExampleViewOptions viewOptions;
const ExampleBase({
- required this.sdk,
required this.name,
required this.path,
- required this.description,
- required this.tags,
+ required this.sdk,
required this.type,
+ this.complexity,
this.contextLine = 1,
+ this.description = '',
this.isMultiFile = false,
this.link,
- required this.pipelineOptions,
- required this.complexity,
+ this.pipelineOptions = '',
+ this.tags = const [],
+ this.viewOptions = ExampleViewOptions.empty,
});
+ // TODO(alexeyinkin): Use all fields, https://github.com/apache/beam/issues/23979
@override
List<Object> get props => [path];
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
index dbc9a7e8567..6cac8861e24 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/content_example_loading_descriptor.dart
@@ -27,15 +27,16 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
/// The name of the example, if any, to show in the dropdown.
final String? name;
- final Complexity complexity;
+ final Complexity? complexity;
final Sdk sdk;
const ContentExampleLoadingDescriptor({
required this.content,
- required this.name,
required this.sdk,
- required this.complexity,
+ this.complexity,
+ this.name,
+ super.viewOptions,
});
static ContentExampleLoadingDescriptor? tryParse(Map eventData) {
@@ -69,7 +70,7 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
return Sdk.tryParse(map['sdk']);
}
- static Complexity _parseComplexity(Map map) {
+ static Complexity? _parseComplexity(Map map) {
final complexityString = map['complexity'];
return Complexity.fromString(complexityString);
}
@@ -79,9 +80,9 @@ class ContentExampleLoadingDescriptor extends ExampleLoadingDescriptor {
@override
Map<String, dynamic> toJson() => {
+ 'complexity': complexity?.name,
'content': content,
'name': name,
'sdk': sdk.id,
- 'complexity': complexity.name,
};
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
index 35c3cf18100..c78dafff250 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
@@ -18,8 +18,14 @@
import 'package:equatable/equatable.dart';
+import '../example_view_options.dart';
+
abstract class ExampleLoadingDescriptor with EquatableMixin {
- const ExampleLoadingDescriptor();
+ const ExampleLoadingDescriptor({
+ this.viewOptions = ExampleViewOptions.empty,
+ });
+
+ final ExampleViewOptions viewOptions;
Map<String, dynamic> toJson() => throw UnimplementedError();
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
similarity index 73%
copy from playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
copy to playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
index 8ac57c624a9..f65534aac93 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/http_example_loading_descriptor.dart
@@ -16,15 +16,23 @@
* limitations under the License.
*/
+import '../sdk.dart';
import 'example_loading_descriptor.dart';
-class StandardExampleLoadingDescriptor extends ExampleLoadingDescriptor {
- final String path;
+class HttpExampleLoadingDescriptor extends ExampleLoadingDescriptor {
+ final Sdk sdk;
+ final Uri uri;
- const StandardExampleLoadingDescriptor({
- required this.path,
+ const HttpExampleLoadingDescriptor({
+ required this.sdk,
+ required this.uri,
+ super.viewOptions,
});
@override
- List<Object> get props => [path];
+ List<Object> get props => [
+ sdk,
+ uri,
+ viewOptions,
+ ];
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
index 8ac57c624a9..62767e2b58d 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/standard_example_loading_descriptor.dart
@@ -23,8 +23,12 @@ class StandardExampleLoadingDescriptor extends ExampleLoadingDescriptor {
const StandardExampleLoadingDescriptor({
required this.path,
+ super.viewOptions,
});
@override
- List<Object> get props => [path];
+ List<Object> get props => [
+ path,
+ viewOptions,
+ ];
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
index 1bcbe0dc60a..fc697bccb75 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart
@@ -23,8 +23,12 @@ class UserSharedExampleLoadingDescriptor extends ExampleLoadingDescriptor {
const UserSharedExampleLoadingDescriptor({
required this.snippetId,
+ super.viewOptions,
});
@override
- List<Object> get props => [snippetId];
+ List<Object> get props => [
+ snippetId,
+ viewOptions,
+ ];
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_view_options.dart b/playground/frontend/playground_components/lib/src/models/example_view_options.dart
new file mode 100644
index 00000000000..bc12a66db0a
--- /dev/null
+++ b/playground/frontend/playground_components/lib/src/models/example_view_options.dart
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:equatable/equatable.dart';
+
+import '../util/string.dart';
+
+class ExampleViewOptions with EquatableMixin {
+ final bool foldCommentAtLineZero;
+ final bool foldImports;
+ final List<String> readOnlySectionNames;
+ final List<String> showSectionNames;
+ final List<String> unfoldSectionNames;
+
+ const ExampleViewOptions({
+ required this.foldCommentAtLineZero,
+ required this.foldImports,
+ required this.readOnlySectionNames,
+ required this.showSectionNames,
+ required this.unfoldSectionNames,
+ });
+
+ factory ExampleViewOptions.fromShortMap(Map<String, dynamic> map) {
+ return ExampleViewOptions(
+ foldCommentAtLineZero: true,
+ foldImports: true,
+ readOnlySectionNames: _split(map['readonly']),
+ showSectionNames: _split(map['show']),
+ unfoldSectionNames: _split(map['unfold']),
+ );
+ }
+
+ static List<String> _split(Object? value) {
+ if (value is! String) {
+ return [];
+ }
+
+ return value.splitNotEmpty(',');
+ }
+
+ static const empty = ExampleViewOptions(
+ foldCommentAtLineZero: true,
+ foldImports: true,
+ readOnlySectionNames: [],
+ showSectionNames: [],
+ unfoldSectionNames: [],
+ );
+
+ @override
+ List<Object> get props => [
+ foldCommentAtLineZero,
+ foldImports,
+ readOnlySectionNames,
+ showSectionNames,
+ unfoldSectionNames,
+ ];
+}
diff --git a/playground/frontend/playground_components/lib/src/repositories/complexity_grpc_extension.dart b/playground/frontend/playground_components/lib/src/repositories/complexity_grpc_extension.dart
index c9edb542983..39c9eed824d 100644
--- a/playground/frontend/playground_components/lib/src/repositories/complexity_grpc_extension.dart
+++ b/playground/frontend/playground_components/lib/src/repositories/complexity_grpc_extension.dart
@@ -20,7 +20,7 @@ import '../api/v1/api.pbgrpc.dart' as g;
import '../enums/complexity.dart';
extension GrpcComplecity on g.Complexity {
- Complexity get model {
+ Complexity? get model {
switch (this) {
case g.Complexity.COMPLEXITY_BASIC:
return Complexity.basic;
@@ -29,7 +29,7 @@ extension GrpcComplecity on g.Complexity {
case g.Complexity.COMPLEXITY_ADVANCED:
return Complexity.advanced;
case g.Complexity.COMPLEXITY_UNSPECIFIED:
- return Complexity.unspecified;
+ return null;
}
throw Exception('Unknown complexity: $this');
}
diff --git a/playground/frontend/playground_components/lib/src/repositories/models/get_snippet_response.dart b/playground/frontend/playground_components/lib/src/repositories/models/get_snippet_response.dart
index 460b215c4f4..c935936898d 100644
--- a/playground/frontend/playground_components/lib/src/repositories/models/get_snippet_response.dart
+++ b/playground/frontend/playground_components/lib/src/repositories/models/get_snippet_response.dart
@@ -21,15 +21,15 @@ import '../../models/sdk.dart';
import 'shared_file.dart';
class GetSnippetResponse {
+ final Complexity? complexity;
final List<SharedFile> files;
- final Sdk sdk;
final String pipelineOptions;
- final Complexity complexity;
+ final Sdk sdk;
const GetSnippetResponse({
+ required this.complexity,
required this.files,
- required this.sdk,
required this.pipelineOptions,
- required this.complexity,
+ required this.sdk,
});
}
diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/util/string.dart
similarity index 79%
copy from playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
copy to playground/frontend/playground_components/lib/src/util/string.dart
index 35c3cf18100..924abcde1f2 100644
--- a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/example_loading_descriptor.dart
+++ b/playground/frontend/playground_components/lib/src/util/string.dart
@@ -16,10 +16,8 @@
* limitations under the License.
*/
-import 'package:equatable/equatable.dart';
-
-abstract class ExampleLoadingDescriptor with EquatableMixin {
- const ExampleLoadingDescriptor();
-
- Map<String, dynamic> toJson() => throw UnimplementedError();
+extension StringExtension on String {
+ List<String> splitNotEmpty(Pattern pattern) {
+ return split(pattern).where((s) => s.isNotEmpty).toList(growable: false);
+ }
}
diff --git a/playground/frontend/playground_components/lib/src/widgets/editor_textarea.dart b/playground/frontend/playground_components/lib/src/widgets/editor_textarea.dart
index 9714177ec94..571415a1e71 100644
--- a/playground/frontend/playground_components/lib/src/widgets/editor_textarea.dart
+++ b/playground/frontend/playground_components/lib/src/widgets/editor_textarea.dart
@@ -149,15 +149,12 @@ class _EditorTextAreaState extends State<EditorTextArea> {
}
int _getIndexOfContextLine() {
- int ctxLineNumber = widget.example!.contextLine;
- String contextLine = widget.codeController.text.split('\n')[ctxLineNumber];
+ final contextLine = widget.example!.contextLine;
+ final code = widget.codeController.code;
+ final fullCharIndex = code.lines.lines[contextLine].textRange.start;
+ final visibleCharIndex = code.hiddenRanges.cutPosition(fullCharIndex);
- while (contextLine == '') {
- ctxLineNumber -= 1;
- contextLine = widget.codeController.text.split('\n')[ctxLineNumber];
- }
-
- return widget.codeController.text.indexOf(contextLine);
+ return visibleCharIndex;
}
// This function made for more accuracy in the process of finding an exact line.
diff --git a/playground/frontend/playground_components/pubspec.yaml b/playground/frontend/playground_components/pubspec.yaml
index 7922c2bbec3..9183b6b4490 100644
--- a/playground/frontend/playground_components/pubspec.yaml
+++ b/playground/frontend/playground_components/pubspec.yaml
@@ -32,12 +32,13 @@ dependencies:
easy_localization_loader: ^1.0.0
equatable: ^2.0.5
flutter: { sdk: flutter }
- flutter_code_editor: ^0.1.3
+ flutter_code_editor: ^0.1.4 # Unlisted package, use direct link: https://pub.dev/packages/flutter_code_editor
flutter_markdown: ^0.6.12
flutter_svg: ^1.0.3
google_fonts: ^3.0.1
grpc: ^3.0.2
highlight: ^0.7.0
+ http: ^0.13.5
json_annotation: ^4.7.0
meta: ^1.7.0
protobuf: ^2.1.0
diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.dart
new file mode 100644
index 00000000000..5860ff7bb17
--- /dev/null
+++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/http_example_loader_test.dart
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:playground_components/playground_components.dart';
+import 'package:playground_components/src/controllers/example_loaders/http_example_loader.dart';
+
+import 'http_example_loader_test.mocks.dart';
+
+// A random small file at a specific revision.
+const _name = 'section-remote-info.yaml';
+const _path =
+ 'https://raw.githubusercontent.com/apache/beam/238356dade3df54ea3d3f84a7424fa5c99bf37a4/learning/katas/go/core_transforms/$_name';
+
+const _contents = '''
+id: 131788
+update_date: Mon, 27 Jul 2020 18:50:54 UTC
+''';
+
+const _sdk = Sdk.go;
+
+@GenerateMocks([ExampleCache])
+void main() {
+ test('HttpExampleLoader', () async {
+ final loader = HttpExampleLoader(
+ descriptor: HttpExampleLoadingDescriptor(
+ sdk: _sdk,
+ uri: Uri.parse(_path),
+ ),
+ exampleCache: MockExampleCache(),
+ );
+
+ final example = await loader.future;
+
+ // TODO(alexeyinkin): Compare whole objects when that gets to include all fields, https://github.com/apache/beam/issues/23979
+ expect(example.name, _name);
+ expect(example.sdk, _sdk);
+ expect(example.source, _contents);
+ expect(example.type, ExampleType.example);
+ expect(example.path, _path);
+ });
+}
diff --git a/playground/frontend/pubspec.lock b/playground/frontend/pubspec.lock
index 6e7da5f916a..bce3fe573ac 100644
--- a/playground/frontend/pubspec.lock
+++ b/playground/frontend/pubspec.lock
@@ -278,7 +278,7 @@ packages:
name: flutter_code_editor
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.3"
+ version: "0.1.4"
flutter_highlight:
dependency: transitive
description:
@@ -391,7 +391,7 @@ packages:
name: http
url: "https://pub.dartlang.org"
source: hosted
- version: "0.13.4"
+ version: "0.13.5"
http2:
dependency: transitive
description:
diff --git a/playground/frontend/test/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory_test.dart b/playground/frontend/test/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory_test.dart
new file mode 100644
index 00000000000..1867ae28d3a
--- /dev/null
+++ b/playground/frontend/test/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory_test.dart
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'dart:convert';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:playground/constants/params.dart';
+import 'package:playground/modules/examples/models/example_loading_descriptors/examples_loading_descriptor_factory.dart';
+import 'package:playground_components/playground_components.dart';
+
+const _viewOptionsMap = {
+ 'readonly': 'readonly1,readonly2',
+ 'show': 'show1,show2',
+ 'unfold': 'unfold1,unfold2',
+};
+
+const _viewOptions = ExampleViewOptions(
+ foldCommentAtLineZero: true,
+ foldImports: true,
+ readOnlySectionNames: ['readonly1', 'readonly2'],
+ showSectionNames: ['show1', 'show2'],
+ unfoldSectionNames: ['unfold1', 'unfold2'],
+);
+
+void main() {
+ final lazy = ExamplesLoadingDescriptorFactory.defaultLazyLoadDescriptors;
+
+ group('ExamplesLoadingDescriptorFactory', () {
+ test('defaultLazyLoadDescriptors', () {
+ final expected = {
+ Sdk.go: [
+ const CatalogDefaultExampleLoadingDescriptor(
+ sdk: Sdk.go,
+ )
+ ],
+ Sdk.java: [
+ const CatalogDefaultExampleLoadingDescriptor(
+ sdk: Sdk.java,
+ )
+ ],
+ Sdk.python: [
+ const CatalogDefaultExampleLoadingDescriptor(
+ sdk: Sdk.python,
+ )
+ ],
+ Sdk.scio: [
+ const CatalogDefaultExampleLoadingDescriptor(
+ sdk: Sdk.scio,
+ )
+ ],
+ };
+
+ expect(lazy, expected);
+ });
+
+ group('fromUriParts', () {
+ void testExamples(Iterable<_Example> examples) {
+ for (final example in examples) {
+ final result = ExamplesLoadingDescriptorFactory.fromUriParts(
+ params: example.params,
+ path: '',
+ );
+
+ expect(result, example.expected);
+ }
+ }
+
+ test('ContentExampleLoadingDescriptor', () {
+ testExamples([
+ _Example(
+ params: {
+ kExamplesParam: jsonEncode(
+ [
+ {
+ 'sdk': 'go',
+ 'content': 'go_content',
+ },
+ {
+ 'sdk': 'python',
+ 'content': 'python_content',
+ ..._viewOptionsMap,
+ },
+ ],
+ ),
+ },
+ expected: ExamplesLoadingDescriptor(
+ descriptors: const [
+ ContentExampleLoadingDescriptor(
+ content: 'go_content',
+ sdk: Sdk.go,
+ ),
+ ContentExampleLoadingDescriptor(
+ content: 'python_content',
+ sdk: Sdk.python,
+ viewOptions: _viewOptions,
+ ),
+ ],
+ lazyLoadDescriptors: lazy,
+ ),
+ ),
+ ]);
+ });
+
+ test('HttpExampleLoadingDescriptor', () {
+ testExamples([
+ _Example(
+ params: {
+ kExamplesParam: jsonEncode(
+ [
+ {
+ 'sdk': 'go',
+ 'example': 'http://',
+ },
+ {
+ 'sdk': 'python',
+ 'example': 'https://',
+ ..._viewOptionsMap,
+ },
+ ],
+ ),
+ },
+ expected: ExamplesLoadingDescriptor(
+ descriptors: [
+ HttpExampleLoadingDescriptor(
+ sdk: Sdk.go,
+ uri: Uri.parse('http://'),
+ ),
+ HttpExampleLoadingDescriptor(
+ sdk: Sdk.python,
+ uri: Uri.parse('https://'),
+ viewOptions: _viewOptions,
+ ),
+ ],
+ lazyLoadDescriptors: lazy,
+ ),
+ ),
+ ]);
+ });
+
+ test('StandardExampleLoadingDescriptor', () {
+ testExamples([
+ _Example(
+ params: {
+ kExamplesParam: jsonEncode(
+ [
+ {'example': 'SDK_GO'},
+ {'example': 'SDK_PYTHON/something', ..._viewOptionsMap},
+ ],
+ ),
+ },
+ expected: ExamplesLoadingDescriptor(
+ descriptors: const [
+ StandardExampleLoadingDescriptor(
+ path: 'SDK_GO',
+ ),
+ StandardExampleLoadingDescriptor(
+ path: 'SDK_PYTHON/something',
+ viewOptions: _viewOptions,
+ ),
+ ],
+ lazyLoadDescriptors: lazy,
+ ),
+ ),
+ ]);
+ });
+
+ test('UserSharedExampleLoadingDescriptor', () {
+ testExamples([
+ _Example(
+ params: {
+ kExamplesParam: jsonEncode(
+ [
+ {'example': ''},
+ {'example': '123'},
+ {'example': 'abc', ..._viewOptionsMap},
+ ],
+ ),
+ },
+ expected: ExamplesLoadingDescriptor(
+ descriptors: const [
+ UserSharedExampleLoadingDescriptor(
+ snippetId: '',
+ ),
+ UserSharedExampleLoadingDescriptor(
+ snippetId: '123',
+ ),
+ UserSharedExampleLoadingDescriptor(
+ snippetId: 'abc',
+ viewOptions: _viewOptions,
+ ),
+ ],
+ lazyLoadDescriptors: lazy,
+ ),
+ ),
+ ]);
+ });
+ });
+ });
+}
+
+class _Example {
+ final Map<String, dynamic> params;
+ final ExamplesLoadingDescriptor expected;
+
+ const _Example({
+ required this.params,
+ required this.expected,
+ });
+}
diff --git a/playground/frontend/test/modules/examples/models/example_token_type_test.dart b/playground/frontend/test/modules/examples/models/example_token_type_test.dart
new file mode 100644
index 00000000000..5f1ec8943f7
--- /dev/null
+++ b/playground/frontend/test/modules/examples/models/example_token_type_test.dart
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:playground/modules/examples/models/example_token_type.dart';
+
+void main() {
+ test('ExampleTokenType.fromToken', () {
+ const examples = {
+ //
+ 'http://': ExampleTokenType.http,
+ 'https://example.com/path': ExampleTokenType.http,
+
+ 'SDK_GO': ExampleTokenType.standard,
+ 'SDK_JAVA_something': ExampleTokenType.standard,
+ 'SDK_PYTHONNNN': ExampleTokenType.standard,
+ 'SDK_SCIO/something': ExampleTokenType.standard,
+
+ '': ExampleTokenType.userShared,
+ '123': ExampleTokenType.userShared,
+ 'abc': ExampleTokenType.userShared,
+ 'SDK_TYPESCRIPT': ExampleTokenType.userShared,
+ 'SDK_RUST': ExampleTokenType.userShared,
+ };
+
+ for (final example in examples.entries) {
+ final token = example.key;
+ final result = ExampleTokenType.fromToken(token);
+
+ expect(result, example.value, reason: token);
+ }
+ });
+}
diff --git a/website/www/site/layouts/shortcodes/playground.html b/website/www/site/layouts/shortcodes/playground.html
index 4dc3eaf09e7..7e9aa3dd7d3 100644
--- a/website/www/site/layouts/shortcodes/playground.html
+++ b/website/www/site/layouts/shortcodes/playground.html
@@ -10,6 +10,9 @@ See the License for the specific language governing permissions and
limitations under the License. See accompanying LICENSE file.
*/}}
{{/*
+
+Creates an embedded Playground with given examples.
+
Embedding example:
{{< playground height="700px" >}}
@@ -25,14 +28,32 @@ Embedding example:
{{ .Inner }}
</div>
{{ $snippetsList := slice }}
- {{ $divMatches := findRE "<div class=\"[^\"]+(playground-snippet)\"(.*)</div>" .Inner }}
+ {{ $divMatches := findRE "<div(\\s+)class=\"[^\"]+(playground-snippet)\"((.|\\s)*?)</div>" .Inner }}
{{ range $divMatches }}
- {{ $attributeRegex := "data-sdk=\"(?P<sdk>\\w+)\" data-example=\"([^\"]+)\"" }}
- {{ $sdk := replaceRE ".*data-sdk=\"(\\w+)\".*" "$1" . }}
- {{ $example := replaceRE ".*example=\"([^\"]+)\".*" "$1" . }}
- {{ $json := printf "%s%s%s%s%s" "{\"sdk\":\"" $sdk "\",\"example\":\"" $example "\"}" }}
- {{ $snippetsList = append $json $snippetsList }}
+ {{ $sdk := replaceRE "(.|\\s)*data-sdk=\"(\\w+)\"(.|\\s)*" "$2" . }}
+ {{ $example := replaceRE "(.|\\s)*example=\"([^\"]+)\"(.|\\s)*" "$2" . }}
+ {{ $dict := dict "sdk" $sdk "example" $example }}
+
+ {{ $readonlyRegex := "(.|\\s)*readonly=\"([_,a-zA-Z0-9]+)\"(.|\\s)*" }}
+ {{ if findRE $readonlyRegex . }}
+ {{ $readonly := replaceRE $readonlyRegex "$2" . }}
+ {{ $dict = merge $dict (dict "readonly" $readonly) }}
+ {{ end }}
+
+ {{ $showRegex := "(.|\\s)*show=\"([_a-zA-Z0-9]+)\"(.|\\s)*" }}
+ {{ if findRE $showRegex . }}
+ {{ $show := replaceRE $showRegex "$2" . }}
+ {{ $dict = merge $dict (dict "show" $show) }}
+ {{ end }}
+
+ {{ $unfoldRegex := "(.|\\s)*unfold=\"([_,a-zA-Z0-9]+)\"(.|\\s)*" }}
+ {{ if findRE $unfoldRegex . }}
+ {{ $unfold := replaceRE $unfoldRegex "$2" . }}
+ {{ $dict = merge $dict (dict "unfold" $unfold) }}
+ {{ end }}
+
+ {{ $snippetsList = append (jsonify $dict) $snippetsList }}
{{ end}}
{{ $snippets := printf "%s%s%s" "[" (delimit $snippetsList ",") "]" }}
diff --git a/website/www/site/layouts/shortcodes/playground_snippet.html b/website/www/site/layouts/shortcodes/playground_snippet.html
index 4c4ce501168..10574844201 100644
--- a/website/www/site/layouts/shortcodes/playground_snippet.html
+++ b/website/www/site/layouts/shortcodes/playground_snippet.html
@@ -9,4 +9,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. See accompanying LICENSE file.
*/}}
-{{ $sdk := .Get "language" }}{{ if eq $sdk "py" }}{{ $sdk = "python" }}{{ end }}<div class="language-{{ .Get "language" }} playground-snippet" data-sdk="{{ $sdk }}" data-example="{{ .Get "example" }}"></div>
+{{/*
+
+Creates an embedded Playground tab with a given example. Must be used within 'playground' shortcode
+because here only a div is created and not an iframe. It is 'playground' that actually creates
+an iframe.
+
+Required parameters:
+- example - the example ID or snippet ID.
+- language - the string to be passed as SDK to playground. 'py' translates to 'python'.
+
+Optional parameters:
+- readonly - comma-separated section names to make read-only.
+- show - section name, hides everything except it, makes the entire code read-only.
+- unfold - comma-separated section names, folds all blocks not overlapping with them.
+
+*/}}
+
+{{ $sdk := .Get "language" }}
+{{ if eq $sdk "py" }}
+ {{ $sdk = "python" }}
+{{ end }}
+<div
+ class="language-{{ .Get "language" }} playground-snippet"
+ data-sdk="{{ $sdk }}"
+ data-example="{{ .Get "example" }}"
+ {{ if .Get "readonly" }}
+ data-readonly="{{ .Get "readonly" }}"
+ {{ end }}
+ {{ if .Get "show" }}
+ data-show="{{ .Get "show" }}"
+ {{ end }}
+ {{ if .Get "unfold" }}
+ data-unfold="{{ .Get "unfold" }}"
+ {{ end }}
+></div>