From 60f5572ad333e7c1eddc54481ab0a627d0094331 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Tue, 7 Jul 2020 14:35:06 -0700 Subject: [PATCH 1/4] Don't HTML escape source code blocks in Markdown Adds a renderer in between to control whether or not we apply HTML escapes to source code blocks. Fixes #2252 --- lib/src/model/model_element.dart | 11 +++++++++++ lib/src/model/model_node.dart | 1 - lib/src/render/renderer_factory.dart | 9 +++++++++ lib/src/render/source_code_renderer.dart | 21 +++++++++++++++++++++ tool/grind.dart | 17 +++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 lib/src/render/source_code_renderer.dart diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index fd27a53e5e..4f389d2a93 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -26,6 +26,7 @@ import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as utils; import 'package:dartdoc/src/render/model_element_renderer.dart'; import 'package:dartdoc/src/render/parameter_renderer.dart'; +import 'package:dartdoc/src/render/source_code_renderer.dart'; import 'package:dartdoc/src/source_linker.dart'; import 'package:dartdoc/src/tuple.dart'; import 'package:dartdoc/src/utils.dart'; @@ -929,6 +930,9 @@ abstract class ModelElement extends Canonicalization ParameterRenderer get _parameterRendererDetailed => packageGraph.rendererFactory.parameterRendererDetailed; + SourceCodeRenderer get _sourceCodeRenderer => + packageGraph.rendererFactory.sourceCodeRenderer; + String get linkedParams => _parameterRenderer.renderLinkedParams(parameters); String get linkedParamsLines => @@ -1090,6 +1094,13 @@ abstract class ModelElement extends Canonicalization return __documentation; } + String _sourceCode; + + @override + String get sourceCode { + return _sourceCode ??= _sourceCodeRenderer.renderSourceCode(super.sourceCode); + } + bool canOverride() => element is ClassMemberElement || element is PropertyAccessorElement; diff --git a/lib/src/model/model_node.dart b/lib/src/model/model_node.dart index 406fe003ed..10e6575ff2 100644 --- a/lib/src/model/model_node.dart +++ b/lib/src/model/model_node.dart @@ -63,7 +63,6 @@ class ModelNode { var start = _sourceOffset - (_sourceOffset - i); var source = contents.substring(start, _sourceEnd); - source = const HtmlEscape().convert(source); source = model_utils.stripIndentFromSource(source); source = model_utils.stripDartdocCommentsFromSource(source); diff --git a/lib/src/render/renderer_factory.dart b/lib/src/render/renderer_factory.dart index 9f13aecf91..9dcef0fa16 100644 --- a/lib/src/render/renderer_factory.dart +++ b/lib/src/render/renderer_factory.dart @@ -10,6 +10,7 @@ import 'package:dartdoc/src/render/enum_field_renderer.dart'; import 'package:dartdoc/src/render/feature_renderer.dart'; import 'package:dartdoc/src/render/model_element_renderer.dart'; import 'package:dartdoc/src/render/parameter_renderer.dart'; +import 'package:dartdoc/src/render/source_code_renderer.dart'; import 'package:dartdoc/src/render/template_renderer.dart'; import 'package:dartdoc/src/render/type_parameters_renderer.dart'; import 'package:dartdoc/src/render/typedef_renderer.dart'; @@ -50,6 +51,8 @@ abstract class RendererFactory { ParameterRenderer get parameterRendererDetailed; + SourceCodeRenderer get sourceCodeRenderer; + TypeParametersRenderer get typeParametersRenderer; TypedefRenderer get typedefRenderer; @@ -102,6 +105,9 @@ class HtmlRenderFactory extends RendererFactory { @override FeatureRenderer get featureRenderer => FeatureRendererHtml(); + + @override + SourceCodeRenderer get sourceCodeRenderer => SourceCodeRendererHtml(); } class MdRenderFactory extends RendererFactory { @@ -152,4 +158,7 @@ class MdRenderFactory extends RendererFactory { @override FeatureRenderer get featureRenderer => FeatureRendererMd(); + + @override + SourceCodeRenderer get sourceCodeRenderer => SourceCodeRendererNoop(); } diff --git a/lib/src/render/source_code_renderer.dart b/lib/src/render/source_code_renderer.dart new file mode 100644 index 0000000000..17809fca92 --- /dev/null +++ b/lib/src/render/source_code_renderer.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; + +abstract class SourceCodeRenderer { + String renderSourceCode(String source); +} + +class SourceCodeRendererNoop extends SourceCodeRenderer { + @override + String renderSourceCode(String source) => source; +} + +class SourceCodeRendererHtml extends SourceCodeRenderer { + @override + String renderSourceCode(String source) { + return (const HtmlEscape()).convert(source); + } +} \ No newline at end of file diff --git a/tool/grind.dart b/tool/grind.dart index 1eedc559ff..f69239fb65 100644 --- a/tool/grind.dart +++ b/tool/grind.dart @@ -562,9 +562,26 @@ Future buildTestPackageDocs() async { testPackageDocsDir.absolute.path, Directory.current.path); } +@Task('Build generated test package docs in Markdown (with inherited docs and source code)') +@Depends(clean) +Future buildTestPackageDocsMd() async { + await _buildTestPackageDocs( + testPackageDocsDir.absolute.path, Directory.current.path, params: ['--format', 'md']); +} + @Task('Serve test package docs locally with dhttpd on port 8002') @Depends(buildTestPackageDocs) Future serveTestPackageDocs() async { + await startTestPackageDocsServer(); +} + +@Task('Serve test package docs (in Markdown) locally with dhttpd on port 8002') +@Depends(buildTestPackageDocsMd) +Future serveTestPackageDocsMd() async { + await startTestPackageDocsServer(); +} + +Future startTestPackageDocsServer() async { log('launching dhttpd on port 8002 for SDK'); var launcher = SubprocessLauncher('serve-test-package-docs'); await launcher.runStreamed(sdkBin('pub'), [ From 824c1a3596ee4628f233b6918b9dedb40ffd7e0a Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Tue, 7 Jul 2020 20:36:47 -0700 Subject: [PATCH 2/4] Code review fixes --- lib/src/render/source_code_renderer.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/render/source_code_renderer.dart b/lib/src/render/source_code_renderer.dart index 17809fca92..bfeb5cc3cd 100644 --- a/lib/src/render/source_code_renderer.dart +++ b/lib/src/render/source_code_renderer.dart @@ -1,9 +1,10 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:convert'; +/// Renderer for source code snippets extracted from source files. abstract class SourceCodeRenderer { String renderSourceCode(String source); } @@ -13,6 +14,7 @@ class SourceCodeRendererNoop extends SourceCodeRenderer { String renderSourceCode(String source) => source; } +/// [SourceCodeRenderer] that escapes characters for HTML. class SourceCodeRendererHtml extends SourceCodeRenderer { @override String renderSourceCode(String source) { From c8b526c85d5bfca18e846a16b13362b1ead2ffaf Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Tue, 7 Jul 2020 20:39:23 -0700 Subject: [PATCH 3/4] Remove unused import --- lib/src/model/model_node.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/model/model_node.dart b/lib/src/model/model_node.dart index 10e6575ff2..6ba32f4772 100644 --- a/lib/src/model/model_node.dart +++ b/lib/src/model/model_node.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'dart:convert'; - import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:dartdoc/src/model_utils.dart' as model_utils; From 4bf25e92743e5530d9a50ec101f580aeba159078 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Tue, 7 Jul 2020 20:48:59 -0700 Subject: [PATCH 4/4] dartfmt --- lib/src/model/model_element.dart | 3 ++- lib/src/render/source_code_renderer.dart | 2 +- tool/grind.dart | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 4f389d2a93..8a6ef03ae8 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -1098,7 +1098,8 @@ abstract class ModelElement extends Canonicalization @override String get sourceCode { - return _sourceCode ??= _sourceCodeRenderer.renderSourceCode(super.sourceCode); + return _sourceCode ??= + _sourceCodeRenderer.renderSourceCode(super.sourceCode); } bool canOverride() => diff --git a/lib/src/render/source_code_renderer.dart b/lib/src/render/source_code_renderer.dart index bfeb5cc3cd..82e4d56150 100644 --- a/lib/src/render/source_code_renderer.dart +++ b/lib/src/render/source_code_renderer.dart @@ -20,4 +20,4 @@ class SourceCodeRendererHtml extends SourceCodeRenderer { String renderSourceCode(String source) { return (const HtmlEscape()).convert(source); } -} \ No newline at end of file +} diff --git a/tool/grind.dart b/tool/grind.dart index f69239fb65..420a109ab2 100644 --- a/tool/grind.dart +++ b/tool/grind.dart @@ -555,18 +555,19 @@ Future serveTestExperimentsPackageDocs() async { 'test-package-docs-experiments'); } -@Task('Build generated test package docs (with inherited docs and source code)') +@Task('Build test package docs (HTML) with inherited docs and source code') @Depends(clean) Future buildTestPackageDocs() async { await _buildTestPackageDocs( testPackageDocsDir.absolute.path, Directory.current.path); } -@Task('Build generated test package docs in Markdown (with inherited docs and source code)') +@Task('Build test package docs (Markdown) with inherited docs and source code') @Depends(clean) Future buildTestPackageDocsMd() async { await _buildTestPackageDocs( - testPackageDocsDir.absolute.path, Directory.current.path, params: ['--format', 'md']); + testPackageDocsDir.absolute.path, Directory.current.path, + params: ['--format', 'md']); } @Task('Serve test package docs locally with dhttpd on port 8002')