diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 76c8589..f0c20e5 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -39,16 +39,16 @@ jobs: - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: - name: "analyzer_and_format; Dart 3.4.0; PKGS: packages/code_excerpt_updater, packages/code_excerpter, packages/excerpter, packages/inject_dartpad; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`" + name: "analyzer_and_format; Dart 3.4.0; PKGS: packages/excerpter, packages/inject_dartpad; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter-packages/inject_dartpad;commands:format-analyze" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/excerpter-packages/inject_dartpad;commands:format-analyze" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter-packages/inject_dartpad + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/excerpter-packages/inject_dartpad os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -59,32 +59,6 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - id: packages_code_excerpt_updater_pub_upgrade - name: packages/code_excerpt_updater; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: "packages/code_excerpt_updater; dart format --output=none --set-exit-if-changed ." - run: "dart format --output=none --set-exit-if-changed ." - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: "packages/code_excerpt_updater; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - id: packages_code_excerpter_pub_upgrade - name: packages/code_excerpter; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: "packages/code_excerpter; dart format --output=none --set-exit-if-changed ." - run: "dart format --output=none --set-exit-if-changed ." - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: "packages/code_excerpter; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - id: packages_excerpter_pub_upgrade name: packages/excerpter; dart pub upgrade run: dart pub upgrade @@ -112,16 +86,16 @@ jobs: if: "always() && steps.packages_inject_dartpad_pub_upgrade.conclusion == 'success'" working-directory: packages/inject_dartpad job_003: - name: "analyzer_and_format; Dart dev; PKGS: packages/code_excerpt_updater, packages/code_excerpter, packages/excerpter, packages/inject_dartpad; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`" + name: "analyzer_and_format; Dart dev; PKGS: packages/excerpter, packages/inject_dartpad; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter-packages/inject_dartpad;commands:format-analyze" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/excerpter-packages/inject_dartpad;commands:format-analyze" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter-packages/inject_dartpad + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/excerpter-packages/inject_dartpad os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -132,32 +106,6 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - id: packages_code_excerpt_updater_pub_upgrade - name: packages/code_excerpt_updater; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: "packages/code_excerpt_updater; dart format --output=none --set-exit-if-changed ." - run: "dart format --output=none --set-exit-if-changed ." - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: "packages/code_excerpt_updater; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - id: packages_code_excerpter_pub_upgrade - name: packages/code_excerpter; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: "packages/code_excerpter; dart format --output=none --set-exit-if-changed ." - run: "dart format --output=none --set-exit-if-changed ." - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: "packages/code_excerpter; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - id: packages_excerpter_pub_upgrade name: packages/excerpter; dart pub upgrade run: dart pub upgrade @@ -185,16 +133,16 @@ jobs: if: "always() && steps.packages_inject_dartpad_pub_upgrade.conclusion == 'success'" working-directory: packages/inject_dartpad job_004: - name: "unit_test; Dart 3.4.0; PKGS: packages/code_excerpt_updater, packages/code_excerpter, packages/excerpter; `dart test`" + name: "unit_test; Dart 3.4.0; PKG: packages/excerpter; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter;commands:test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/excerpter;commands:test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter + os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0;packages:packages/excerpter os:ubuntu-latest;pub-cache-hosted;sdk:3.4.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -205,24 +153,6 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - id: packages_code_excerpt_updater_pub_upgrade - name: packages/code_excerpt_updater; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: packages/code_excerpt_updater; dart test - run: dart test - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - id: packages_code_excerpter_pub_upgrade - name: packages/code_excerpter; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: packages/code_excerpter; dart test - run: dart test - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - id: packages_excerpter_pub_upgrade name: packages/excerpter; dart pub upgrade run: dart pub upgrade @@ -237,16 +167,16 @@ jobs: - job_002 - job_003 job_005: - name: "unit_test; Dart dev; PKGS: packages/code_excerpt_updater, packages/code_excerpter, packages/excerpter; `dart test`" + name: "unit_test; Dart dev; PKG: packages/excerpter; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter;commands:test" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/excerpter;commands:test" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/code_excerpt_updater-packages/code_excerpter-packages/excerpter + os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:packages/excerpter os:ubuntu-latest;pub-cache-hosted;sdk:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -257,24 +187,6 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - id: packages_code_excerpt_updater_pub_upgrade - name: packages/code_excerpt_updater; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - name: packages/code_excerpt_updater; dart test - run: dart test - if: "always() && steps.packages_code_excerpt_updater_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpt_updater - - id: packages_code_excerpter_pub_upgrade - name: packages/code_excerpter; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/code_excerpter - - name: packages/code_excerpter; dart test - run: dart test - if: "always() && steps.packages_code_excerpter_pub_upgrade.conclusion == 'success'" - working-directory: packages/code_excerpter - id: packages_excerpter_pub_upgrade name: packages/excerpter; dart pub upgrade run: dart pub upgrade diff --git a/doc/code-excerpts.md b/doc/code-excerpts.md index 6971a61..0f8ec86 100644 --- a/doc/code-excerpts.md +++ b/doc/code-excerpts.md @@ -3,206 +3,7 @@ title: Code excerpts description: Code excerpts --- -# Code excerpts +The docs that lived here now live in +[the README of the new package that implements code excerpts][excerpter]. -Many site pages contain code excerpts, and these excerpts are kept in sync with -their originating [examples][] source file by use of the tools mentioned in this -page. - -# How do I ... - -This page answers the most common "how-to" questions related to code excerpts. - -## How do I associate a code block with its source? - -To associate a markdown code block with (a region of) a source file, use a -`` [processing instruction][] (or two). Here is an example taken -from [src/docs/development/ui/interactive.md][] (flutter/website): - - - ```dart - class FavoriteWidget extends StatefulWidget { - @override - _FavoriteWidgetState createState() => _FavoriteWidgetState(); - } - ``` - -The excerpted code comes from the region named `FavoriteWidget` in the file -[layout/lakes/interactive/lib/main.dart][]. Regions are marked using the -`#docregion` syntax. For example: - -```dart -... -// #docregion FavoriteWidget -class FavoriteWidget extends StatefulWidget { - @override - _FavoriteWidgetState createState() => _FavoriteWidgetState(); -} -// #enddocregion FavoriteWidget -... -``` - -## What's the syntax for instructions and docregions? - -For the full instruction syntax, see [\ syntax][], from the -[code_excerpt_updater][] tool README. For information about `docregion`s see the -[code_excerpter][] tool README. - -The tools have several useful features (not covered here), to help make your -life easier. For example, if all of the files in your page come from a single -folder, which can often be the case, then you can set the path base once, and -then use relative file paths in subsequent instructions, like this: - - - ... - - ```dart - // Some code - ``` - - -## How do I know if the code excerpts are fresh / synced? - -Use the `./tool/refresh-code-excerpts.sh` script to ensure that in-page code -excerpts are fresh relative to the source files that they are extracted from. - -The refresh script uses the following tools under the hood: - - 1. [code_excerpter][] scans all source files and creates code excerpt files. - 2. [code_excerpt_updater][] scans the site pages, and refreshes code excerpts - using the generated excerpt files. - -## How do I edit an existing code excerpt? - -You're working on a site page and you've found a code excerpt that needs to be -updated? Trace the excerpt back to its origin and make the changes in the -originating source. Then run the code-excerpt [refresh script](#refresh). - -## How do I add a new excerpt to an existing example file - - 1. Locate the source file. - 1. Identify the code region in that file. - 1. Choose a region name. - 1. Add `#docregion ` `#enddocregion ` tags. - -## Can I excerpt an entire source file? - -To excerpt an entire source file simply omit the region name from the processing -instruction. - -> **Note:** When you omit the region name, it defaults to `''`, the empty region name. - -> **Pro tip:** By default, the empty region name (`''`) corresponds to the -> entire file, but you can change that by using explicit `docregion` tags with -> `''` as a region name argument. - -## How do I write a test for my code excerpt? - -**Related:** [Should I write a test?][]. - -As is customary, test files live under `examples/my_example_project/test`. - -If your code excerpt is small, embedded your code excerpt (bracketed by -`docregion` tags) directly in the test like this [hello-world example][]: - -```dart - test('hello world', () { - // #docregion hello-world - void main() { - print('Hello, World!'); - } - - // #enddocregion hello-world - expect(main, prints('Hello, World!\n')); - }); -``` - -If you are testing lots of code used, for example, as part of a tutorial, then -follow the recommended Dart practice of placing project code (with `docregion` -tags) under `lib`, and tests under `test`. - - -## Some code excerpts contain `[!...!]`, what's that? - -Code enclosed in the special syntax `[!...!]` will be highlighted. - -For example, the code - -``` -int [!foo!] = 1; -``` - -will display as - -> int foo = 1; - -**Legacy:** Markers like `[[highlight]]...[[/highlight]]` and -`[[strike]]...[[/strike]]` (and more) are still supported in some repos. - -## How can I highlight part of a code excerpt - -Since code excerpts are synced, you can't embed the highlight markers by hand. -Instead use the `replace` argument, for example: - - - ``` - int [!foo!] = 1; - ``` - -> **Note:** `$&` is the [regular expression][] syntax corresponding to the fully -> string that was matched. Groups and the group match syntax, such as `$1`, -> `$2`, etc. are also supported. - -For more information about the `replace` argument syntax see -[code_excerpt_updater][]. - -# Advanced features - -## Code diffs - -To make use of code diffs in a given page, add the following to the page's front matter (or archive the equivalent setting using `_config.yml` file defaults): - -```yaml -diff2html: true -``` - -A `` instruction will produce a code diff when two files are named using either of the following methods: - -- Use the `diff-with` argument: `diff-with="path/to/second/file.ext"`. -- Use the bash brace syntax in the instruction's first unnamed argument: - `path/to/{first,second}/file.ext`. - -## Site-global and file-scope code excerpt transformations - -The [code_excerpt_updater][] tool can apply site-global, file-scope and -code-excerpt specific `replace` transformations. - -Site-global transformations are applied to all code excerpts. See -`./tool/refresh-code-excerpts.sh` for an annotated list of replace expressions passed -along with the `--replace` command line argument of the `code_excerpt_updater` command. - -File-scope replace instructions can be placed anywhere in a doc page. Most often -the appear at the beginning of the page. Here is an example from -[src/_guides/language/effective-dart/design.md][]: - -```html - -``` - -This particular transformation strips the trailing version number off of class names. For -example `String0` becomes `String`, and `Point1`, `Point2`, etc. all become `Point`. This -allows the originating source file to contain multiple versions of the same class. - - -[\ syntax]: https://github.com/chalin/code_excerpt_updater#3-code-excerpt-syntax -[code_excerpt_updater]: https://github.com/dart-lang/site-shared/tree/main/packages/code_excerpt_updater -[code_excerpter]: https://github.com/dart-lang/site-shared/tree/main/packages/code_excerpter -[examples]: examples.md -[hello-world example]: https://github.com/dart-lang/site-www/blob/main/examples/misc/test/samples_test.dart -[layout/lakes/interactive/lib/main.dart]: https://github.com/flutter/website/blob/main/examples/layout/lakes/interactive/lib/main.dart?raw=1 -[markdown_with_code_excerpts.rb]: src/_plugins/markdown_with_code_excerpts.rb -[processing instruction]: https://en.wikipedia.org/wiki/Processing_Instruction -[regular expression]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions -[Should I write a test?]: examples#should-i-write-a-test -[src/_guides/language/effective-dart/design.md]: https://github.com/dart-lang/site-www/blob/main/src/_guides/language/effective-dart/design.md?raw=1 -[src/docs/development/ui/interactive.md]: https://github.com/flutter/website/blob/main/src/docs/development/ui/interactive.md?raw=1 +[excerpter]: ../packages/excerpter/README.md diff --git a/packages/code_excerpt_updater/.gitignore b/packages/code_excerpt_updater/.gitignore deleted file mode 100644 index d0f2d21..0000000 --- a/packages/code_excerpt_updater/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# Files and directories created by pub -.dart_tool -.pub/ -build/ -packages -# Remove the following pattern if you wish to check in your lock file -pubspec.lock - -# Files created by dart2js -*.dart.js -*.part.js -*.js.deps -*.js.map -*.info.json - -# Directory created by dartdoc -doc/api/ - -# JetBrains IDEs -.idea/ -*.iml -*.ipr -*.iws diff --git a/packages/code_excerpt_updater/CHANGELOG.md b/packages/code_excerpt_updater/CHANGELOG.md deleted file mode 100644 index 426126c..0000000 --- a/packages/code_excerpt_updater/CHANGELOG.md +++ /dev/null @@ -1,201 +0,0 @@ -# Changelog - -## 1.1.1 - -- Support YAML excerpt files with a specified excerpt border character as the - value of the `#border` map key. If present, all code excerpt lines will be - assumed to be prefixed withe the border character in the YAML file. The - app will strip out the border before updating docs with excerpt code. - - Here is a sample YAML excerpt file: - - ```yaml - '#border': '|' - 'main': |+ - |void main() => print('$greeting $scope'); - ``` - - Note the leading `|` as the first character of the `main` code excerpt. - -## 1.1.0 - unpublished - -## 1.0.1 - -- Bug fix: reintroduce support for empty plaster string argument. - -## 1.0.0 - -- First Dart-2-only release. No code changes. - -## 0.19.2 - -- Last Dart 1 compatible version. -- Add `--log-fine` option. - -## 0.19.1 - -- Support `remove` argument for diff instructions. - -## 0.19.0 - -- Support `skip="+/-n"` and `take="+/-n"` arguments. - -## 0.18.1 - -- Support `from` and `to` for non-diff code-excerpt instructions. - -## 0.18.0 - -- BREAKING CHANGE: Respect code-excerpt instruction argument order. - -## 0.17.1, 0.17.2 - -- Internal refactoring: e.g., use `Matcher` rather than `RegExp` as diff argument types. - -## 0.17.0 - -- As an alternative to the `diff-with` argument, add support for the Bash path - brace syntax. - -## 0.16.1 - -- Code refactorings. - -## 0.16.0 - -- Fully support the diff `from` argument. - -## 0.15.0 - -- Support `diff-u="NUM"` arguments for diff instructions. - -## 0.14.0 - -- Support diff of code regions. - -## 0.13.0 - -- Remove docregion tags from diff source files before performing the diff (#40). - -## 0.12.0 - -- Support code blocks between `{% foo ... %}` and `{% endfoo %}`. - This has been added, in particular to support `diff` tags. - -## 0.11.0 - -- Support `--exclude=`. - -## 0.10.1 - -- Fix type error. - -## 0.10.0 - -- Command returns a non-zero exit code if errors occur during file processing, - or if fragments were refreshed and `--fail-on-refresh` is requested. - -## 0.9.2 - -- Cleanup of pubspec package dependencies. - -## 0.9.1 - -- Support globally set plaster template using command line option `--plaster TEMPLATE`, - and plaster as a set instruction. - -## 0.9.0 - -- Support reading excerpts from `*.excerpt.yaml` files when the new `--yaml` flag is used. -- Support `plaster` attributes. For legacy excerpts, only `plaster="none"` is recognized. - -## 0.8.1 - -- Support `code-excerpt` instructions as the first line - in a markdown list that starts with `-` or `*`. - -## 0.8.0 - -- Deprecate processing instruction syntax without `?` before the closing `>`. -- Support strip-whitespace syntax `{%-...-%}` for prettify tags. - -## 0.7.2 - -- Accept `{% prettify %}` with more than one argument. - -## 0.7.1 - -- Strictly match code block marker start/end kinds. - E.g., now only `{% endprettify %}` is accepted as - the end of a prettify code block (not a triple backtick). - In this way prettify blocks can contain triple backtick markers. - -## 0.7.0 - -- Support `code-excerpt` `remove` attribute. - -## 0.6.1 - -- Add `class` as a recognized `code-excerpt` attribute. - -## 0.6.0 - -- Support `code-excerpt` `retain` attribute. -- Report an error for unrecognized `code-excerpt` attributes. - -## 0.5.3 - -- Don't warn about instructions having a `class` - argument but no `title` since these are processed - by other tools. - -## 0.5.2 - -- Support the `--replace="/.../.../g; ..."` command line option. - -## 0.5.1 - -- Support the following special characters in replace arguments: - `\t`, `\n`, and hexadecimal character codes `\xHH`. - -## 0.5.0 - -- Support global replace instruction. - -## 0.4.1 - -- Fix: a `replace` regexp with `}` would break the parsing of `code-excerpt` args. - -## 0.4.0 - -- Support multiple semi-colon separated "/foo/bar/g" expressions as arguments to `replace`. - -## 0.3.1 - -- Support escaped backslash characters (`\/`) in the replace expression of - replace attributes; e.g., `replace="/(foo)/$&\/bar/g"` will replace - `foo` by `foo/bar`. - -## 0.3.0 - -- Add support for code blocks braced between `{% prettify opt-lang %}` and - `{% endprettify %}`, as used in site-www. -- Add support for `$&` is replacement expressions of the `replace` attribute. - -## 0.2.0 - -- Add support for `code-excerpt` `replace` attributes having arguments of the form - **/_regex_/_replacement_/g**. Like in JavaScript, _replacement_ can contain - match capture placeholders `$1`, `$2`, etc. `$$` escapes `$`. - -## 0.1.0 - -- When a code excerpt consists of an entire file, and no corresponding fragment - file is found, an attempt is made to find the file in source directory. -- Any `#docregion` tags that appear in file diffs are filtered. - -## 0.0.1 - -- First public version, based on - [github.com/chalin/api_doc_updater](https://github.com/chalin/api_doc_updater). - diff --git a/packages/code_excerpt_updater/LICENSE b/packages/code_excerpt_updater/LICENSE deleted file mode 100644 index 83f8d1c..0000000 --- a/packages/code_excerpt_updater/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2017 Dart Project Authors https://www.dartlang.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/packages/code_excerpt_updater/README.md b/packages/code_excerpt_updater/README.md deleted file mode 100644 index 1b14ca8..0000000 --- a/packages/code_excerpt_updater/README.md +++ /dev/null @@ -1,253 +0,0 @@ -# Markdown code-block updater - -This is the repo for a simple _line-based_ updater for markdown code-blocks preceded by XML -processor instructions of the form ``. Dart (`.dart`), markdown (`.md`), and -Jade (`.jade`) files are processed. For Dart source files, code blocks in API comments are updated. - -## 1. Installation - -```shell -pub global activate --source git https://github.com/chalin/code_excerpt_updater.git -``` - -## 2. Usage - -``` -Usage: code_excerpt_updater [OPTIONS] file_or_directory... - - --exclude= Paths to exclude when processing a directory recursively. - Dot files and directorys are always excluded. - - --fail-on-refresh Report a non-zero exit code if a fragment is refreshed. --p, --fragment-dir-path PATH to directory containing code fragment files - (defaults to "", that is, the current working directory). - --h, --help Show command help. --i, --indentation NUMBER. Default number of spaces to use as indentation for code inside code blocks. - (defaults to "0") - --q, --src-dir-path PATH to directory containing code used in diffs - (defaults to "", that is, the current working directory). - --w, --write-in-place Write updates to files in-place. - --[no-]escape-ng-interpolation Escape Angular interpolation syntax {{...}} as {!{...}!}. - (defaults to on) - - --plaster TEMPLATE. Default plaster template to use for all files. - For example, "// Insert your code here"; use "none" to remove plasters. - - --replace REPLACE-EXPRESSIONs. Global replace argument. See README for syntax. - --yaml Read excerpts from *.excerpt.yaml files. -``` - -Returns a non-zero exit code errors occur during file processing, or if fragments were refreshed and -`--fail-on-refresh` is requested. - -## 3. `` syntax - -### a. Code fragment - -The instruction comes in three forms. The first (and most common) form must immediately precede a markdown code block: - - - - ``` - ... - ``` - -The first (unnamed) argument defines a path to a fragment file. The argument can optionally name a code fragment region -— any non-word character sequences (`\w+`) in the region name are converted to a hyphen. - -Recognized arguments are: - -- `from="string|/regex/"`: skips the initial lines until one is found matching the given pattern. -- `region`, a code fragment region name. -- `replace="/regexp/replacement/g;..."` defines one or more semi-colon separated [regular expression][]/replacement - expression pairs for use in a global search-and-replace applied to the code excerpt. - The replacement expression can contain capture group syntax `$&`, `$1`, `$2`, ... . -- `remove="string|/regexp/"`: remove the lines, from the identified code excerpt file, which contain the given string - or match _regexp_. To match a string starting with a slash, escape it. -- `retain="string|/regexp/"`: retain the lines, from the identified code excerpt file, which contain the given string - or match _regexp_. To match a string starting with a slash, escape it. -- `indent-by` defines the number of spaces to be used to indent the code in the code block. - (Default is no indentation.) -- `path-base`, when provided, must be the only argument. Its use is described below in the second instruction form. -- `plaster="..."` determines how plaster marker lines are handled in excerpts. When set to "none", the plaster marker - lines are removed. Otherwise, the attribute value defines a plaster template, possibly containing `$defaultPlaster`. - Examples: `plaster="/* $defaultPlaster */"`, `plaster="/* add your code here */"`. - When using legacy excerpts, the only supported value of this attribute is "none". - The default plaster is `···`, contained in a language-specific comment that is determined from the excerpt directive. - The language is the code-block language, if specified, otherwise it is taken to be the excerpt path extension. -- `skip="n"`: skips the first _n_ lines of the excerpt when _n_ is non-negative; drops (skips) the last - _n_ lines otherwise. -- `take="n"`: takes the first _n_ lines of the excerpt when _n_ is non-negative; takes the last - _n_ lines otherwise. -- `to="string|/regex/"`: skips the lines after the first line found matching the given pattern. - -Notes: -- Arguments are processed in the order they appear. This is significant for arguments like - `replace`, `remove`, etc. -- The `` instruction can optionally be preceded by an single-line comment - token. Namely either `//` or `///`. -- Path, and arguments if given, must be enclosed in double quotes. -- It is a limitation of processing instructions that it cannot contain a `>` character. - This limitation can be overcome in some situations: e.g., in a regexp, use `\x3E` as an encoding of `>`. -- If both `retain` and `replace` arguments are provided, the `retain` filter is always applied first. - -### b. Code diff - -The second form of the instruction must also be followed by a code block: - - - ``` - ... - ``` - -If you diff files whose paths share a prefix and/or suffix, then you can drop the -`diff-with` argument and use the Bash path-brace syntax instead. For example: - - - ``` - ... - ``` - -These are the optional arguments (usage is explained further below): - -- `from="regexp"` -- `to="regexp"` -- `diff-u="NUM"` - -When the code_excerpt_updater is run, it will update the content of the code -block with the output of `diff -u path/filtered_file1.ext path2/filtered_file2.ext2` truncated at the first diff -output line that matches the `to` regular expression, where the `filtered_file*.ext*` represents the corresponding -file `file*.ext*` but with docregion tags removed. When an optional region name is provided, then the named regions -(the same in both files) are compared. - -If `diff-u="NUM"` is used, then the diff command is called with the `-U NUM` flag instead of `-u`. - -### c. Set instruction - -Use a set instruction to globally set a path base, or a replace expression (using the syntax described above). - -A global **replace** instructions applies to all subsequence code-excerpt instructions. To reset, use an -empty replace argument. If a code-excerpt instruction has a replace argument, the global replace -is applied after the code-excerpt-specific replace. - -Here is an example of setting a **path base**: - -``` - -``` - -Following this instruction, the paths to file fragments will be interpreted relative to the `path-base` argument. - -### Limitations - -XML processing instructions cannot contain `>`. In particular this means that attribute values cannot contain `>`, -which is a limitation for the diff `from` and `to` regular expressions. - -## 4. Code excerpt lookup and updating - -The updater does not create code fragment files. It does expect such files to -exist and be named following the conventions described below. - -For a directive like ``, the updater will search the -fragment folder, for a file named: - -- `dir/file-rname.ext.txt`
- or -- `dir/file.ext.txt`
- if the region is omitted - -If no such fragment is found, it will search the source directory (`--src-dir-path`) for a file named: - -- `dir/file.ext` - -If the updater finds a (fragment or original source) file, it will replace the lines contained within -the markdown code block with those from that file, indenting each -fragment file line as specified by the `indent-by` argument. - -For example, if `hello.dart.txt` contains the line "print('Hi');" then - -``` -/// -/// ```dart -/// print('Bonjour'); -/// ``` -``` - -will be updated to - -``` -/// -/// ```dart -/// print('Hi'); -/// ``` -``` - -## 5. Example - -Consider the following API doc excerpt from the -[NgStyle](https://webdev.dartlang.org/api/angular/angular.common/NgStyle-class) class. - -```dart - /// ### Examples - /// - /// Try the [live example][ex] from the [Template Syntax][guide] page. Here are - /// the relevant excerpts from the example's template and the corresponding - /// component class: - /// - /// - /// ```html - /// ``` - /// - /// - /// ```dart - /// ``` -``` - -Given an appropriate path to the folder containing code fragment files, this -update tool would generate: - -```dart - /// ### Examples - /// - /// Try the [live example][ex] from the [Template Syntax][guide] page. Here are - /// the relevant excerpts from the example's template and the corresponding - /// component class: - /// - /// - /// ```html - ///
- ///

Change style of this text!

- /// - /// | - /// | - /// - /// - ///

Style set to: '{{styleP.style.cssText}}'

- ///
- /// ``` - /// - /// - /// ```dart - /// bool isItalic = false; - /// bool isBold = false; - /// String fontSize = 'large'; - /// String fontSizePx = '14'; - /// - /// Map setStyle() { - /// return { - /// 'font-style': isItalic ? 'italic' : 'normal', - /// 'font-weight': isBold ? 'bold' : 'normal', - /// 'font-size': fontSize - /// }; - /// } - /// ``` -``` - -## 6. Tests - -Repo tests can be launched from `test/main.dart`. - -[regular expression]: https://api.dartlang.org/stable/dart-core/RegExp-class.html diff --git a/packages/code_excerpt_updater/analysis_options.yaml b/packages/code_excerpt_updater/analysis_options.yaml deleted file mode 100644 index b29fbd0..0000000 --- a/packages/code_excerpt_updater/analysis_options.yaml +++ /dev/null @@ -1,5 +0,0 @@ -include: package:analysis_defaults/analysis.yaml - -analyzer: - exclude: - - test_data/ diff --git a/packages/code_excerpt_updater/bin/code_excerpt_updater.dart b/packages/code_excerpt_updater/bin/code_excerpt_updater.dart deleted file mode 100644 index 4856b5c..0000000 --- a/packages/code_excerpt_updater/bin/code_excerpt_updater.dart +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2017. All rights reserved. Use of this source code -// is governed by a MIT-style license that can be found in the LICENSE file. - -import 'dart:async'; -import 'dart:io' as io; - -import 'package:code_excerpt_updater/code_excerpt_updater_cli.dart'; - -/// See [UpdaterCLI]. -Future main(List args) async { - final updater = UpdaterCLI.fromArgs(args); - await updater.process(); - final msg = 'Processed ${updater.numFiles} Dart/Jade/Markdown files: ' - '${updater.numUpdatedFrag} out of ' - '${updater.numSrcDirectives} fragments needed updating.'; - print(msg); - final exitCode = updater.numErrors > 0 - ? updater.numErrors - : updater.failOnRefresh && updater.numUpdatedFrag > 0 - ? updater.numUpdatedFrag - : 0; - io.exitCode = exitCode; -} diff --git a/packages/code_excerpt_updater/lib/code_excerpt_updater_cli.dart b/packages/code_excerpt_updater/lib/code_excerpt_updater_cli.dart deleted file mode 100644 index f071d5e..0000000 --- a/packages/code_excerpt_updater/lib/code_excerpt_updater_cli.dart +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2017. All rights reserved. Use of this source code -// is governed by a MIT-style license that can be found in the LICENSE file. - -import 'dart:async'; -import 'dart:io'; - -import 'package:args/args.dart'; -import 'package:logging/logging.dart'; - -import 'src/code_excerpt_updater.dart'; -import 'src/logger.dart'; - -const _commandName = 'code_excerpt_updater'; -final _dotPathRe = RegExp(r'(^|/)\..*($|/)'); -final _validExt = RegExp(r'\.(dart|jade|md)$'); - -/// Processes `.dart` and `.md` files, recursively traverses directories -/// using [Updater]. See this command's help for CLI argument details. -class UpdaterCLI { - static const _logFineFlagName = 'log-fine'; - static const _escapeNgInterpolationFlagName = 'escape-ng-interpolation'; - static const _excludeFlagName = 'exclude'; - static const _failOnRefresh = 'fail-on-refresh'; - static const _fragmentDirPathFlagName = 'fragment-dir-path'; - static const _inPlaceFlagName = 'write-in-place'; - static const _indentFlagName = 'indentation'; - static const _plasterFlagName = 'plaster'; - static const _srcDirPathFlagName = 'src-dir-path'; - static const _yamlFlagName = 'yaml'; - - static const _defaultPath = - '(defaults to "", that is, the current working directory)'; - static const _replaceName = 'replace'; - - static final _parser = ArgParser() - ..addFlag(_logFineFlagName) - ..addMultiOption(_excludeFlagName, - help: 'Paths to exclude when processing a directory recursively.\n' - 'Dot files and directories are always excluded.', - valueHelp: 'PATH_REGEXP,...') - ..addFlag(_failOnRefresh, - negatable: false, - help: 'Report a non-zero ' - 'exit code if a fragment is refreshed.') - ..addOption(_fragmentDirPathFlagName, - abbr: 'p', - help: - 'PATH to directory containing code fragment files\n$_defaultPath.') - ..addFlag('help', abbr: 'h', negatable: false, help: 'Show command help.') - ..addOption( - _indentFlagName, - abbr: 'i', - defaultsTo: '0', - help: 'NUMBER. Default number of spaces to use as indentation for code ' - 'inside code blocks.', - ) - ..addOption(_srcDirPathFlagName, - abbr: 'q', - help: 'PATH to directory containing code used in diffs\n$_defaultPath.') - ..addFlag(_inPlaceFlagName, - abbr: 'w', negatable: false, help: 'Write updates to files in-place.') - ..addFlag(_escapeNgInterpolationFlagName, - defaultsTo: true, - help: 'Escape Angular interpolation syntax {{...}} as {!{...}!}.') - ..addOption( - _plasterFlagName, - help: 'TEMPLATE. Default plaster template to use for all files.\n' - 'For example, "// Insert your code here"; use "none" to remove plasters.', - ) - ..addOption( - _replaceName, - help: 'REPLACE-EXPRESSIONS. Global replace argument. ' - 'See README for syntax.', - ) - ..addFlag(_yamlFlagName, - negatable: false, help: 'Read excerpts from *.excerpt.yaml files.'); - - final bool escapeNgInterpolation; - final List excludePathRegExpStrings; - final List excludePathRegExp; - final bool excerptsYaml; - final bool failOnRefresh; - final String fragmentDirPath; - final String replaceExpr; - final String srcDirPath; - final String? plasterTemplate; - final bool inPlaceFlag; - final int indentation; - final List pathsToFileOrDir; - final Level? logLevel; - - int numErrors = 0; - int numFiles = 0; - int numSrcDirectives = 0; - int numUpdatedFrag = 0; - - UpdaterCLI._( - this.escapeNgInterpolation, - this.excludePathRegExpStrings, - this.excludePathRegExp, - this.excerptsYaml, - this.failOnRefresh, - this.fragmentDirPath, - this.replaceExpr, - this.srcDirPath, - this.plasterTemplate, - this.inPlaceFlag, - this.indentation, - this.pathsToFileOrDir, - this.logLevel); - - factory UpdaterCLI.fromArgs(List argsAsStrings) { - final ArgResults args; - - try { - args = _parser.parse(argsAsStrings); - } on FormatException catch (e) { - print('${e.message}\n'); - _printUsageAndExit(_parser, exitCode: 64); - } - - bool flag(String name) => args[name] as bool? ?? false; - - final pathsToFileOrDir = args.rest; - - if (flag('help')) _printHelpAndExit(_parser); - - String str(String name) => args[name] as String? ?? ''; - - var i = 0; - if (args[_indentFlagName] != null) { - try { - i = int.parse(str(_indentFlagName)); - } on FormatException { - _printUsageAndExit(_parser, - msg: '$_indentFlagName: invalid value "${args[_indentFlagName]}"'); - } - } - final indentation = i; - - final logLevel = flag(_logFineFlagName) ? Level.FINE : null; - - if (pathsToFileOrDir.isEmpty) { - _printUsageAndExit(_parser, msg: 'Expecting one or more path arguments'); - } - - final escapeNgInterpolation = flag(_escapeNgInterpolationFlagName); - final excludePathRegExpStrings = args[_excludeFlagName] as List; - final excerptsYaml = flag(_yamlFlagName); - final failOnRefresh = flag(_failOnRefresh); - final fragmentDirPath = str(_fragmentDirPathFlagName); - final inPlaceFlag = flag(_inPlaceFlagName); - final plasterTemplate = args[_plasterFlagName] == null - ? null - : args[_plasterFlagName] as String; - final replaceExpr = str(_replaceName); - final srcDirPath = str(_srcDirPathFlagName); - - final excludePathRegExp = [ - _dotPathRe, - ...excludePathRegExpStrings.map(RegExp.new) - ]; - - return UpdaterCLI._( - escapeNgInterpolation, - excludePathRegExpStrings, - excludePathRegExp, - excerptsYaml, - failOnRefresh, - fragmentDirPath, - replaceExpr, - srcDirPath, - plasterTemplate, - inPlaceFlag, - indentation, - pathsToFileOrDir, - logLevel); - } - - /// Process files/directories given as CLI arguments. - Future process() async { - for (final entityPath in pathsToFileOrDir) { - await _processEntity(entityPath, warnAboutNonDartFile: true); - } - } - - Future _processEntity(String path, - {bool warnAboutNonDartFile = false}) async { - final type = await FileSystemEntity.type(path); - switch (type) { - case FileSystemEntityType.directory: - return _processDirectory(path); - case FileSystemEntityType.file: - if (_validExt.hasMatch(path)) return _processFile(path); - default: - break; - } - if (warnAboutNonDartFile) { - final kind = - type == FileSystemEntityType.notFound ? 'existent' : 'Dart/Markdown'; - stderr.writeln('Warning: skipping non-$kind file "$path" ($type)'); - } - } - - /// Process (recursively) the entities in the directory [dirPath], ignoring - /// non-Dart and non-directory entities. - Future _processDirectory(String dirPath) async { - log.fine('_processDirectory: $dirPath'); - if (_exclude(dirPath)) return; - final dir = Directory(dirPath); - final fileEntityList = dir.list(); // recursive: true, followLinks: false - await for (final fse in fileEntityList) { - final path = fse.path; - final exclude = - _exclude(path) || fse is File && !_validExt.hasMatch(path); - log.finer('>> FileSystemEntity: $path ${exclude ? '- excluded' : ''}'); - if (exclude) continue; - await (fse is Directory ? _processDirectory(path) : _processFile(path)); - } - } - - Future _processFile(String path) async { - try { - await _updateFile(path); - numFiles++; - log.info('_processFile: $path'); - } catch (e, _) { - numErrors++; - stderr.writeln('Error processing "$path": $e'); // \n$_ - exitCode = 2; - } - } - - bool _exclude(String path) => excludePathRegExp.any((e) => path.contains(e)); - - Future _updateFile(String filePath) async { - final updater = Updater( - fragmentDirPath, - srcDirPath, - defaultIndentation: indentation, - escapeNgInterpolation: escapeNgInterpolation, - globalPlasterTemplate: plasterTemplate, - globalReplaceExpr: replaceExpr, - excerptsYaml: excerptsYaml, - logLevel: logLevel, - ); - final result = updater.generateUpdatedFile(filePath); - - numErrors += updater.numErrors; - numSrcDirectives += updater.numSrcDirectives; - numUpdatedFrag += updater.numUpdatedFrag; - - if (!inPlaceFlag) { - print(result); - } else if (updater.numUpdatedFrag > 0) { - await File(filePath).writeAsString(result); - } - } -} - -Never _printHelpAndExit(ArgParser parser) { - print('Use $_commandName to update code fragments within markdown ' - 'code blocks preceded with directives. ' - '(See the tool\'s GitHub repo README for details.)\n'); - _printUsageAndExit(parser); -} - -Never _printUsageAndExit(ArgParser parser, {String? msg, int exitCode = 1}) { - if (msg != null) print('\n$msg\n'); - print('Usage: $_commandName [OPTIONS] file_or_directory...\n'); - print(parser.usage); - exit(exitCode); -} diff --git a/packages/code_excerpt_updater/lib/src/args.dart b/packages/code_excerpt_updater/lib/src/args.dart deleted file mode 100644 index c87e0e7..0000000 --- a/packages/code_excerpt_updater/lib/src/args.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'constants.dart'; -import 'instr_info.dart'; -import 'issue_reporter.dart'; -import 'logger.dart'; - -class ArgProcessor { - ArgProcessor(this._reporter); - - final IssueReporter _reporter; - - InstrInfo extractAndNormalizeArgs(Match procInstrMatch) { - final info = InstrInfo(procInstrMatch[0]); - log.finer( - '>>> pIMatch: ${procInstrMatch.groupCount} - [${info.instruction}]'); - var i = 1; - info.linePrefix = procInstrMatch[i++] ?? ''; - // The instruction is the first line in a markdown list. - for (final c in const ['-', '*']) { - if (!info.linePrefix.contains(c)) continue; - info.linePrefix = info.linePrefix.replaceFirst(c, ' '); - break; // It can't contain both characters - } - i++; // final commentToken = match[i++]; - i++; // optional path+region - final pathAndOptRegion = procInstrMatch[i++]; - info.unnamedArg = pathAndOptRegion; - _extractAndNormalizeNamedArgs(info, procInstrMatch[i]); - return info; - } - - final RegExp supportedArgs = RegExp( - r'^(class|diff-with|diff-u|from|indent-by|path-base|plaster|region|replace|' - r'remove|retain|skip|take|title|to)$', - ); - final RegExp argRegExp = RegExp(r'^([-\w]+)\s*(=\s*"(.*?)"\s*|\b)\s*'); - - void _extractAndNormalizeNamedArgs(InstrInfo info, String? argsAsString) { - if (argsAsString == null) return; - var restOfArgs = argsAsString.trim(); - log.fine('>> __extractAndNormalizeNamedArgs: [$restOfArgs]'); - while (restOfArgs.isNotEmpty) { - final match = argRegExp.firstMatch(restOfArgs); - if (match == null) { - _reporter.error( - 'instruction argument parsing failure at/around: $restOfArgs'); - break; - } - final argName = match[1] ?? ''; - final argValue = match[3]; - info.args[argName] = argValue; - log.finer( - ' >> arg: $argName = ${argValue == null ? argValue : '"$argValue"'}', - ); - restOfArgs = restOfArgs.substring(match[0]?.length ?? 0); - } - _processPathAndRegionArgs(info); - _expandDiffPathBraces(info); - _validateArgs(info.args); - } - - final RegExp pathBraces = RegExp(r'^(.*?)\{(.*?),(.*?)\}(.*?)$'); - - void _expandDiffPathBraces(InstrInfo info) { - final match = pathBraces.firstMatch(info.path); - if (match == null) return; - if (info.args['diff-with'] != null) { - const msg = "You can't use both the brace syntax and the diff-with " - 'argument; choose one or the other.'; - _reporter.error(msg); - } - final groupOne = match[1] ?? ''; - final groupTwo = match[2] ?? ''; - final groupThree = match[3] ?? ''; - final groupFour = match[4] ?? ''; - info.path = groupOne + groupTwo + groupFour; - info.args['diff-with'] = groupOne + groupThree + groupFour; - } - - final RegExp regionInPath = RegExp(r'\s*\((.+)\)\s*$'); - final RegExp nonWordChars = RegExp(r'[^\w]+'); - - void _processPathAndRegionArgs(InstrInfo info) { - final path = info.unnamedArg; - if (path == null) return; - final match = regionInPath.firstMatch(path); - if (match == null) { - info.path = path; - } else { - // Remove region from path - info.path = path.substring(0, match.start); - info.region = match[1]?.replaceAll(nonWordChars, '-'); - } - log.finer('>>> path="${info.path}", region="${info.region}"'); - } - - void _validateArgs(Map args) { - _isNullOr(args['skip'], _isInt); - _isNullOr(args['take'], _isInt); - } - - final RegExp isNumericRegExp = RegExp(r'^[-+]?\d+$'); - - bool _isInt(String value) => isNumericRegExp.hasMatch(value); - - bool _isNullOr(String? value, Predicate test) => - value == null || test(value); -} diff --git a/packages/code_excerpt_updater/lib/src/code_excerpt_updater.dart b/packages/code_excerpt_updater/lib/src/code_excerpt_updater.dart deleted file mode 100644 index 68ab77e..0000000 --- a/packages/code_excerpt_updater/lib/src/code_excerpt_updater.dart +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) 2017. All rights reserved. Use of this source code -// is governed by a MIT-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as p; - -import 'args.dart'; -import 'code_transformer/core.dart'; -import 'code_transformer/plaster.dart'; -import 'code_transformer/replace.dart'; -import 'constants.dart'; -import 'differ.dart'; -import 'excerpt_getter.dart'; -import 'instr_info.dart'; -import 'issue_reporter.dart'; -import 'logger.dart'; - -/// A simple line-based updater for markdown code-blocks. It processes given -/// files line-by-line, looking for matches to [procInstrRE] contained within -/// markdown code blocks. -/// -/// Returns, as a string, a version of the given file source, with the -/// `` code fragments updated. Fragments are read from the -/// [fragmentDirPath] directory, and diff sources from `srcDirPath`. -class Updater { - static final RegExp codeBlockStartMarker = - RegExp(r'^\s*(///?)?\s*(```+|{%-?\s*\w+\s*(\w*)(\s+.*)?-?%})?'); - static final RegExp codeBlockEndPrettifyMarker = - RegExp(r'^\s*(///?)?\s*({%-?\s*end\w+\s*-?%})?'); - - final String fragmentDirPath; - final int defaultIndentation; - final bool escapeNgInterpolation; - final String globalReplaceExpr; - final String? globalPlasterTemplate; - String? filePlasterTemplate; - - late final ArgProcessor _argProcessor; - late final Differ _differ; - late final ExcerptGetter _getter; - late final IssueReporter _reporter; - - CodeTransformer? _appGlobalCodeTransformer; - CodeTransformer? _fileGlobalCodeTransformer; - late final PlasterCodeTransformer _plaster; - late final ReplaceCodeTransformer _replace; - - String _filePath = ''; - int _origNumLines = 0; - List _lines = []; - - int _numSrcDirectives = 0; - int _numUpdatedFrag = 0; - - /// [err] defaults to [stderr]. - Updater( - this.fragmentDirPath, - String srcDirPath, { - this.defaultIndentation = 0, - bool excerptsYaml = false, - this.escapeNgInterpolation = true, - this.globalReplaceExpr = '', - this.globalPlasterTemplate, - Stdout? err, - Level? logLevel, - }) { - initLogger(logLevel); - _reporter = - IssueReporter(IssueContext(() => _filePath, () => lineNum), err); - _replace = ReplaceCodeTransformer(_reporter); - _plaster = PlasterCodeTransformer(excerptsYaml, _replace); - - if (globalReplaceExpr.isNotEmpty) { - _appGlobalCodeTransformer = _replace.codeTransformer(globalReplaceExpr); - if (_appGlobalCodeTransformer == null) { - // Error details have already been reported, now throw. - final msg = - 'Command line replace expression is invalid: $globalReplaceExpr'; - throw Exception(msg); - } - } - _argProcessor = ArgProcessor(_reporter); - _getter = - ExcerptGetter(excerptsYaml, fragmentDirPath, srcDirPath, _reporter); - _differ = Differ(_getter.getExcerpt, log, _reporter.error); - } - - int get numErrors => _reporter.numErrors; - - int get numSrcDirectives => _numSrcDirectives; - - int get numUpdatedFrag => _numUpdatedFrag; - - int get numWarnings => _reporter.numWarnings; - - int get lineNum => _origNumLines - _lines.length; - - CodeTransformer? get fileAndCmdLineCodeTransformer => - compose(_fileGlobalCodeTransformer, _appGlobalCodeTransformer); - - /// Returns the content of the file at [path] with code blocks updated. - /// Missing fragment files are reported via `err`. - /// If [path] cannot be read then an exception is thrown. - String generateUpdatedFile(String path) { - _filePath = path.isEmpty ? 'unnamed-file' : path; - return _updateSrc(File(path).readAsStringSync()); - } - - String _updateSrc(String dartSource) { - _getter.pathBase = ''; - _lines = dartSource.split(eol); - _origNumLines = _lines.length; - return _processLines(); - } - - /// Regex matching code-excerpt processing instructions - final RegExp procInstrRE = RegExp( - r'^(\s*((?:///?|-|\*)\s*)?)?<\?code-excerpt\s*("([^"]+)")?((\s+[-\w]+(\s*=\s*"[^"]*")?\s*)*)\??>'); - - String _processLines() { - final output = []; - while (_lines.isNotEmpty) { - final line = _lines.removeAt(0); - output.add(line); - if (!line.contains('') ?? false)) { - _reporter - .warn('processing instruction must be closed using "?>" syntax'); - } - final info = _argProcessor.extractAndNormalizeArgs(match); - - if (info.unnamedArg == null) { - _processSetInstruction(info); - } else { - output.addAll(_getUpdatedCodeBlock(info)); - } - } - return output.join(eol); - } - - void _processSetInstruction(InstrInfo info) { - void checkForMoreThan1ArgErr() { - if (info.args.keys.length > 1) { - _reporter.error( - 'set instruction should have at most one argument: ' - '${info.instruction}', - ); - } - } - - if (info.args.containsKey('path-base')) { - _getter.pathBase = info.args['path-base'] ?? ''; - checkForMoreThan1ArgErr(); - } else if (info.args.containsKey('replace')) { - _fileGlobalCodeTransformer = info.args['replace']?.isNotEmpty ?? false - ? _replace.codeTransformer(info.args['replace']) - : null; - checkForMoreThan1ArgErr(); - } else if (info.args.containsKey('plaster')) { - filePlasterTemplate = info.args['plaster']; - checkForMoreThan1ArgErr(); - } else if (info.args.keys.isEmpty || - info.args.keys.length == 1 && info.args['class'] != null) { - // Ignore empty instruction, other tools process them. - } else if (info.args.keys.length == 1 && info.args.containsKey('title')) { - // Only asking for a title is ok. - } else { - _reporter - .warn('instruction ignored: unrecognized set instruction argument: ' - '${info.instruction}'); - } - } - - /// Expects the next lines to be a markdown code block. - /// Side-effect: consumes code-block lines. - Iterable _getUpdatedCodeBlock(InstrInfo info) { - final args = info.args; - final infoPath = info.path; - final currentCodeBlock = []; - if (_lines.isEmpty) { - _reporter.error('reached end of input, expect code block - "$infoPath"'); - return currentCodeBlock; - } - var line = _lines.removeAt(0); - final openingCodeBlockLine = line; - final firstLineMatch = codeBlockStartMarker.firstMatch(line); - if (firstLineMatch == null || firstLineMatch[2] == null) { - _reporter.error('code block should immediately follow - ' - '"$infoPath"\n not: $line'); - return [openingCodeBlockLine]; - } - - final newCodeBlockCode = args['diff-with'] == null - ? _getter.getExcerpt( - infoPath, - info.region, - _excerptCodeTransformer( - args, _codeLang(openingCodeBlockLine, info.path)), - ) - : _differ.getDiff(infoPath, info.region, args, - p.join(_getter.srcDirPath, _getter.pathBase)); - - log.finer('>>> new code block code: $newCodeBlockCode'); - if (newCodeBlockCode == null) { - // Error has been reported. Return while leaving existing code. - // We could skip ahead to the end of the code block but that - // will be handled by the outer loop. - return [openingCodeBlockLine]; - } - - final RegExp codeBlockEndChecker; - final codeBlockStart = firstLineMatch[2]; - if (codeBlockStart != null && codeBlockStart.startsWith('`')) { - // Create a RegExp to check for at least the same amount of backticks - // as the opening backticks had. - final backtickCount = codeBlockStart.length; - codeBlockEndChecker = _createCodeBlockEndMarker(backtickCount); - } else { - // Fall back to the prettify end marker for now. - codeBlockEndChecker = codeBlockEndPrettifyMarker; - } - - String? closingCodeBlockLine; - while (_lines.isNotEmpty) { - line = _lines[0]; - final match = codeBlockEndChecker.firstMatch(line); - if (match == null) { - _reporter.error('unterminated markdown code block ' - 'for '); - return [openingCodeBlockLine, ...currentCodeBlock]; - } else if (match[2] != null) { - // We've found the closing code-block marker. - closingCodeBlockLine = line; - _lines.removeAt(0); - break; - } - currentCodeBlock.add(line); - _lines.removeAt(0); - } - if (closingCodeBlockLine == null) { - _reporter.error('unterminated markdown code block ' - 'for '); - return [openingCodeBlockLine, ...currentCodeBlock]; - } - _numSrcDirectives++; - final linePrefix = info.linePrefix; - final indentBy = - args['diff-with'] == null ? _getIndentBy(args['indent-by']) : 0; - final indentation = ' ' * indentBy; - final prefixedCodeExcerpt = newCodeBlockCode.map((line) { - final prefixedLine = - '$linePrefix$indentation$line'.replaceFirst(RegExp(r'\s+$'), ''); - return escapeNgInterpolation - ? prefixedLine.replaceAllMapped( - RegExp(r'({){|(})}'), (m) => '${m[1] ?? m[2]}!${m[1] ?? m[2]}') - : prefixedLine; - }).toList(growable: false); - if (!const ListEquality() - .equals(currentCodeBlock, prefixedCodeExcerpt)) { - _numUpdatedFrag++; - } - final result = [ - openingCodeBlockLine, - ...prefixedCodeExcerpt, - closingCodeBlockLine - ]; - log.finer('>>> result: $result'); - return result; - } - - CodeTransformer? _excerptCodeTransformer( - Map args, String lang) { - final transformers = []; - - final plasterTransformer = _plaster.codeTransformer( - args.containsKey('plaster') - ? args['plaster'] - : filePlasterTemplate ?? globalPlasterTemplate, - lang); - - if (plasterTransformer != null) { - transformers.add(plasterTransformer); - } - - args.forEach((arg, val) { - final argTransformer = _argToTransformer(arg, val); - if (argTransformer != null) { - transformers.add(argTransformer); - } - }); - - final fileAndCodeTransformer = fileAndCmdLineCodeTransformer; - if (fileAndCodeTransformer != null) { - transformers.add(fileAndCodeTransformer); - } - - return transformers.fold(null, compose); - } - - CodeTransformer? _argToTransformer(String arg, String? value) { - if (value == null) { - return null; - } - switch (arg) { - case 'from': - return fromCodeTransformer(value); - case 'remove': - return removeCodeTransformer(value); - case 'replace': - return _replace.codeTransformer(value); - case 'retain': - return retainCodeTransformer(value); - case 'skip': - return skipCodeTransformer(value); - case 'take': - return takeCodeTransformer(value); - case 'to': - return toCodeTransformer(value); - default: - return null; - } - } - - int _getIndentBy([String? indentByAsString]) { - if (indentByAsString == null) return defaultIndentation; - var errorMsg = ''; - var result = 0; - try { - result = int.parse(indentByAsString); - } on FormatException { - errorMsg = 'error parsing integer value: $indentByAsString'; - } - if (result < 0 || result > 100) { - errorMsg = 'integer out of range: $result'; - result = 0; - } - if (errorMsg.isNotEmpty) { - _reporter.error(' indent-by: $errorMsg'); - } - return result; - } - - final RegExp _codeBlockLangSpec = RegExp(r'(?:```|prettify\s+)(\w+)'); - - String _codeLang(String openingCodeBlockLine, String path) { - final match = _codeBlockLangSpec.firstMatch(openingCodeBlockLine)?[1]; - if (match != null) return match; - - var ext = p.extension(path); - if (ext.startsWith('.')) ext = ext.substring(1); - return ext; - } - - static RegExp _createCodeBlockEndMarker(int backtickCount) => - RegExp(r'^\s*(///?)?\s*' '(`{$backtickCount})?'); -} diff --git a/packages/code_excerpt_updater/lib/src/code_transformer/core.dart b/packages/code_excerpt_updater/lib/src/code_transformer/core.dart deleted file mode 100644 index 3c275af..0000000 --- a/packages/code_excerpt_updater/lib/src/code_transformer/core.dart +++ /dev/null @@ -1,77 +0,0 @@ -/// Collected code transformer and predicate declarations -library; - -import '../constants.dart'; -import '../matcher.dart'; -import '../util.dart'; - -typedef CodeTransformer = String Function(String code); - -CodeTransformer? compose(CodeTransformer? f, CodeTransformer? g) { - if (f == null) { - return g; - } - if (g == null) { - return f; - } - return (String s) => g(f(s)); -} - -CodeTransformer _retain(Matcher p) => (String code) { - final lines = code.split(eol)..retainWhere(p); - return lines.join(eol); - }; - -//--- -// Specific transformers -//--- - -CodeTransformer fromCodeTransformer(String arg) { - final matcher = patternArgToMatcher(arg, 'from'); - return (String code) { - final lines = code.split(eol).skipWhile(not(matcher)); - return lines.join(eol); - }; -} - -CodeTransformer removeCodeTransformer(String arg) { - final matcher = patternArgToMatcher(arg, 'remove'); - return _retain(not(matcher)); -} - -CodeTransformer retainCodeTransformer(String arg) { - final matcher = patternArgToMatcher(arg, 'retain'); - return _retain(matcher); -} - -CodeTransformer? skipCodeTransformer(String arg) { - final n = toInt(arg); - if (n == null) return null; - return n >= 0 - ? (String code) => code.split(eol).skip(n).join(eol) - : (String code) { - final lines = code.split(eol); - return lines.take(lines.length + n).join(eol); - }; -} - -CodeTransformer? takeCodeTransformer(String arg) { - final n = toInt(arg); - if (n == null) return null; - return n >= 0 - ? (String code) => code.split(eol).take(n).join(eol) - : (String code) { - final lines = code.split(eol); - return lines.skip(lines.length + n - 1).join(eol); - }; -} - -CodeTransformer toCodeTransformer(String arg) { - final matcher = patternArgToMatcher(arg, 'to'); - return (String code) { - final lines = code.split(eol); - final i = lines.indexWhere(matcher); - if (i < 0) return code; - return lines.take(i + 1).join(eol); - }; -} diff --git a/packages/code_excerpt_updater/lib/src/code_transformer/plaster.dart b/packages/code_excerpt_updater/lib/src/code_transformer/plaster.dart deleted file mode 100644 index df2ca52..0000000 --- a/packages/code_excerpt_updater/lib/src/code_transformer/plaster.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'core.dart'; -import 'replace.dart'; - -const defaultPlaster = '···'; - -class PlasterCodeTransformer { - final bool excerptsYaml; - - final ReplaceCodeTransformer _replace; - - PlasterCodeTransformer(this.excerptsYaml, this._replace); - - /// Replace raw plaster markers in excerpt with [plasterTemplate]. - /// Note that plaster line indentation is not affected. - /// - /// If [plasterTemplate] is 'none' then plasters are removed. - /// If [plasterTemplate] is null then a default [lang] specific plaster - /// template is used. - CodeTransformer? codeTransformer(String? plasterTemplate, String lang) { - if (plasterTemplate == 'none') return removeCodeTransformer(defaultPlaster); - if (!excerptsYaml) return null; - - final template = - plasterTemplate?.replaceAll(r'$defaultPlaster', defaultPlaster) ?? - _plasterTemplateFor(lang); - return template == null - ? null - : _replace.codeTransformerHelper(defaultPlaster, template); - } - - String? _plasterTemplateFor(String lang) { - switch (lang) { - case 'css': - return '/* $defaultPlaster */'; - - case 'html': - return ''; - - case 'dart': - case 'js': - case 'scss': - case 'ts': - return '// $defaultPlaster'; - - case 'yaml': - return '# $defaultPlaster'; - - case 'diff': - default: - return null; - } - } -} diff --git a/packages/code_excerpt_updater/lib/src/code_transformer/replace.dart b/packages/code_excerpt_updater/lib/src/code_transformer/replace.dart deleted file mode 100644 index 774f5db..0000000 --- a/packages/code_excerpt_updater/lib/src/code_transformer/replace.dart +++ /dev/null @@ -1,97 +0,0 @@ -import '../constants.dart'; -import '../issue_reporter.dart'; -import '../logger.dart'; -import '../util.dart'; -import 'core.dart'; - -class ReplaceCodeTransformer { - static final RegExp _matchDollarNumRE = RegExp(r'(\$+)(&|\d*)'); - static final RegExp _endRE = RegExp(r'^g;?\s*$'); - - final IssueReporter _reporter; - - ReplaceCodeTransformer(this._reporter); - - CodeTransformer? codeTransformer(String? replaceExp) { - void reportErr([String extraInfo = '']) { - _reporter.error( - '${'invalid replace attribute ("$replaceExp"); '}' - '${extraInfo.isEmpty ? '' : '$extraInfo; '}' - 'supported syntax is 1 or more semi-colon-separated: /regexp/replacement/g', - ); - } - - if (replaceExp == null) return null; - final replaceExpParts = replaceExp - .replaceAll(escapedSlashRE, zeroChar) - .split('/') - .map((s) => s.replaceAll(zeroChar, '/')) - .toList(); - - // replaceExpParts = [''] + n x [re, replacement, end] where n >= 1 and - // end matches _endRE. - - final start = replaceExpParts[0]; - final len = replaceExpParts.length; - if (len < 4 || len % 3 != 1) { - reportErr('argument has missing parts ($len)'); - return null; - } - if (start != '') { - reportErr('argument should start with "/", not "$start"'); - return null; - } - final transformers = []; - for (var i = 1; i < replaceExpParts.length; i += 3) { - final re = replaceExpParts[i]; - final replacement = replaceExpParts[i + 1]; - final end = replaceExpParts[i + 2]; - if (!_endRE.hasMatch(end)) { - reportErr( - 'expected argument end syntax of "g" or "g;" but found "$end"'); - return null; - } - final transformer = codeTransformerHelper(re, replacement); - transformers.add(transformer); - } - - return transformers.fold(null, compose); - } - - CodeTransformer codeTransformerHelper(String re, String replacement) { - final encodedReplacement = encodeSlashChar(replacement); - log.finest(' >> replacement expr: $encodedReplacement'); - - if (!_matchDollarNumRE.hasMatch(encodedReplacement)) { - return (String code) => code.replaceAll(RegExp(re), encodedReplacement); - } - - return (String code) => code.replaceAllMapped( - RegExp(re), - (Match m) => encodedReplacement.replaceAllMapped( - _matchDollarNumRE, - (replaceMatch) { - // In JS, $$ becomes $ in a replacement string. - final numDollarChar = replaceMatch[1]!.length; - // Escaped dollar characters, if any: - final dollars = r'$' * (numDollarChar ~/ 2); - - final number = replaceMatch[2]; - - // Even number of $'s, e.g. $$1? - if (numDollarChar.isEven || number == null || number.isEmpty) { - return '$dollars${replaceMatch[2]}'; - } - - if (number == '&') return '$dollars${m[0]}'; - - final argNum = int.tryParse(number) ?? m.groupCount + 1; - // No corresponding group? Return the arg, like in JavaScript. - if (argNum > m.groupCount) return '$dollars\$$number'; - - return '$dollars${m[argNum]}'; - }, - ), - ); - } -} diff --git a/packages/code_excerpt_updater/lib/src/constants.dart b/packages/code_excerpt_updater/lib/src/constants.dart deleted file mode 100644 index 02d9125..0000000 --- a/packages/code_excerpt_updater/lib/src/constants.dart +++ /dev/null @@ -1,8 +0,0 @@ -/// App-wide constants -library; - -const backslash = '\\'; -const eol = '\n'; -const zeroChar = '\u{0}'; - -typedef Predicate = bool Function(T); diff --git a/packages/code_excerpt_updater/lib/src/diff/diff.dart b/packages/code_excerpt_updater/lib/src/diff/diff.dart deleted file mode 100644 index bfe3d96..0000000 --- a/packages/code_excerpt_updater/lib/src/diff/diff.dart +++ /dev/null @@ -1,92 +0,0 @@ -import '../matcher.dart'; -import 'hunk.dart'; - -/// Representation of a unified diff -class Diff { - final String _rawText; - bool _parsed = false; - - final List fileInfo = [null, null]; - final List hunks = []; - - Diff(this._rawText); - - /// Keep hunk lines in between those lines that match [from] and [to], - /// inclusive (matching is done on non-hunk-header lines). Drop all other - /// lines. Omit [from], to keep lines as of the first line of the first hunk. - /// Omit [to] to keep all lines after [from]. Returns true iff [from] or [to] - /// matched. - bool keepLines({Matcher? from, Matcher? to}) { - if (!_parsed) _parse(); - var matchFound = false; - if (from != null) { - while (hunks.isNotEmpty) { - final hunk = hunks.first; - if (hunk.dropLinesUntil(from)) { - matchFound = true; - break; - } - hunks.removeAt(0); - } - } - if (to == null) return matchFound; - - for (var i = 0; i < hunks.length; i++) { - final hunk = hunks[i]; - if (hunk.dropLinesAfter(to)) { - hunks.length = i + 1; - return true; - } - } - return false; - } - - bool dropLinesUntil(Matcher matcher) { - if (!_parsed) _parse(); - while (hunks.isNotEmpty) { - final hunk = hunks.first; - if (hunk.dropLinesUntil(matcher)) return true; - hunks.removeAt(0); - } - return false; - } - - bool dropLinesAfter(Matcher matcher) { - if (!_parsed) _parse(); - for (final hunk in hunks) { - if (hunk.dropLinesAfter(matcher)) return true; - } - return false; - } - - void _parse() { - if (_parsed || _rawText.isEmpty) return; - _parsed = true; - final lines = _rawText.split(eol); - - fileInfo[0] = lines[0]; - fileInfo[1] = lines[1]; - - var i = 2; - hunks.clear(); - while (i < lines.length) { - if (!lines[i].startsWith('@@')) throw _invalidHunk(i); - final start = i++; - // Look for the start of the next hunk or the end of the diff - while (i < lines.length && !lines[i].startsWith('@@')) { - i++; - } - hunks.add(Hunk(lines.skip(start).take(i - start).join(eol))); - } - } - - @override - String toString() => !_parsed - ? _rawText - : hunks.isEmpty - ? fileInfo.join(eol) - : '${fileInfo.join(eol)}\n${hunks.join(eol)}'; - - Exception _invalidHunk(int lineNum) => - Exception('Invalid hunk syntax. Expected "@@" at line $lineNum.'); -} diff --git a/packages/code_excerpt_updater/lib/src/diff/hunk.dart b/packages/code_excerpt_updater/lib/src/diff/hunk.dart deleted file mode 100644 index 1fadca5..0000000 --- a/packages/code_excerpt_updater/lib/src/diff/hunk.dart +++ /dev/null @@ -1,142 +0,0 @@ -import '../matcher.dart'; - -const eol = '\n'; - -/// A unified-diff hunk consisting of a line-range header followed by the -/// unified diff line details. For example: -/// -/// ```diff -/// @@ -1,10 +1,12 @@ -/// import 'package:flutter/material.dart'; -/// +import 'package:english_words/english_words.dart'; -/// -/// void main() => runApp(MyApp()); -/// -/// class MyApp extends StatelessWidget { -/// @override -/// Widget build(BuildContext context) { -/// + final wordPair = WordPair.random(); -/// return MaterialApp( -/// title: 'Welcome to Flutter', -/// home: Scaffold( -/// ``` -class Hunk { - static final Hunk empty = Hunk(''); - - static final RegExp headRegExp = - RegExp(r'@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@(.*)'); - - String _rawText; - - String _rawHead = ''; - List _start = const []; - List _length = const []; - String _timeStamp = ''; - List _lines = const []; - bool _parsed = false; - - Hunk(String? textFormat) : _rawText = textFormat ?? '' { - if (_rawText.isNotEmpty) { - final srcLines = _rawText.split(eol); - _rawText = ''; - _rawHead = srcLines.first; - _lines = srcLines.skip(1).toList(); - - final m = headRegExp.firstMatch(_rawHead); - if (m == null) { - throw Exception('The raw text is missing a header.'); - } - - _start = [_int(m[1]) ?? 0, _int(m[4]) ?? 0]; - _length = [_int(m[3]) ?? 1, _int(m[6]) ?? 1]; - _timeStamp = m[7] ?? ''; - - assert(_rawHead == _head, '_rawHead: $_rawHead\n_head:$_head'); - _parsed = true; - } - } - - int? start(int i) { - assert(isValidFileIndex(i)); - return _start[i]; - } - - int length(int i) { - assert(isValidFileIndex(i)); - return _length[i]; - } - - /// Drop lines (excluding the header), until a line if found - /// that matches [m]. The matching line is not dropped. - /// @returns true iff a matching line was found. - bool dropLinesUntil(Matcher m) { - final indexOfMatch = _indexOfFirstMatch(_lines, m); - if (indexOfMatch >= _lines.length) return false; - - for (var i = 0; i < indexOfMatch; i++) { - if (_lines[i].startsWith('-')) { - _start[0]++; - _length[0]--; - } else if (_lines[i].startsWith('+')) { - _start[1]++; - _length[1]--; - } else { - _start[0]++; - _length[0]--; - _start[1]++; - _length[1]--; - } - } - - final rest = _lines.skip(indexOfMatch).toList(); - _lines = rest; - return true; // new Hunk('$head\n$rest'); - } - - /// Look for a line (excluding the header), that matches [m]. - /// All lines after the match are dropped. - /// @returns true iff a matching line was found. - bool dropLinesAfter(Matcher m) { - final indexOfMatch = _indexOfFirstMatch(_lines, m); - if (indexOfMatch >= _lines.length) return false; - - for (var i = indexOfMatch + 1; i < _lines.length; i++) { - if (_lines[i].startsWith('-')) { - _length[0]--; - } else if (_lines[i].startsWith('+')) { - _length[1]--; - } else { - _length[0]--; - _length[1]--; - } - } - _lines = _lines.take(indexOfMatch + 1).toList(); - return true; - } - - String get _head => '@@ -${_lineLength(0)} +${_lineLength(1)} @@$_timeStamp'; - - @override - String toString() => _parsed ? '$_head\n${_lines.join(eol)}' : _rawText; - - String _lineLength(int i) { - assert(isValidFileIndex(i)); - final indexLength = _length[i]; - return indexLength <= 1 ? '${_start[i]}' : '${_start[i]},$indexLength'; - } - - bool isValidFileIndex(int i) => i == 0 || i == 1; - - int? _int(String? s) { - if (s == null) return null; - return int.tryParse(s); - } - - int _indexOfFirstMatch(List a, Matcher m) { - var i = 0; - while (i < a.length && !m(a[i])) { - i++; - } - return i; - } -} diff --git a/packages/code_excerpt_updater/lib/src/differ.dart b/packages/code_excerpt_updater/lib/src/differ.dart deleted file mode 100644 index 19bddd7..0000000 --- a/packages/code_excerpt_updater/lib/src/differ.dart +++ /dev/null @@ -1,157 +0,0 @@ -import 'dart:io'; - -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as p; - -import 'code_transformer/core.dart'; -import 'constants.dart'; -import 'diff/diff.dart'; -import 'matcher.dart'; - -typedef ErrorReporter = void Function(String msg); -typedef ExcerptFetcher = Iterable? Function(String path, String region); - -class Differ { - final RegExp docregionRe = RegExp(r'#(end)?doc(plaster|region)\b'); - final ExcerptFetcher _excerptFetcher; - final ErrorReporter _reportError; - final Logger _log; - - late final Directory _tmpDir = Directory.systemTemp; - - Differ(this._excerptFetcher, this._log, this._reportError); - - Iterable? getDiff(String relativeSrcPath1, String region, - Map args, String pathPrefix) { - final relativeSrcPath2 = args['diff-with'] ?? ''; - final useCompleteFiles = region.isEmpty && args['remove'] == null; - final path1 = useCompleteFiles - ? filteredFile(p.join(pathPrefix, relativeSrcPath1)) - : _writeExcerpt(relativeSrcPath1, region, args); - final path2 = useCompleteFiles - ? filteredFile(p.join(pathPrefix, relativeSrcPath2)) - : _writeExcerpt(relativeSrcPath2, region, args); - - final diffUArg = args['diff-u']; - final diffArgs = diffUArg == null ? ['-u'] : ['-U', diffUArg]; - diffArgs.add(path1.path); - diffArgs.add(path2.path); - final r = Process.runSync('diff', diffArgs); - - try { - path1.deleteSync(); - path2.deleteSync(); - } on FileSystemException catch (e) { - _log.info( - 'Ignored exception while attempting to delete temporary files: $e'); - } - - if (r.exitCode > 1) { - _reportError(r.stderr as String); - return null; - } - if ((r.stdout as String).isEmpty) return []; // no differences between files - - /* Sample diff output: - --- examples/acx/lottery/1-base/lib/lottery_simulator.html 2017-08-25 07:45:24.000000000 -0400 - +++ examples/acx/lottery/2-starteasy/lib/lottery_simulator.html 2017-08-25 07:45:24.000000000 -0400 - @@ -23,35 +23,39 @@ -
- - - - Progress: {{progress}}%
- - - + - + - -
- ... - */ - - var diffText = (r.stdout as String).trim(); - final fromArg = args['from']; - final toArg = args['to']; - if (fromArg != null || toArg != null) { - final from = fromArg == null ? null : patternArgToMatcher(fromArg); - final to = toArg == null ? null : patternArgToMatcher(toArg); - final diff = Diff(diffText); - if (diff.keepLines(from: from, to: to)) diffText = diff.toString(); - } - final result = diffText.split(eol); - - // Fix file id lines by removing: - // - [pathPrefix] from the start of the file path so that paths are relative - // - timestamp (because file timestamps are not relevant in the git world) - result[0] = _adjustDiffFileIdLine( - relativeSrcPath1 + (region.isEmpty ? '' : ' ($region)'), result[0]); - result[1] = _adjustDiffFileIdLine( - relativeSrcPath2 + (region.isEmpty ? '' : ' ($region)'), result[1]); - _log.fine('>> diff result:\n${result.join("\n")}'); - return result; - } - - /// Read the file at [filePath], strip out any docregion tags (lines matching - /// [docregionRe]), write the result to a temporary file and return the - /// corresponding [File] object. - /// - /// Lets [FileSystemException]s through. - File filteredFile(String filePath) { - final file = File(filePath); - final src = file.readAsStringSync(); - final lines = src.split(eol); - lines.removeWhere(docregionRe.hasMatch); - - return _writeTmp(filePath, lines.join(eol)); - } - - /// Write the named region of [filePath] to a temporary file whose filename - /// is derived from [filePath]. Returns the [File] instance of the temp file. - File _writeExcerpt( - String filePath, String region, Map args) { - var excerpt = _excerptFetcher(filePath, region)?.join(eol) ?? ''; - - final removeArg = args['remove']; - if (removeArg != null) { - final removed = removeCodeTransformer(removeArg); - excerpt = removed(excerpt); - } - - // To avoid "No newline at end of file" messages from the diff tool, - // ensure that the excerpt ends with an EOL (since all trailing blank lines - // are usually stripped out). - if (excerpt.isNotEmpty) excerpt += eol; - - return _writeTmp(filePath, excerpt); - } - - /// Write [content] to a temporary file whose filename is derived - /// from [filePath]. Returns the temporary [File] instance. - File _writeTmp(String filePath, String content) { - final ext = p.extension(filePath); - final tmpFilePath = - p.join(tempDirectory.path, 'differ_src_${filePath.hashCode}$ext'); - final tmpFile = File(tmpFilePath); - tmpFile.writeAsStringSync(content); - return tmpFile; - } - - // int _indexOfFirstMatch(List a, int startingIdx, RegExp re) { - // var i = startingIdx; - // while (i < a.length && !re.hasMatch(a[i])) i++; - // return i; - // } - - final RegExp _diffFileIdRegEx = RegExp(r'^(---|\+\+\+) ([^\t]+)\t(.*)$'); - - String _adjustDiffFileIdLine(String relativePath, String diffFileIdLine) { - final line = diffFileIdLine; - final match = _diffFileIdRegEx.firstMatch(line); - if (match == null) { - _log.warning('Warning: unexpected file Id line: $diffFileIdLine'); - return diffFileIdLine; - } - return '${match[1]} $relativePath'; - } - - Directory get tempDirectory => _tmpDir; -} diff --git a/packages/code_excerpt_updater/lib/src/excerpt_getter.dart b/packages/code_excerpt_updater/lib/src/excerpt_getter.dart deleted file mode 100644 index e9e1191..0000000 --- a/packages/code_excerpt_updater/lib/src/excerpt_getter.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'dart:io'; - -import 'package:path/path.dart' as p; -import 'package:yaml/yaml.dart'; - -import 'code_transformer/core.dart'; -import 'constants.dart'; -import 'issue_reporter.dart'; -import 'logger.dart'; -import 'util.dart'; - -const _defaultYamlExcerptLeftBorderChar = ''; // I.e., no char by default -const _yamlExcerptLeftBorderCharKey = '#border'; - -class ExcerptGetter { - ExcerptGetter( - this.excerptsYaml, this.fragmentDirPath, this.srcDirPath, this._reporter); - - final bool excerptsYaml; - final String fragmentDirPath; - final String srcDirPath; - final IssueReporter _reporter; - - String pathBase = ''; - String _yamlExcerptLeftBorderChar = _defaultYamlExcerptLeftBorderChar; - - Iterable? getExcerpt( - // String pathBase, - String relativePath, - String region, - [CodeTransformer? t]) { - _yamlExcerptLeftBorderChar = _defaultYamlExcerptLeftBorderChar; - var excerpt = _getExcerptAsString(relativePath, region); - if (excerpt == null) return null; // Errors have been reported - log.fine('>> excerpt before xform: "$excerpt"'); - if (_yamlExcerptLeftBorderChar.isNotEmpty) { - excerpt = _removeLineBorderPrefix(_yamlExcerptLeftBorderChar, excerpt); - } - if (t != null) excerpt = t(excerpt); - final lines = excerpt.split(eol); - // All excerpts are [eol] terminated, so drop trailing blank lines - while (lines.isNotEmpty && lines.last == '') { - lines.removeLast(); - } - return trimMinLeadingSpace(lines); - } - - String _removeLineBorderPrefix(String borderChar, String excerpt) => excerpt - .split(eol) - .map((line) => line.startsWith(_yamlExcerptLeftBorderChar) - ? line.substring(1) - : line) - .join(eol); - - /// Look for a fragment file under [fragmentDirPath], failing that look for a - /// source file under [srcDirPath]. If a file is found return its content as - /// a string. Otherwise, report an error and return null. - String? _getExcerptAsString(String relativePath, String region) => - excerptsYaml - ? _getExcerptAsStringFromYaml(relativePath, region) - : _getExcerptAsStringLegacy(relativePath, region); - - /// Potentially assigns to _yamlExcerptLeftBorderChar the - /// value of the YAML [_yamlExcerptLeftBorderCharKey] key. - String? _getExcerptAsStringFromYaml(String relativePath, String region) { - const ext = '.excerpt.yaml'; - final excerptYamlPath = - p.join(fragmentDirPath, pathBase, relativePath + ext); - YamlMap? excerptsYaml; - try { - final contents = File(excerptYamlPath).readAsStringSync(); - excerptsYaml = - loadYaml(contents, sourceUrl: Uri.file(excerptYamlPath)) as YamlMap; - _yamlExcerptLeftBorderChar = - (excerptsYaml[_yamlExcerptLeftBorderCharKey] ?? '') as String; - } on FileSystemException { - // Fall through - } - if (region.isEmpty && excerptsYaml == null) { - // Continue: search for source file. - } else if (excerptsYaml == null) { - _reporter.error('cannot read file "$excerptYamlPath"'); - return null; - } else if (excerptsYaml[region] == null) { - _reporter.error('there is no "$region" region in "$excerptYamlPath"'); - return null; - } else { - return (excerptsYaml[region] as String).trimRight(); - } - - // ... - final filePath = p.join(fragmentDirPath, pathBase, relativePath); - try { - return File(filePath).readAsStringSync(); - } on FileSystemException { - _reporter.error('excerpt not found for "$relativePath"'); - return null; - } - } - - String? _getExcerptAsStringLegacy(String relativePath, String region) { - const fragExtension = '.txt'; - final String file; - if (region.isNotEmpty) { - final dir = p.dirname(relativePath); - final basename = p.basenameWithoutExtension(relativePath); - final ext = p.extension(relativePath); - file = p.join(dir, '$basename-$region$ext$fragExtension'); - } else { - file = relativePath + fragExtension; - } - - // First look for a matching fragment - final fragPath = p.join(fragmentDirPath, pathBase, file); - try { - return File(fragPath).readAsStringSync(); - } on FileSystemException { - if (region != '') { - _reporter.error('cannot read fragment file "$fragPath"'); - return null; - } - // Fall through - } - - // No fragment file file. Look for a source file with a matching file name. - final srcFilePath = p.join(srcDirPath, pathBase, relativePath); - try { - return File(srcFilePath).readAsStringSync(); - } on FileSystemException { - _reporter.error('cannot find a source file "$srcFilePath", ' - 'nor fragment file "$fragPath"'); - return null; - } - } -} diff --git a/packages/code_excerpt_updater/lib/src/instr_info.dart b/packages/code_excerpt_updater/lib/src/instr_info.dart deleted file mode 100644 index fca20d6..0000000 --- a/packages/code_excerpt_updater/lib/src/instr_info.dart +++ /dev/null @@ -1,28 +0,0 @@ -/// Representation of an XML processing instruction -class InstrInfo { - final String? instruction; - String linePrefix = ''; - - InstrInfo(this.instruction); - - /// Optional. Currently represents a path + optional region - String? unnamedArg; - - String? _path; - String get path => _path ?? args['path'] ?? ''; - set path(String p) { - _path = p; - } - - String? _region; - set region(String? r) { - _region = r; - } - - String get region => args['region'] ?? _region ?? ''; - - final Map args = {}; - - @override - String toString() => 'InstrInfo: $linePrefix$instruction; args=$args'; -} diff --git a/packages/code_excerpt_updater/lib/src/issue_reporter.dart b/packages/code_excerpt_updater/lib/src/issue_reporter.dart deleted file mode 100644 index dad768a..0000000 --- a/packages/code_excerpt_updater/lib/src/issue_reporter.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'dart:io'; - -class IssueReporter { - final IssueContext _ctx; - final Stdout _stderr; - - int numWarnings = 0; - int numErrors = 0; - - IssueReporter(this._ctx, [Stdout? err]) : _stderr = err ?? stderr; - - void warn(String msg) { - numWarnings++; - return _report('Warning', msg); - } - - void error(String msg) { - numErrors++; - return _report('Error', msg); - } - - void _report(String prefix, String msg) => - _stderr.writeln('$prefix: ${_ctx.filePath}:${_ctx.lineNum} $msg'); -} - -class IssueContext { - final String Function() _filePath; - final int Function() _lineNum; - - const IssueContext(this._filePath, this._lineNum); - - String get filePath => _filePath(); - int get lineNum => _lineNum(); -} diff --git a/packages/code_excerpt_updater/lib/src/logger.dart b/packages/code_excerpt_updater/lib/src/logger.dart deleted file mode 100644 index a051bd3..0000000 --- a/packages/code_excerpt_updater/lib/src/logger.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:logging/logging.dart'; - -final Logger log = Logger('CEU'); - -bool _loggerInitialized = false; - -void initLogger([Level? logLevel]) { - if (_loggerInitialized) return; - Logger.root.level = logLevel ?? Level.WARNING; - Logger.root.onRecord.listen((LogRecord rec) { - print('${rec.level.name}: ${rec.time}: ${rec.message}'); - }); - _loggerInitialized = true; -} diff --git a/packages/code_excerpt_updater/lib/src/matcher.dart b/packages/code_excerpt_updater/lib/src/matcher.dart deleted file mode 100644 index 2092bb0..0000000 --- a/packages/code_excerpt_updater/lib/src/matcher.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:logging/logging.dart'; - -final Logger _log = Logger('CEU.CT'); - -typedef Matcher = bool Function(String t); -// typedef Predicate = bool Function(T t); - -Matcher not(Matcher p) => (String s) => !p(s); - -Matcher patternArgToMatcher(String arg, [String cmd = '']) { - final Matcher matcher; - if (arg.startsWith('/') && arg.endsWith('/')) { - final re = RegExp(arg.substring(1, arg.length - 1)); - _log.finest(' >> $cmd arg: "$arg" used as regexp $re'); - matcher = re.hasMatch; - } else { - final stringToMatch = arg.startsWith(r'\/') - ? arg.substring(1) // TODO: process other escaped characters - : arg; - _log.finest(' >> $cmd arg: "$stringToMatch" is used as a string matcher'); - matcher = (s) => s.contains(stringToMatch); - } - return matcher; -} diff --git a/packages/code_excerpt_updater/lib/src/util.dart b/packages/code_excerpt_updater/lib/src/util.dart deleted file mode 100644 index 4f80141..0000000 --- a/packages/code_excerpt_updater/lib/src/util.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'dart:math'; - -import 'constants.dart'; - -/// String to int conversion -int? toInt(String? s, {int radix = 10, int? errorValue}) { - if (s == null) { - return errorValue; - } - try { - return int.parse(s, radix: radix); - } on FormatException { - return errorValue; - } -} - -//----------------------------------------------------------------------------- - -final _blankLineRegEx = RegExp(r'^\s*$'); -final _leadingWhitespaceRegEx = RegExp(r'^[ \t]*'); - -Iterable trimMinLeadingSpace(Iterable lines) { - final nonBlankLines = lines.where((s) => !_blankLineRegEx.hasMatch(s)); - - // Length of leading spaces to be trimmed - final lengths = nonBlankLines.map((s) { - final matchLength = _leadingWhitespaceRegEx.firstMatch(s)?[0]?.length; - return matchLength ?? 0; - }); - - if (lengths.isEmpty) { - return lines; - } - - final len = lengths.reduce(min); - return len == 0 - ? lines - : lines.map((line) => line.length < len ? line : line.substring(len)); -} - -//----------------------------------------------------------------------------- -// TODO: consider writing the following conversions as a string transformer. - -final escapedSlashRE = RegExp(r'\\/'); - -final _slashHexCharRE = RegExp(r'\\x(..)'); -final _slashLetterRE = RegExp(r'\\([\\nt])'); - -/// Encode special characters: '\t', `\n`, and `\xHH` where `HH` are hex digits. -String encodeSlashChar(String s) => s - .replaceAllMapped(_slashLetterRE, (Match m) => _slashCharToChar(m[1])) - // At this point, escaped `\` is encoded as [zeroChar]. - .replaceAllMapped(_slashHexCharRE, - (Match m) => _hexToChar(m[1], errorValue: '\\x${m[1]}')) - // Recover `\` characters. - .replaceAll(zeroChar, backslash); - -String _hexToChar(String? hexDigits, {required String errorValue}) { - final charCode = toInt(hexDigits, radix: 16); - return charCode == null ? errorValue : String.fromCharCode(charCode); -} - -String _slashCharToChar(String? char) { - switch (char) { - case 'n': - return '\n'; - case 't': - return '\t'; - case backslash: - return zeroChar; - default: - return '\\$char'; - } -} diff --git a/packages/code_excerpt_updater/mono_pkg.yaml b/packages/code_excerpt_updater/mono_pkg.yaml deleted file mode 100644 index d4e257b..0000000 --- a/packages/code_excerpt_updater/mono_pkg.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# See https://github.com/google/mono_repo.dart for details on this file -sdk: -- pubspec -- dev - -stages: -- analyzer_and_format: - - group: - - format - - analyze: --fatal-infos . -- unit_test: - - test: diff --git a/packages/code_excerpt_updater/pubspec.yaml b/packages/code_excerpt_updater/pubspec.yaml deleted file mode 100644 index 6fc9b85..0000000 --- a/packages/code_excerpt_updater/pubspec.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: code_excerpt_updater -publish_to: none - -environment: - sdk: ^3.4.0 - -dependencies: - args: ^2.4.2 - collection: ^1.18.0 - logging: ^1.2.0 - path: ^1.9.0 - yaml: ^3.1.2 - -dev_dependencies: - analysis_defaults: - path: ../analysis_defaults - mockito: ^5.4.4 - test: ^1.25.2 diff --git a/packages/code_excerpt_updater/test/diff_test.dart b/packages/code_excerpt_updater/test/diff_test.dart deleted file mode 100644 index 06c7a03..0000000 --- a/packages/code_excerpt_updater/test/diff_test.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:code_excerpt_updater/src/diff/diff.dart'; -import 'package:code_excerpt_updater/src/matcher.dart'; -import 'package:test/test.dart'; - -import 'hunk_test.dart'; - -final diff1head = ''' ---- 1-base/lib/main.dart -+++ 2-use-package/lib/main.dart -''' - .trim(); - -final diff1 = '$diff1head\n$hunk1'; - -final diff1TrimmedBefore = '$diff1head\n$hunk1TrimmedBefore'; -final diff1TrimmedBeforeAndAfter = '$diff1head\n$hunk1TrimmedBeforeAndAfter'; - -/// A diff with two hunks -final diff2 = '$diff1\n$hunk2'; - -void main() { - final matchClass = patternArgToMatcher('/^ class/'); - final matchReturn = patternArgToMatcher(r'/^\s+return/'); - final wontMatch = patternArgToMatcher('will not match'); - - group('Idempotence on src', () { - test('Empty diff', () { - expect(Diff('').toString(), ''); - }); - - test('Diff with one hunk', () { - final d = Diff(diff1); - expect(d.toString(), diff1); - }); - - test('Diff with more than one hunk', () { - final d = Diff(diff2); - expect(d.toString(), diff2); - }); - }); - - group('Diff with one hunk:', () { - late Diff d; - - setUp(() => d = Diff(diff1)); - - group('Skip before "class":', () { - test('dropLinesUntil', () { - expect(d.dropLinesUntil(matchClass), true); - expect(d.toString(), diff1TrimmedBefore); - }); - - test('dropLines', () { - expect(d.keepLines(from: matchClass), true); - expect(d.toString(), diff1TrimmedBefore); - }); - }); - - group('Skip before "class" until "return":', () { - test('dropLinesUntil/dropLinesAfter', () { - expect(d.dropLinesUntil(matchClass), true); - expect(d.dropLinesAfter(matchReturn), true); - expect(d.toString(), diff1TrimmedBeforeAndAfter); - }); - - test('dropLines', () { - expect(d.keepLines(from: matchClass, to: matchReturn), true); - expect(d.toString(), diff1TrimmedBeforeAndAfter); - }); - }); - - group('Skip all:', () { - test('dropLinesUntil', () { - expect(d.dropLinesUntil(wontMatch), false); - expect(d.toString(), diff1head); - }); - - test('dropLines', () { - expect(d.keepLines(from: wontMatch), false); - expect(d.toString(), diff1head); - }); - }); - }); - - group('Diff with 2 hunks:', () { - final d = Diff(diff2); - - group('Skip before "class":', () { - test('dropLinesUntil', () { - expect(d.dropLinesUntil(matchClass), true); - expect(d.toString(), '$diff1TrimmedBefore\n$hunk2'); - }); - - test('dropLines', () { - expect(d.keepLines(from: matchClass), true); - expect(d.toString(), '$diff1TrimmedBefore\n$hunk2'); - }); - }); - - test('Diff2: Skip before "class" until "return"', () { - expect(d.keepLines(from: matchClass, to: matchReturn), true); - expect(d.toString(), diff1TrimmedBeforeAndAfter); - }); - }); - - test('Diff using to regexp but no from regexp', () { - final d = Diff('$diff1head\n$hunk2'); - expect(d.keepLines(to: patternArgToMatcher(r'/^\+\s+child:/')), true); - expect(d.toString(), '$diff1head\n$hunk2Trimmed'); - }); -} - -final hunk2Trimmed = ''' -@@ -12,4 +14,4 @@ - title: Text('Welcome to Flutter'), - ), - body: Center( -- child: Text('Hello World'), -+ child: Text(wordPair.asPascalCase), -''' - .trim(); diff --git a/packages/code_excerpt_updater/test/excerpt_getter_test.dart b/packages/code_excerpt_updater/test/excerpt_getter_test.dart deleted file mode 100644 index 511d1b4..0000000 --- a/packages/code_excerpt_updater/test/excerpt_getter_test.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:code_excerpt_updater/src/excerpt_getter.dart'; -import 'package:code_excerpt_updater/src/issue_reporter.dart'; -import 'package:test/test.dart'; - -const _testDir = 'test_data'; - -void main() { - const excerptsYaml = true; - const fragmentDirPath = '$_testDir/excerpt_yaml'; - const srcDirPath = fragmentDirPath; - final issueReporter = - IssueReporter(IssueContext(() => 'unused/path/to/file', () => 1)); - - late ExcerptGetter eg; - - setUpAll(() { - eg = ExcerptGetter( - excerptsYaml, - fragmentDirPath, - srcDirPath, - issueReporter, - )..pathBase = ''; - }); - - test('sanity', () { - final excerpt = eg.getExcerpt('excerpt_getter.dart', 'main'); - final code = [r"void main() => print('$greeting $scope');"]; - expect(excerpt, code); - }); - - test('trim trailing blank lines', () { - final excerpt = - eg.getExcerpt('excerpt_getter.dart', 'trailing blank lines'); - final code = [r"var greeting = 'hello';"]; - expect(excerpt, code); - }); - - test('main with border', () { - final excerpt = eg.getExcerpt('excerpt_getter_with_border.dart', 'main'); - final code = [r"void main() => print('$greeting $scope');"]; - expect(excerpt, code); - }); - - test('trailing blank lines with border', () { - final excerpt = eg.getExcerpt( - 'excerpt_getter_with_border.dart', 'trailing blank lines'); - final code = [r"var greeting = 'hello';"]; - expect(excerpt, code); - }); -} diff --git a/packages/code_excerpt_updater/test/hunk_test.dart b/packages/code_excerpt_updater/test/hunk_test.dart deleted file mode 100644 index 3687055..0000000 --- a/packages/code_excerpt_updater/test/hunk_test.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:code_excerpt_updater/src/diff/hunk.dart'; -import 'package:code_excerpt_updater/src/matcher.dart'; -import 'package:test/test.dart'; - -const hunk0 = ''' -@@ -1,10 +1,12 @@ - import 'package:flutter/material.dart'; -+import 'package:english_words/english_words.dart'; - - void main() => runApp(MyApp()); - -'''; - -final hunk0ExtraBody1 = ''' - class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { -+ final wordPair = WordPair.random(); - return MaterialApp( -''' - .trimRight(); - -final hunk0ExtraBody2 = ''' - title: 'Welcome to Flutter', - home: Scaffold( -''' - .trimRight(); - -final hunk0ExtraBody = '$hunk0ExtraBody1\n$hunk0ExtraBody2'; - -final hunk1 = '$hunk0$hunk0ExtraBody'; - -final hunk1TrimmedBefore = '@@ -5,6 +6,7 @@\n$hunk0ExtraBody'; -final hunk1TrimmedBeforeAndAfter = '@@ -5,4 +6,5 @@\n$hunk0ExtraBody1'; - -final hunk2 = ''' -@@ -12,7 +14,7 @@ - title: Text('Welcome to Flutter'), - ), - body: Center( -- child: Text('Hello World'), -+ child: Text(wordPair.asPascalCase), - ), - ), - ); -''' - .trim(); - -void main() { - group('basic hunk 1', () { - late Hunk h; - - setUp(() { - h = Hunk(hunk1); - }); - - test('Idempotence on src', () { - expect(h.toString(), hunk1); - }); - - test('Line info', () { - expect(h.start(0), 1); - expect(h.start(1), 1); - expect(h.length(0), 10); - expect(h.length(1), 12); - - expect(() => h.start(2), throwsA(isA())); - expect(() => h.length(2), throwsA(isA())); - }); - - test('Skip before "class"', () { - expect(h.dropLinesUntil(patternArgToMatcher('/^ class/')), true); - expect(h.toString(), hunk1TrimmedBefore); - }); - - test('Skip before "class" until "return"', () { - expect(h.dropLinesUntil(patternArgToMatcher('/^ class/')), true); - expect(h.dropLinesAfter(patternArgToMatcher(r'/^\s+return/')), true); - expect(h.toString(), hunk1TrimmedBeforeAndAfter); - }); - }); - - group('basic hunk 2', () { - late Hunk h; - - setUp(() { - h = Hunk(hunk2); - }); - - test('Idempotence on src', () { - expect(h.toString(), hunk2); - }); - - test('Line info', () { - expect(h.start(0), 12); - expect(h.start(1), 14); - expect(h.length(0), 7); - expect(h.length(1), 7); - }); - - test('Skip before w/o match', () { - final skipped = h.dropLinesUntil(patternArgToMatcher('xx')); - expect(skipped, false); - expect(h.toString(), hunk2); - }); - }); -} diff --git a/packages/code_excerpt_updater/test/main_test.dart b/packages/code_excerpt_updater/test/main_test.dart deleted file mode 100644 index 6f25f52..0000000 --- a/packages/code_excerpt_updater/test/main_test.dart +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2017. All rights reserved. Use of this source code -// is governed by a MIT-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:code_excerpt_updater/src/code_excerpt_updater.dart'; -import 'package:mockito/mockito.dart'; -import 'package:path/path.dart' as p; -import 'package:test/test.dart'; - -const _testDir = 'test_data'; - -// TODO: enhance tests so that we can inspect the generated error messages. -// It might be easier to modify the updater to use an IOSink than to try to read -// stderr. - -late Updater updater; -late Stdout _stderr; - -String _readFile(String path) => File(path).readAsStringSync(); - -String _srcFileName2Path(String fileName) => p.join(_testDir, 'src', fileName); -String _expectedFn2Path(String relPath) => - p.join(_testDir, 'expected', relPath); - -String getSrc(String relPath) => _readFile(_srcFileName2Path(relPath)); -String getExpected(String relPath) => _readFile(_expectedFn2Path(relPath)); - -const Map _errorMessages = { - 'no_change/frag_not_found.dart': - 'Error: test_data/src/no_change/frag_not_found.dart:2 ' - 'cannot find a source file "test_data/diff_src/dne.xzy", ' - 'nor fragment file "test_data/frag/dne.xzy.txt"', - 'no_change/invalid_code_block.dart': - 'Error: test_data/src/no_change/invalid_code_block.dart:5 ' - 'unterminated markdown code block for ', - 'no_change/invalid_code_excerpt_arg.dart': - 'Warning: test_data/src/no_change/invalid_code_excerpt_arg.dart:1 ' - 'instruction ignored: unrecognized set instruction argument: ' - '/// ', - 'no_change/missing_code_block.dart': - 'Error: test_data/src/no_change/missing_code_block.dart:3 ' - 'code block should immediately follow - "quote.md"\n' - ' not: int x = 0;', - 'no_change/diff.md': 'Error: test_data/src/no_change/diff.md:86 ' - 'You can\'t use both the brace syntax and the diff-with argument; ' - 'choose one or the other.', -}; - -void _stdFileTest(String testFilePath) { - // print('>> testing $testFilePath'); - final testFileName = p.basename(testFilePath); - test(testFileName, () { - final testFileRelativePath = testFilePath; - // var originalSrc = getSrc(testFileRelativePath); - // print('>> ${_srcFileName2Path(testFileRelativePath)}'); - final updatedDocs = - updater.generateUpdatedFile(_srcFileName2Path(testFileRelativePath)); - // print('>> updatedDocs: ${updatedDocs}'); - - final expectedErr = _errorMessages[testFilePath]; - if (expectedErr == null) { - verifyZeroInteractions(_stderr); - expect(updater.numErrors, 0); - } else { - final vr = verify(_stderr.writeln(captureAny)); - expect(vr.captured.join(';'), expectedErr); - final isWarning = expectedErr.startsWith('Warn'); - expect(updater.numErrors, isWarning ? 0 : 1); - expect(updater.numWarnings, isWarning ? 1 : 0); - } - - final expectedDoc = File(_expectedFn2Path(testFilePath)).existsSync() - ? getExpected(testFilePath) - : getSrc(testFilePath); - expect(updatedDocs, expectedDoc); - }); -} - -class MockStderr extends Mock implements Stdout {} - -void main() { - group('Basic:', testsFromDefaultDir); - group('Set path:', testSetPath); - group('Default indentation:', testDefaultIndentation); - group('Disable escape ng interpolation:', testNoEscapeNgInterpolation); - group('Excerpt from src:', testSrcButNoFrag); - group('Excerpt YAML:', testExcerptYaml); - - test('Replace command line option: invalid expression', () { - try { - Updater(p.join(_testDir, 'frag'), p.join(_testDir, 'diff_src'), - globalReplaceExpr: 'invalidReplaceExpr', err: _stderr); - } catch (e) { - expect( - e.toString(), - 'Exception: Command line replace expression' - ' is invalid: invalidReplaceExpr'); - return; - } - expect(true, false); - }); - - group('Replace command line option:', testReplaceCmdLineOption); -} - -void testReplaceCmdLineOption() { - const replaceExpr = r'/mundo/$&!/g'; - - setUp(() { - clearInteractions(_stderr); - updater = Updater(p.join(_testDir, 'frag'), '', - globalReplaceExpr: replaceExpr, err: _stderr); - }); - - _stdFileTest('replace.md'); -} - -void testsFromDefaultDir() { - setUp(() { - _stderr = MockStderr(); - updater = Updater(p.join(_testDir, 'frag'), p.join(_testDir, 'diff_src'), - err: _stderr); - }); - - group('No change to doc;', () { - setUp(() => clearInteractions(_stderr)); - - final testFileNames = [ - 'basic_diff.dart', - 'basic_no_region.dart', - 'basic_with_args.md', - 'basic_with_region.dart', - 'dartdoc.md', - 'diff.md', - 'frag_not_found.dart', - 'invalid_code_block.dart', - 'invalid_code_excerpt_arg.dart', - 'missing_code_block.dart', - 'no_comment_prefix.md', - 'no_path.md', - 'no_src.dart', - 'prettify.md', - 'skip-and-take.md', - ].map((fn) => p.join('no_change', fn)); - - testFileNames.forEach(_stdFileTest); - }); - - group('Code updates;', () { - final testFileNames = [ - 'arg-order.md', - 'basic_no_region.dart', - 'basic_with_empty_region.md', - 'basic_with_region.dart', - 'dartdoc.md', - 'escape_ng_interpolation.md', - 'fragment-indentation.md', - 'language-tour.md', - 'list.md', - 'no_comment_prefix.md', - 'prettify.md', - 'remove.md', - 'retain.md', - ]; - - testFileNames.forEach(_stdFileTest); - }); - - group('Handle trailing space;', () { - test('ensure input file has expected trailing whitespace', () { - final fragPath = p.join( - updater.fragmentDirPath, 'frag_with_trailing_whitespace.dart.txt'); - final frag = _readFile(fragPath); - expect(frag.endsWith('\t \n\n'), isTrue); - }); - - _stdFileTest('trim.dart'); - }); -} - -void testSetPath() { - setUp(() { - updater = Updater(p.join(_testDir, ''), p.join(_testDir, ''), err: _stderr); - }); - - _stdFileTest('set_path.md'); -} - -void testDefaultIndentation() { - setUp(() { - updater = Updater(p.join(_testDir, 'frag'), p.join(_testDir, 'diff_src'), - defaultIndentation: 2, err: _stderr); - }); - - // Diffs are unaffected by the indentation setting. - _stdFileTest(p.join('no_change', 'basic_diff.dart')); - _stdFileTest('basic_with_region.jade'); -} - -void testNoEscapeNgInterpolation() { - setUp(() { - updater = Updater(p.join(_testDir, 'frag'), p.join(_testDir, 'diff_src'), - escapeNgInterpolation: false); - }); - - _stdFileTest('no_escape_ng_interpolation.md'); -} - -void testSrcButNoFrag() { - setUp(() { - updater = - Updater(p.join(_testDir, 'fragDNE'), p.join(_testDir, 'diff_src')); - }); - - _stdFileTest('src_but_no_frag.md'); -} - -void testExcerptYaml() { - final fragAndSrcPath = p.join(_testDir, 'excerpt_yaml'); - - group('defaults:', () { - setUp(() { - updater = Updater( - fragAndSrcPath, - fragAndSrcPath, - excerptsYaml: true, - ); - }); - - final testFileNames = [ - 'excerpt_yaml.md', - 'plaster.md', - ]; - - testFileNames.forEach(_stdFileTest); - }); - - group('globally change default plaster', () { - setUp(() { - updater = Updater( - fragAndSrcPath, - fragAndSrcPath, - excerptsYaml: true, - globalPlasterTemplate: r'// Insert your code here $defaultPlaster', - ); - }); - - _stdFileTest('plaster-global-option.md'); - }); -} diff --git a/packages/code_excerpt_updater/test_data/diff_src/0-base/basic.dart b/packages/code_excerpt_updater/test_data/diff_src/0-base/basic.dart deleted file mode 100644 index 8adf2d2..0000000 --- a/packages/code_excerpt_updater/test_data/diff_src/0-base/basic.dart +++ /dev/null @@ -1,4 +0,0 @@ -var _greeting = 'hello'; -var _scope = 'world'; - -void main() => print('$_greeting $_scope'); diff --git a/packages/code_excerpt_updater/test_data/diff_src/0-base/docregion.dart b/packages/code_excerpt_updater/test_data/diff_src/0-base/docregion.dart deleted file mode 100644 index e9acc49..0000000 --- a/packages/code_excerpt_updater/test_data/diff_src/0-base/docregion.dart +++ /dev/null @@ -1,16 +0,0 @@ -var _greeting = 'hello'; -var _scope = 'world'; - -/// Some -/// doc -/// comment -/// lines -/// to -/// ensure -/// we -/// get -/// two -/// diff -/// hunks -// #docregion main -void main() => print('$_greeting $_scope'); diff --git a/packages/code_excerpt_updater/test_data/diff_src/1-step/basic.dart b/packages/code_excerpt_updater/test_data/diff_src/1-step/basic.dart deleted file mode 100644 index 605e13b..0000000 --- a/packages/code_excerpt_updater/test_data/diff_src/1-step/basic.dart +++ /dev/null @@ -1,4 +0,0 @@ -var _greeting = 'bonjour'; -var _scope = 'world'; - -void main() => print('$_greeting $_scope'); diff --git a/packages/code_excerpt_updater/test_data/diff_src/1-step/docregion.dart b/packages/code_excerpt_updater/test_data/diff_src/1-step/docregion.dart deleted file mode 100644 index 5d4c5a1..0000000 --- a/packages/code_excerpt_updater/test_data/diff_src/1-step/docregion.dart +++ /dev/null @@ -1,16 +0,0 @@ -var _greeting = 'bonjour'; -var _scope = 'world'; - -/// Some -/// doc -/// comment -/// lines -/// to -/// ensure -/// we -/// get -/// two -/// diff -/// hunks -// #docregion main -void main() => print('$_greeting $_scope!'); diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart b/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart deleted file mode 100644 index 177edf6..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart +++ /dev/null @@ -1,7 +0,0 @@ -// #docregion var -var greeting = 'hello'; -var scope = 'world'; -// #enddocregion var - -// #docregion main -void main() => print('$greeting $scope'); diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart.excerpt.yaml deleted file mode 100644 index 7b04e9c..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic.dart.excerpt.yaml +++ /dev/null @@ -1,10 +0,0 @@ -'': |+ - var greeting = 'hello'; - var scope = 'world'; - - void main() => print('$greeting $scope'); -'var': |+ - var greeting = 'hello'; - var scope = 'world'; -'main': |+ - void main() => print('$greeting $scope'); diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic_0.dart b/packages/code_excerpt_updater/test_data/excerpt_yaml/basic_0.dart deleted file mode 100644 index ca01698..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/basic_0.dart +++ /dev/null @@ -1,4 +0,0 @@ -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter.dart.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter.dart.excerpt.yaml deleted file mode 100644 index c765c9c..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter.dart.excerpt.yaml +++ /dev/null @@ -1,6 +0,0 @@ -'trailing blank lines': |+ - var greeting = 'hello'; - - -'main': |+ - void main() => print('$greeting $scope'); diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter_with_border.dart.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter_with_border.dart.excerpt.yaml deleted file mode 100644 index b036141..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/excerpt_getter_with_border.dart.excerpt.yaml +++ /dev/null @@ -1,7 +0,0 @@ -'#border': '|' -'main': |+ - |void main() => print('$greeting $scope'); -'trailing blank lines': |+ - |var greeting = 'hello'; - | - | diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.css.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.css.excerpt.yaml deleted file mode 100644 index 382fa1d..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.css.excerpt.yaml +++ /dev/null @@ -1,4 +0,0 @@ -'': |+ - .abc {} - ··· - .def {} diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.dart.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.dart.excerpt.yaml deleted file mode 100644 index be2d672..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.dart.excerpt.yaml +++ /dev/null @@ -1,8 +0,0 @@ -'': |+ - var greeting = 'hello'; - ··· - var scope = 'world'; -'html': |+ -

- ··· -

diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.html.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.html.excerpt.yaml deleted file mode 100644 index dd21524..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.html.excerpt.yaml +++ /dev/null @@ -1,4 +0,0 @@ -'': |+ -

- ··· -

diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.txt.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.txt.excerpt.yaml deleted file mode 100644 index 74544da..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.txt.excerpt.yaml +++ /dev/null @@ -1,4 +0,0 @@ -'': |+ - abc - ··· - def diff --git a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.yaml.excerpt.yaml b/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.yaml.excerpt.yaml deleted file mode 100644 index 636499a..0000000 --- a/packages/code_excerpt_updater/test_data/excerpt_yaml/plaster.yaml.excerpt.yaml +++ /dev/null @@ -1,4 +0,0 @@ -'': |+ - abc: - ··· - def diff --git a/packages/code_excerpt_updater/test_data/expected/arg-order.md b/packages/code_excerpt_updater/test_data/expected/arg-order.md deleted file mode 100644 index 1d87b5a..0000000 --- a/packages/code_excerpt_updater/test_data/expected/arg-order.md +++ /dev/null @@ -1,10 +0,0 @@ -## Test arg order - - -``` -var greeting = 'bonjour'; -``` - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/expected/basic_no_region.dart b/packages/code_excerpt_updater/test_data/expected/basic_no_region.dart deleted file mode 100644 index c934dbf..0000000 --- a/packages/code_excerpt_updater/test_data/expected/basic_no_region.dart +++ /dev/null @@ -1,27 +0,0 @@ -/// No region arguments in this file. -library; - -/// Test: no code in code block, directive w/o indentation -/// -/// ```html -///
-///

Hello World!

-///
-/// ``` -int? basic1; - -/// Test: no code in code block, directive with indentation -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -num? basic2; - -/// Test: out-of-date code in code block, directive with indentation -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -dynamic basic3; diff --git a/packages/code_excerpt_updater/test_data/expected/basic_with_empty_region.md b/packages/code_excerpt_updater/test_data/expected/basic_with_empty_region.md deleted file mode 100644 index ad10854..0000000 --- a/packages/code_excerpt_updater/test_data/expected/basic_with_empty_region.md +++ /dev/null @@ -1,16 +0,0 @@ -Test: empty region - - -```dart -var greeting = 'hello'; -var scope = 'world'; -``` - -The full file, because an empty region overrides the parenthetical remark in the path/title: - -```dart -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` diff --git a/packages/code_excerpt_updater/test_data/expected/basic_with_region.dart b/packages/code_excerpt_updater/test_data/expected/basic_with_region.dart deleted file mode 100644 index 9d04f09..0000000 --- a/packages/code_excerpt_updater/test_data/expected/basic_with_region.dart +++ /dev/null @@ -1,23 +0,0 @@ -/// Test: no code in code block, directive with indentation -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -void f() {} - -/// Test: region name in path. -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -class D {} - -/// Test: region name in path. -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -class E {} diff --git a/packages/code_excerpt_updater/test_data/expected/basic_with_region.jade b/packages/code_excerpt_updater/test_data/expected/basic_with_region.jade deleted file mode 100644 index f22b024..0000000 --- a/packages/code_excerpt_updater/test_data/expected/basic_with_region.jade +++ /dev/null @@ -1,30 +0,0 @@ -:marked - Test: - - Jade file - - Global indentation setting - - Valueless instruction argument (`title`). - - - ```dart - var greeting = 'hello'; - var scope = 'world'; - ``` - - Test that region argument takes precedence over string in parentheses: - - ``` - var greeting = 'hello'; - var scope = 'world'; - ``` - - - ``` - var greeting = 'hello'; - var scope = 'world'; - ``` - - - ``` - var greeting = 'hello'; - var scope = 'world'; - ``` diff --git a/packages/code_excerpt_updater/test_data/expected/dartdoc.md b/packages/code_excerpt_updater/test_data/expected/dartdoc.md deleted file mode 100644 index 5c08223..0000000 --- a/packages/code_excerpt_updater/test_data/expected/dartdoc.md +++ /dev/null @@ -1,12 +0,0 @@ -## API docs - -Markdown code block opened and closed with more than 3 backticks -that contains another Markdown code block declared with just 3. - - -````dart -/// ```html -///

HTML is magical!

-/// ``` -class HTML {} -```` diff --git a/packages/code_excerpt_updater/test_data/expected/escape_ng_interpolation.md b/packages/code_excerpt_updater/test_data/expected/escape_ng_interpolation.md deleted file mode 100644 index b5253fa..0000000 --- a/packages/code_excerpt_updater/test_data/expected/escape_ng_interpolation.md +++ /dev/null @@ -1,6 +0,0 @@ - -``` -
-

Hello {!{name}!}!

-
-``` diff --git a/packages/code_excerpt_updater/test_data/expected/excerpt_yaml.md b/packages/code_excerpt_updater/test_data/expected/excerpt_yaml.md deleted file mode 100644 index feda383..0000000 --- a/packages/code_excerpt_updater/test_data/expected/excerpt_yaml.md +++ /dev/null @@ -1,19 +0,0 @@ -## Excerpt-yaml tests - -Excerpt: - - -``` -var greeting = 'hello'; -var scope = 'world'; -``` - -Excerpt full source for which there is no `.excerpt.yaml` file. - - -``` -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` diff --git a/packages/code_excerpt_updater/test_data/expected/fragment-indentation.md b/packages/code_excerpt_updater/test_data/expected/fragment-indentation.md deleted file mode 100644 index 1a5bf61..0000000 --- a/packages/code_excerpt_updater/test_data/expected/fragment-indentation.md +++ /dev/null @@ -1,20 +0,0 @@ -## Test: code fragment should be unindented - - -``` -// Fragment is indented by 4 spaces -var x = 1; -return x; -``` - -## Test: code fragment should be unindented - - -``` - // Fragment is indented by 4 spaces - var x = 1; - -/* ... */ - return x; - /* ... */ -``` diff --git a/packages/code_excerpt_updater/test_data/expected/language-tour.md b/packages/code_excerpt_updater/test_data/expected/language-tour.md deleted file mode 100644 index 62ddc5c..0000000 --- a/packages/code_excerpt_updater/test_data/expected/language-tour.md +++ /dev/null @@ -1,47 +0,0 @@ -## Basic prettify tests - -### Without arguments - - -{% prettify %} -This is a **markdown** fragment. -{% endprettify %} - -### With language argument - - -{% prettify dart %} -var greeting = 'hello'; -var scope = 'world'; -{% endprettify %} - - -{% prettify html %} -
-

Hello World!

-
-{% endprettify %} - -### With other arguments - - -{% prettify html tag="code" %} -
-

Hello World!

-
-{% endprettify %} - -### With strip-whitespace syntax - - -{% prettify html tag="code+br" -%} -
-

Hello World!

-
-{%- endprettify %} - - -{%- prettify dart -%} -var greeting = 'hello'; -var scope = 'world'; -{%- endprettify -%} diff --git a/packages/code_excerpt_updater/test_data/expected/list.md b/packages/code_excerpt_updater/test_data/expected/list.md deleted file mode 100644 index d18cd1d..0000000 --- a/packages/code_excerpt_updater/test_data/expected/list.md +++ /dev/null @@ -1,34 +0,0 @@ -## Test instructions in markdown lists - -- - ``` - // Fragment is indented by 4 spaces - var x = 1; - return x; - ``` - -* - ``` - // Fragment is indented by 4 spaces - var x = 1; - - /* ... */ - return x; - /* ... */ - ``` - -- Some text - - ``` - // Fragment is indented by 4 spaces - var x = 1; - return x; - ``` - -* Nested list item next: - - - ``` - // Fragment is indented by 4 spaces - var x = 1; - return x; - ``` diff --git a/packages/code_excerpt_updater/test_data/expected/no_comment_prefix.md b/packages/code_excerpt_updater/test_data/expected/no_comment_prefix.md deleted file mode 100644 index e77bd00..0000000 --- a/packages/code_excerpt_updater/test_data/expected/no_comment_prefix.md +++ /dev/null @@ -1,20 +0,0 @@ -## Test: no code in code block, directive w/o indentation - - -``` -This is a **markdown** fragment. -``` - -## Test: no code in code block, directive with indentation - - -``` - This is a **markdown** fragment. -``` - -## Test: out-of-date code in code block, directive with indentation - - -``` - This is a **markdown** fragment. -``` diff --git a/packages/code_excerpt_updater/test_data/expected/no_escape_ng_interpolation.md b/packages/code_excerpt_updater/test_data/expected/no_escape_ng_interpolation.md deleted file mode 100644 index 43b566f..0000000 --- a/packages/code_excerpt_updater/test_data/expected/no_escape_ng_interpolation.md +++ /dev/null @@ -1,6 +0,0 @@ - -``` -
-

Hello {{name}}!

-
-``` diff --git a/packages/code_excerpt_updater/test_data/expected/plaster-global-option.md b/packages/code_excerpt_updater/test_data/expected/plaster-global-option.md deleted file mode 100644 index 6f539a8..0000000 --- a/packages/code_excerpt_updater/test_data/expected/plaster-global-option.md +++ /dev/null @@ -1,52 +0,0 @@ -## Test plaster feature - -### Globally set default plaster - - -``` -var greeting = 'hello'; -// Insert your code here ··· -var scope = 'world'; -``` - -### Remove plaster - - - - -``` -abc -def -``` - - -``` -abc -··· -def -``` - - - - -``` -abc -// Insert your code here ··· -def -``` - -### Custom template - - -``` -var greeting = 'hello'; -/*...*/ -var scope = 'world'; -``` - - -``` -var greeting = 'hello'; -/* ··· */ -var scope = 'world'; -``` diff --git a/packages/code_excerpt_updater/test_data/expected/plaster.md b/packages/code_excerpt_updater/test_data/expected/plaster.md deleted file mode 100644 index 9b78cfe..0000000 --- a/packages/code_excerpt_updater/test_data/expected/plaster.md +++ /dev/null @@ -1,98 +0,0 @@ -## Test plaster feature - -Testing of this feature only became relevant with the use of YAML excerpts. - -### Plaster for language without comment syntax - - -``` -abc -··· -def -``` - -### Plaster for language with comment syntax - -Languages with start-comment syntax: - - -``` -var greeting = 'hello'; -// ··· -var scope = 'world'; -``` - -Languages with start- and end-comment syntax: - - -``` -.abc {} -/* ··· */ -.def {} -``` - - -``` -

- -

-``` - - -``` -abc: - # ··· - def -``` - -### Remove plaster - - -``` -abc -def -``` - - -``` -var greeting = 'hello'; -var scope = 'world'; -``` - - -``` -abc: - def -``` - -### Language spec on code block - - -```html -

- -

-``` - - -{% prettify html %} -

- -

-{% endprettify %} - -### Custom template - - -``` -var greeting = 'hello'; -/*...*/ -var scope = 'world'; -``` - - -``` -var greeting = 'hello'; -/* ··· */ -var scope = 'world'; -``` diff --git a/packages/code_excerpt_updater/test_data/expected/prettify.md b/packages/code_excerpt_updater/test_data/expected/prettify.md deleted file mode 100644 index 103e5a3..0000000 --- a/packages/code_excerpt_updater/test_data/expected/prettify.md +++ /dev/null @@ -1,14 +0,0 @@ -Also see `no_change/prettify.md` and `language-tour.md` in this test folder for -other prettify tests. - -## API docs - -Prettify block containing triple-backticks: - - -{% prettify html %} -/// ```html -///

HTML is magical!

-/// ``` -class HTML {} -{% endprettify %} diff --git a/packages/code_excerpt_updater/test_data/expected/remove.md b/packages/code_excerpt_updater/test_data/expected/remove.md deleted file mode 100644 index 8c14a1c..0000000 --- a/packages/code_excerpt_updater/test_data/expected/remove.md +++ /dev/null @@ -1,23 +0,0 @@ -## Test remove attribute - -Test plain string argument: - - -``` -var greeting = 'hello'; -var scope = 'world'; -``` - -Test regexp argument: - - -``` -``` - -Test plain string of the form `/.../`: - - -``` -var x = 1; -return x; -``` diff --git a/packages/code_excerpt_updater/test_data/expected/replace.md b/packages/code_excerpt_updater/test_data/expected/replace.md deleted file mode 100644 index 431600b..0000000 --- a/packages/code_excerpt_updater/test_data/expected/replace.md +++ /dev/null @@ -1,112 +0,0 @@ -## Test replace attribute - - -``` -var greeting = 'bonjour'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - - -``` -var greeting = 'bonjour$1$2'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - - -``` -var greeting = 'hello hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - - -``` -var greeting = 'hello/bonjour'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - - -``` -var greeting = 'bonjour'; //? -var scope = 'world'; //! - -void main() => print('$greeting $scope'); //! -``` - -### Special characters starting with a slash - -- Test `\n` in regexp part - - - ``` -

Hello World!

- ``` - -- Test `\n` in replacement part, along with escaped `\\n`: - - - ``` - This is a - markdown - fragment\n - ``` - -- Test replacement of `>` when written as `\x3E`: - - - ``` -
-

Hello World!

-
- ``` - -- Ensure that double slashes aren't interpreted specially: - - - ``` -
-

Hello World\xAB

-
- ``` - -### Command-line and File-global replace test - -Command-line replace expression is /mundo/$&!/g, which is to be applied last. - - - - -``` -var greeting = 'hola'; -var scope = 'mundo!'; - -void main() => print('$greeting $scope'); -``` - -### Reset file-global replace - - - -``` -var greeting = 'bonjour'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - -### Regression: support `}` in regexp. - - -``` -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); //! -``` diff --git a/packages/code_excerpt_updater/test_data/expected/retain.md b/packages/code_excerpt_updater/test_data/expected/retain.md deleted file mode 100644 index b441057..0000000 --- a/packages/code_excerpt_updater/test_data/expected/retain.md +++ /dev/null @@ -1,24 +0,0 @@ -## Test retain attribute - -Test plain string argument: - - -``` -void main() => print('$greeting $scope'); -``` - -Test regexp argument: - - -``` -var greeting = 'hello'; -var scope = 'world'; -void main() => print('$greeting $scope'); -``` - -Test plain string of the form `/.../`: - - -``` -// Fragment is indented by 4 spaces -``` diff --git a/packages/code_excerpt_updater/test_data/expected/set_path.md b/packages/code_excerpt_updater/test_data/expected/set_path.md deleted file mode 100644 index 5825d44..0000000 --- a/packages/code_excerpt_updater/test_data/expected/set_path.md +++ /dev/null @@ -1,7 +0,0 @@ - - - -``` -var greeting = 'hello'; -var scope = 'world'; -``` diff --git a/packages/code_excerpt_updater/test_data/expected/src_but_no_frag.md b/packages/code_excerpt_updater/test_data/expected/src_but_no_frag.md deleted file mode 100644 index 9fa9916..0000000 --- a/packages/code_excerpt_updater/test_data/expected/src_but_no_frag.md +++ /dev/null @@ -1,9 +0,0 @@ -## Test - - -``` -var _greeting = 'hello'; -var _scope = 'world'; - -void main() => print('$_greeting $_scope'); -``` diff --git a/packages/code_excerpt_updater/test_data/expected/trim.dart b/packages/code_excerpt_updater/test_data/expected/trim.dart deleted file mode 100644 index 7096a2b..0000000 --- a/packages/code_excerpt_updater/test_data/expected/trim.dart +++ /dev/null @@ -1,9 +0,0 @@ -// ignore_for_file: type_annotate_public_apis -/// Test: trimming of whitespace from frag lines -/// -/// ```dart -/// // In fragment file, the const declaration line ends with: TAB SPACE -/// // (Beware: some editors trim out trailing whitespace!) -/// const c = 1; -/// ``` -int? v; diff --git a/packages/code_excerpt_updater/test_data/frag/0-base/docregion-main.dart.txt b/packages/code_excerpt_updater/test_data/frag/0-base/docregion-main.dart.txt deleted file mode 100644 index 427a167..0000000 --- a/packages/code_excerpt_updater/test_data/frag/0-base/docregion-main.dart.txt +++ /dev/null @@ -1 +0,0 @@ -void main() => print('$_greeting $_scope'); diff --git a/packages/code_excerpt_updater/test_data/frag/1-step/docregion-main.dart.txt b/packages/code_excerpt_updater/test_data/frag/1-step/docregion-main.dart.txt deleted file mode 100644 index 2ca508f..0000000 --- a/packages/code_excerpt_updater/test_data/frag/1-step/docregion-main.dart.txt +++ /dev/null @@ -1 +0,0 @@ -void main() => print('$_greeting $_scope!'); diff --git a/packages/code_excerpt_updater/test_data/frag/backticks_in_api_doc.dart.txt b/packages/code_excerpt_updater/test_data/frag/backticks_in_api_doc.dart.txt deleted file mode 100644 index 9ef0625..0000000 --- a/packages/code_excerpt_updater/test_data/frag/backticks_in_api_doc.dart.txt +++ /dev/null @@ -1,4 +0,0 @@ -/// ```html -///

HTML is magical!

-/// ``` -class HTML {} diff --git a/packages/code_excerpt_updater/test_data/frag/basic-another-greeting.dart.txt b/packages/code_excerpt_updater/test_data/frag/basic-another-greeting.dart.txt deleted file mode 100644 index ec68bab..0000000 --- a/packages/code_excerpt_updater/test_data/frag/basic-another-greeting.dart.txt +++ /dev/null @@ -1,2 +0,0 @@ -var greeting = 'hello'; -var scope = 'world'; \ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/frag/basic-greeting.dart.txt b/packages/code_excerpt_updater/test_data/frag/basic-greeting.dart.txt deleted file mode 100644 index ec68bab..0000000 --- a/packages/code_excerpt_updater/test_data/frag/basic-greeting.dart.txt +++ /dev/null @@ -1,2 +0,0 @@ -var greeting = 'hello'; -var scope = 'world'; \ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/frag/basic.dart.txt b/packages/code_excerpt_updater/test_data/frag/basic.dart.txt deleted file mode 100644 index ca01698..0000000 --- a/packages/code_excerpt_updater/test_data/frag/basic.dart.txt +++ /dev/null @@ -1,4 +0,0 @@ -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); diff --git a/packages/code_excerpt_updater/test_data/frag/frag_with_trailing_whitespace.dart.txt b/packages/code_excerpt_updater/test_data/frag/frag_with_trailing_whitespace.dart.txt deleted file mode 100644 index 7c69fa0..0000000 --- a/packages/code_excerpt_updater/test_data/frag/frag_with_trailing_whitespace.dart.txt +++ /dev/null @@ -1,4 +0,0 @@ -// In fragment file, the const declaration line ends with: TAB SPACE -// (Beware: some editors trim out trailing whitespace!) -const c = 1; - diff --git a/packages/code_excerpt_updater/test_data/frag/indented_frag-code-blocks.dart.txt b/packages/code_excerpt_updater/test_data/frag/indented_frag-code-blocks.dart.txt deleted file mode 100644 index 0a59d8d..0000000 --- a/packages/code_excerpt_updater/test_data/frag/indented_frag-code-blocks.dart.txt +++ /dev/null @@ -1,6 +0,0 @@ - // Fragment is indented by 4 spaces - var x = 1; - - /* ... */ - return x; - /* ... */ diff --git a/packages/code_excerpt_updater/test_data/frag/indented_frag-single-code-block.dart.txt b/packages/code_excerpt_updater/test_data/frag/indented_frag-single-code-block.dart.txt deleted file mode 100644 index bafb53c..0000000 --- a/packages/code_excerpt_updater/test_data/frag/indented_frag-single-code-block.dart.txt +++ /dev/null @@ -1,3 +0,0 @@ - // Fragment is indented by 4 spaces - var x = 1; - return x; diff --git a/packages/code_excerpt_updater/test_data/frag/ng_interpolation.html.txt b/packages/code_excerpt_updater/test_data/frag/ng_interpolation.html.txt deleted file mode 100644 index 7b3b6ef..0000000 --- a/packages/code_excerpt_updater/test_data/frag/ng_interpolation.html.txt +++ /dev/null @@ -1,3 +0,0 @@ -
-

Hello {{name}}!

-
\ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/frag/no_region.dart.txt b/packages/code_excerpt_updater/test_data/frag/no_region.dart.txt deleted file mode 100644 index ec68bab..0000000 --- a/packages/code_excerpt_updater/test_data/frag/no_region.dart.txt +++ /dev/null @@ -1,2 +0,0 @@ -var greeting = 'hello'; -var scope = 'world'; \ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/frag/no_region.html.txt b/packages/code_excerpt_updater/test_data/frag/no_region.html.txt deleted file mode 100644 index b346b03..0000000 --- a/packages/code_excerpt_updater/test_data/frag/no_region.html.txt +++ /dev/null @@ -1,3 +0,0 @@ -
-

Hello World!

-
\ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/frag/quote.md.txt b/packages/code_excerpt_updater/test_data/frag/quote.md.txt deleted file mode 100644 index 2b630d6..0000000 --- a/packages/code_excerpt_updater/test_data/frag/quote.md.txt +++ /dev/null @@ -1 +0,0 @@ -This is a **markdown** fragment. \ No newline at end of file diff --git a/packages/code_excerpt_updater/test_data/src/arg-order.md b/packages/code_excerpt_updater/test_data/src/arg-order.md deleted file mode 100644 index 7f67070..0000000 --- a/packages/code_excerpt_updater/test_data/src/arg-order.md +++ /dev/null @@ -1,9 +0,0 @@ -## Test arg order - - -``` -``` - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/basic_no_region.dart b/packages/code_excerpt_updater/test_data/src/basic_no_region.dart deleted file mode 100644 index 6253de6..0000000 --- a/packages/code_excerpt_updater/test_data/src/basic_no_region.dart +++ /dev/null @@ -1,22 +0,0 @@ -/// No region arguments in this file. -library; - -/// Test: no code in code block, directive w/o indentation -/// -/// ```html -/// ``` -int? basic1; - -/// Test: no code in code block, directive with indentation -/// -/// ```dart -/// ``` -num? basic2; - -/// Test: out-of-date code in code block, directive with indentation -/// -/// ```dart -/// we don't care what this text is since it will be replaced -/// misindented text that we don't care about -/// ``` -dynamic basic3; diff --git a/packages/code_excerpt_updater/test_data/src/basic_with_empty_region.md b/packages/code_excerpt_updater/test_data/src/basic_with_empty_region.md deleted file mode 100644 index 0e18c24..0000000 --- a/packages/code_excerpt_updater/test_data/src/basic_with_empty_region.md +++ /dev/null @@ -1,10 +0,0 @@ -Test: empty region - - -```dart -``` - -The full file, because an empty region overrides the parenthetical remark in the path/title: - -```dart -``` diff --git a/packages/code_excerpt_updater/test_data/src/basic_with_region.dart b/packages/code_excerpt_updater/test_data/src/basic_with_region.dart deleted file mode 100644 index 3855d1f..0000000 --- a/packages/code_excerpt_updater/test_data/src/basic_with_region.dart +++ /dev/null @@ -1,17 +0,0 @@ -/// Test: no code in code block, directive with indentation -/// -/// ```dart -/// ``` -void f() {} - -/// Test: region name in path. -/// -/// ```dart -/// ``` -class D {} - -/// Test: region name in path. -/// -/// ```dart -/// ``` -class E {} diff --git a/packages/code_excerpt_updater/test_data/src/basic_with_region.jade b/packages/code_excerpt_updater/test_data/src/basic_with_region.jade deleted file mode 100644 index 670b728..0000000 --- a/packages/code_excerpt_updater/test_data/src/basic_with_region.jade +++ /dev/null @@ -1,22 +0,0 @@ -:marked - Test: - - Jade file - - Global indentation setting - - Valueless instruction argument (`title`). - - - ```dart - ``` - - Test that region argument takes precedence over string in parentheses: - - ``` - ``` - - - ``` - ``` - - - ``` - ``` diff --git a/packages/code_excerpt_updater/test_data/src/dartdoc.md b/packages/code_excerpt_updater/test_data/src/dartdoc.md deleted file mode 100644 index 6b85d49..0000000 --- a/packages/code_excerpt_updater/test_data/src/dartdoc.md +++ /dev/null @@ -1,8 +0,0 @@ -## API docs - -Markdown code block opened and closed with more than 3 backticks -that contains another Markdown code block declared with just 3. - - -````dart -```` diff --git a/packages/code_excerpt_updater/test_data/src/escape_ng_interpolation.md b/packages/code_excerpt_updater/test_data/src/escape_ng_interpolation.md deleted file mode 100644 index 27f788f..0000000 --- a/packages/code_excerpt_updater/test_data/src/escape_ng_interpolation.md +++ /dev/null @@ -1,3 +0,0 @@ - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/excerpt_yaml.md b/packages/code_excerpt_updater/test_data/src/excerpt_yaml.md deleted file mode 100644 index 1dce974..0000000 --- a/packages/code_excerpt_updater/test_data/src/excerpt_yaml.md +++ /dev/null @@ -1,13 +0,0 @@ -## Excerpt-yaml tests - -Excerpt: - - -``` -``` - -Excerpt full source for which there is no `.excerpt.yaml` file. - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/fragment-indentation.md b/packages/code_excerpt_updater/test_data/src/fragment-indentation.md deleted file mode 100644 index aae339e..0000000 --- a/packages/code_excerpt_updater/test_data/src/fragment-indentation.md +++ /dev/null @@ -1,11 +0,0 @@ -## Test: code fragment should be unindented - - -``` -``` - -## Test: code fragment should be unindented - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/language-tour.md b/packages/code_excerpt_updater/test_data/src/language-tour.md deleted file mode 100644 index 2f90c7b..0000000 --- a/packages/code_excerpt_updater/test_data/src/language-tour.md +++ /dev/null @@ -1,35 +0,0 @@ -## Basic prettify tests - -### Without arguments - - -{% prettify %} -... -{% endprettify %} - -### With language argument - - -{% prettify dart %} -... -{% endprettify %} - - -{% prettify html %} -{% endprettify %} - -### With other arguments - - -{% prettify html tag="code" %} -{% endprettify %} - -### With strip-whitespace syntax - - -{% prettify html tag="code+br" -%} -{%- endprettify %} - - -{%- prettify dart -%} -{%- endprettify -%} diff --git a/packages/code_excerpt_updater/test_data/src/list.md b/packages/code_excerpt_updater/test_data/src/list.md deleted file mode 100644 index a84cca3..0000000 --- a/packages/code_excerpt_updater/test_data/src/list.md +++ /dev/null @@ -1,19 +0,0 @@ -## Test instructions in markdown lists - -- - ``` - ``` - -* - ``` - ``` - -- Some text - - ``` - ``` - -* Nested list item next: - - - ``` - ``` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/basic_diff.dart b/packages/code_excerpt_updater/test_data/src/no_change/basic_diff.dart deleted file mode 100644 index 7250ed3..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/basic_diff.dart +++ /dev/null @@ -1,38 +0,0 @@ -/// Test: multi line -/// -/// -/// ```diff -/// --- 0-base/basic.dart -/// +++ 1-step/basic.dart -/// @@ -1,4 +1,4 @@ -/// -var _greeting = 'hello'; -/// +var _greeting = 'bonjour'; -/// var _scope = 'world'; -/// -/// void main() => print('$_greeting $_scope'); -/// ``` -class C {} - -/// -/// ```diff -/// ``` -class D {} - -/// -/// ```diff -/// --- 0-base/basic.dart -/// +++ 1-step/basic.dart -/// @@ -1 +1 @@ -/// -var _greeting = 'hello'; -/// +var _greeting = 'bonjour'; -/// ``` -class E {} - -/// -/// ```diff -/// --- 0-base/basic.dart -/// +++ 1-step/basic.dart -/// @@ -1 +1 @@ -/// -var _greeting = 'hello'; -/// ``` -class F {} diff --git a/packages/code_excerpt_updater/test_data/src/no_change/basic_no_region.dart b/packages/code_excerpt_updater/test_data/src/no_change/basic_no_region.dart deleted file mode 100644 index 08aebbd..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/basic_no_region.dart +++ /dev/null @@ -1,16 +0,0 @@ -/// Test: non-indented code, multi line -/// -/// ```html -///
-///

Hello World!

-///
-/// ``` -int? basic1; - -/// Test: indented code, multi line -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -void f() {} diff --git a/packages/code_excerpt_updater/test_data/src/no_change/basic_with_args.md b/packages/code_excerpt_updater/test_data/src/no_change/basic_with_args.md deleted file mode 100644 index 6d90e6d..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/basic_with_args.md +++ /dev/null @@ -1,49 +0,0 @@ -## Test `from` arg - - -```dart -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - -Pattern not in excerpt: - - -```dart -``` - -## Test `to` arg - - -```dart -var greeting = 'hello'; -var scope = 'world'; -``` - -Pattern matching last line of excerpt: - - -```dart -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - -Pattern not in excerpt: - - -```dart -var greeting = 'hello'; -var scope = 'world'; - -void main() => print('$greeting $scope'); -``` - -## Test `from` and `to` - - -```dart -var scope = 'world'; -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/basic_with_region.dart b/packages/code_excerpt_updater/test_data/src/no_change/basic_with_region.dart deleted file mode 100644 index f5e030f..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/basic_with_region.dart +++ /dev/null @@ -1,23 +0,0 @@ -/// Test: multi line -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -class C {} - -/// Test: region name in path. -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -class D {} - -/// Test: region name in path. -/// -/// ```dart -/// var greeting = 'hello'; -/// var scope = 'world'; -/// ``` -class E {} diff --git a/packages/code_excerpt_updater/test_data/src/no_change/dartdoc.md b/packages/code_excerpt_updater/test_data/src/no_change/dartdoc.md deleted file mode 100644 index 5c08223..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/dartdoc.md +++ /dev/null @@ -1,12 +0,0 @@ -## API docs - -Markdown code block opened and closed with more than 3 backticks -that contains another Markdown code block declared with just 3. - - -````dart -/// ```html -///

HTML is magical!

-/// ``` -class HTML {} -```` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/diff.md b/packages/code_excerpt_updater/test_data/src/no_change/diff.md deleted file mode 100644 index efc2424..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/diff.md +++ /dev/null @@ -1,109 +0,0 @@ -## Diff tests of code blocks in Markdown `diff` tags - -## Basic - - -```diff ---- 0-base/basic.dart -+++ 1-step/basic.dart -@@ -1,4 +1,4 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - var _scope = 'world'; - - void main() => print('$_greeting $_scope'); -``` - -### Files with docregion tags - - -```diff ---- 0-base/docregion.dart -+++ 1-step/docregion.dart -@@ -1,4 +1,4 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - var _scope = 'world'; - - /// Some -@@ -12,4 +12,4 @@ - /// two - /// diff - /// hunks --void main() => print('$_greeting $_scope'); -+void main() => print('$_greeting $_scope!'); -``` - -### Diff region - - -```diff ---- 0-base/docregion.dart (main) -+++ 1-step/docregion.dart (main) -@@ -1 +1 @@ --void main() => print('$_greeting $_scope'); -+void main() => print('$_greeting $_scope!'); -``` - -### Files with docregion tags and diff-u argument - - -```diff ---- 0-base/docregion.dart -+++ 1-step/docregion.dart -@@ -1,5 +1,5 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - var _scope = 'world'; - - /// Some - /// doc -@@ -11,5 +11,5 @@ - /// get - /// two - /// diff - /// hunks --void main() => print('$_greeting $_scope'); -+void main() => print('$_greeting $_scope!'); -``` - -## Bash path-brace syntax for diffs - - -```diff ---- 0-base/basic.dart -+++ 1-step/basic.dart -@@ -1,4 +1,4 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - var _scope = 'world'; - - void main() => print('$_greeting $_scope'); -``` - -## Bash path-brace syntax with diff-with error - - -```diff ---- 0-base/basic.dart -+++ 1-step/basic.dart -@@ -1,4 +1,4 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - var _scope = 'world'; - - void main() => print('$_greeting $_scope'); -``` - -## Remove argument - - -```diff ---- 0-base/basic.dart -+++ 1-step/basic.dart -@@ -1,3 +1,3 @@ --var _greeting = 'hello'; -+var _greeting = 'bonjour'; - - void main() => print('$_greeting $_scope'); -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/frag_not_found.dart b/packages/code_excerpt_updater/test_data/src/no_change/frag_not_found.dart deleted file mode 100644 index a6a5c04..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/frag_not_found.dart +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// ``` -/// ... -/// ``` -int? x; diff --git a/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_block.dart b/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_block.dart deleted file mode 100644 index efe8a9b..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_block.dart +++ /dev/null @@ -1,4 +0,0 @@ -/// Closing code-block token is missing below: -/// -/// ``` -int x = 1; diff --git a/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_excerpt_arg.dart b/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_excerpt_arg.dart deleted file mode 100644 index 77ee211..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/invalid_code_excerpt_arg.dart +++ /dev/null @@ -1,2 +0,0 @@ -/// -int? noApiDoc0; diff --git a/packages/code_excerpt_updater/test_data/src/no_change/missing_code_block.dart b/packages/code_excerpt_updater/test_data/src/no_change/missing_code_block.dart deleted file mode 100644 index ae187b7..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/missing_code_block.dart +++ /dev/null @@ -1,3 +0,0 @@ -/// Missing code block -/// -int x = 0; diff --git a/packages/code_excerpt_updater/test_data/src/no_change/no_comment_prefix.md b/packages/code_excerpt_updater/test_data/src/no_change/no_comment_prefix.md deleted file mode 100644 index cf5c615..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/no_comment_prefix.md +++ /dev/null @@ -1,13 +0,0 @@ -## Test: code without indentation, single line - - -``` -This is a **markdown** fragment. -``` - -## Test: indented code, single line - - -``` - This is a **markdown** fragment. -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/no_path.md b/packages/code_excerpt_updater/test_data/src/no_change/no_path.md deleted file mode 100644 index 91be199..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/no_path.md +++ /dev/null @@ -1,11 +0,0 @@ -Test: code-excerpt instruction w/o a path; i.e., which need not be updated: - - -```html -

Hello {{name}}!

-``` - - -```dart -var x = 1; -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_change/no_src.dart b/packages/code_excerpt_updater/test_data/src/no_change/no_src.dart deleted file mode 100644 index dc5fb4b..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/no_src.dart +++ /dev/null @@ -1,2 +0,0 @@ -/// A file with no PIs -int? noApiDoc0; diff --git a/packages/code_excerpt_updater/test_data/src/no_change/prettify.md b/packages/code_excerpt_updater/test_data/src/no_change/prettify.md deleted file mode 100644 index 018c576..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/prettify.md +++ /dev/null @@ -1,17 +0,0 @@ -Regression test for https://github.com/dart-lang/site-www/pull/719. -Originally, when run on the code excerpt instruction below, -the code excerpt would be duplicated. - -Also see `../prettify.md` and `language-tour.md` in this test folder for other prettify tests. - -## API docs - -Prettify block containing triple-backticks: - - -{% prettify html %} -/// ```html -///

HTML is magical!

-/// ``` -class HTML {} -{% endprettify %} diff --git a/packages/code_excerpt_updater/test_data/src/no_change/skip-and-take.md b/packages/code_excerpt_updater/test_data/src/no_change/skip-and-take.md deleted file mode 100644 index 4386ff6..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_change/skip-and-take.md +++ /dev/null @@ -1,36 +0,0 @@ -## Test `skip` - - -```dart -void main() => print('$greeting $scope'); -``` - -Negative arg: - - -```dart -var greeting = 'hello'; -var scope = 'world'; -``` - -## Test `take` - - -```dart -var greeting = 'hello'; -var scope = 'world'; -``` - -Negative arg: - - -```dart -void main() => print('$greeting $scope'); -``` - -## Test `skip` and `take` together - - -```dart -var scope = 'world'; -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_comment_prefix.md b/packages/code_excerpt_updater/test_data/src/no_comment_prefix.md deleted file mode 100644 index 0518966..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_comment_prefix.md +++ /dev/null @@ -1,19 +0,0 @@ -## Test: no code in code block, directive w/o indentation - - -``` -``` - -## Test: no code in code block, directive with indentation - - -``` -``` - -## Test: out-of-date code in code block, directive with indentation - - -``` - we don't care what this text is since it will be replaced -misindented text that we don't care about -``` diff --git a/packages/code_excerpt_updater/test_data/src/no_escape_ng_interpolation.md b/packages/code_excerpt_updater/test_data/src/no_escape_ng_interpolation.md deleted file mode 100644 index 27f788f..0000000 --- a/packages/code_excerpt_updater/test_data/src/no_escape_ng_interpolation.md +++ /dev/null @@ -1,3 +0,0 @@ - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/plaster-global-option.md b/packages/code_excerpt_updater/test_data/src/plaster-global-option.md deleted file mode 100644 index 2c7bab8..0000000 --- a/packages/code_excerpt_updater/test_data/src/plaster-global-option.md +++ /dev/null @@ -1,35 +0,0 @@ -## Test plaster feature - -### Globally set default plaster - - -``` -``` - -### Remove plaster - - - - -``` -``` - - -``` -``` - - - - -``` -``` - -### Custom template - - -``` -``` - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/plaster.md b/packages/code_excerpt_updater/test_data/src/plaster.md deleted file mode 100644 index d4716ab..0000000 --- a/packages/code_excerpt_updater/test_data/src/plaster.md +++ /dev/null @@ -1,65 +0,0 @@ -## Test plaster feature - -Testing of this feature only became relevant with the use of YAML excerpts. - -### Plaster for language without comment syntax - - -``` -``` - -### Plaster for language with comment syntax - -Languages with start-comment syntax: - - -``` -``` - -Languages with start- and end-comment syntax: - - -``` -``` - - -``` -``` - - -``` -``` - -### Remove plaster - - -``` -``` - - -``` -``` - - -``` -``` - -### Language spec on code block - - -```html -``` - - -{% prettify html %} -{% endprettify %} - -### Custom template - - -``` -``` - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/prettify.md b/packages/code_excerpt_updater/test_data/src/prettify.md deleted file mode 100644 index c19c0c2..0000000 --- a/packages/code_excerpt_updater/test_data/src/prettify.md +++ /dev/null @@ -1,11 +0,0 @@ -Also see `no_change/prettify.md` and `language-tour.md` in this test folder for -other prettify tests. - -## API docs - -Prettify block containing triple-backticks: - - -{% prettify html %} -... -{% endprettify %} diff --git a/packages/code_excerpt_updater/test_data/src/remove.md b/packages/code_excerpt_updater/test_data/src/remove.md deleted file mode 100644 index 96b4c30..0000000 --- a/packages/code_excerpt_updater/test_data/src/remove.md +++ /dev/null @@ -1,19 +0,0 @@ -## Test remove attribute - -Test plain string argument: - - -``` -``` - -Test regexp argument: - - -``` -``` - -Test plain string of the form `/.../`: - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/replace.md b/packages/code_excerpt_updater/test_data/src/replace.md deleted file mode 100644 index 6670cf7..0000000 --- a/packages/code_excerpt_updater/test_data/src/replace.md +++ /dev/null @@ -1,70 +0,0 @@ -## Test replace attribute - - -``` -``` - - -``` -``` - - -``` -``` - - -``` -``` - - -``` -``` - -### Special characters starting with a slash - -- Test `\n` in regexp part - - - ``` - ``` - -- Test `\n` in replacement part, along with escaped `\\n`: - - - ``` - ``` - -- Test replacement of `>` when written as `\x3E`: - - - ``` - ``` - -- Ensure that double slashes aren't interpreted specially: - - - ``` - ``` - -### Command-line and File-global replace test - -Command-line replace expression is /mundo/$&!/g, which is to be applied last. - - - - -``` -``` - -### Reset file-global replace - - - -``` -``` - -### Regression: support `}` in regexp. - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/retain.md b/packages/code_excerpt_updater/test_data/src/retain.md deleted file mode 100644 index 37f301a..0000000 --- a/packages/code_excerpt_updater/test_data/src/retain.md +++ /dev/null @@ -1,19 +0,0 @@ -## Test retain attribute - -Test plain string argument: - - -``` -``` - -Test regexp argument: - - -``` -``` - -Test plain string of the form `/.../`: - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/set_path.md b/packages/code_excerpt_updater/test_data/src/set_path.md deleted file mode 100644 index c13dfcc..0000000 --- a/packages/code_excerpt_updater/test_data/src/set_path.md +++ /dev/null @@ -1,5 +0,0 @@ - - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/src_but_no_frag.md b/packages/code_excerpt_updater/test_data/src/src_but_no_frag.md deleted file mode 100644 index d467dec..0000000 --- a/packages/code_excerpt_updater/test_data/src/src_but_no_frag.md +++ /dev/null @@ -1,5 +0,0 @@ -## Test - - -``` -``` diff --git a/packages/code_excerpt_updater/test_data/src/trim.dart b/packages/code_excerpt_updater/test_data/src/trim.dart deleted file mode 100644 index 81d4553..0000000 --- a/packages/code_excerpt_updater/test_data/src/trim.dart +++ /dev/null @@ -1,6 +0,0 @@ -// ignore_for_file: type_annotate_public_apis -/// Test: trimming of whitespace from frag lines -/// -/// ```dart -/// ``` -int? v; diff --git a/packages/code_excerpter/.gitignore b/packages/code_excerpter/.gitignore deleted file mode 100644 index fdc2120..0000000 --- a/packages/code_excerpter/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Files and directories created by pub -.dart_tool -.pub/ -build/ -packages -# Remove the following pattern if you wish to check in your lock file -pubspec.lock - -# Directory created by dartdoc -doc/api/ - -# IDEs -.idea/ -.vscode/ diff --git a/packages/code_excerpter/CHANGELOG.md b/packages/code_excerpter/CHANGELOG.md deleted file mode 100644 index 43c45c2..0000000 --- a/packages/code_excerpter/CHANGELOG.md +++ /dev/null @@ -1,61 +0,0 @@ -# Changelog - -## 1.0.0 - -- When YAML excerpt files are generated, the excerpt values - are now multiline strings with a left border character as - the first character of each line. The value of the special - map key '#border' is the border character. (The code-excerpt - updater trims of this border character when present.) - -## 0.6.2 - -- Internal changes (ran format --fix). - -## 0.6.1 - -- Don't process dot files. - -## 0.6.0 - -- Upgrade to v1 of `builder` and `build_runner`. - -## 0.5.0 - -- Set max SDK version to <3.0.0. - -## 0.4.1 - -- Updated README to explain usage, syntax, etc. -- Set min SDK to 2.0.0-dev.67.0 and upgrade `build_runner` to 0.9.0. - -## 0.4.0 - -- Set min SDK to 2.0.0-dev.64.1 and upgrade `test` to 1.0.0. - -## 0.3.1+1, +2 - -- Set min SDK to 2.0.0-dev.61 and other package version downgrades. - -## 0.3.1 - -- Fix type error. -- Set min SDK to 2.0.0-dev.62 - -## 0.3.0 - -- Change base config so that the builder applies to all packages - (via `auto_apply: all_packages`). - -## 0.2.0 - -- Support quoted default region name `''`, and deprecate - unquoted default region name usage. -- Warn about repeated region names. - -## 0.1.0 - -- First public version, inspired by JavaScript-based - [github.com/chalin/code-excerpter](https://github.com/chalin/code-excerpter), - which was derived from tooling used under angular.io. - diff --git a/packages/code_excerpter/LICENSE b/packages/code_excerpter/LICENSE deleted file mode 100644 index fc5612b..0000000 --- a/packages/code_excerpter/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2018 Dart Project Authors https://www.dartlang.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/packages/code_excerpter/README.md b/packages/code_excerpter/README.md deleted file mode 100644 index 22c583d..0000000 --- a/packages/code_excerpter/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# code_excerpter - -A line-based builder for extracting code regions from source files. - -Documentation for a package or framework often contains code excerpts. -There are two main approaches to ensuring that such **code excerpts remain -up-to-date** as the package or framework code base evolves. -(1) A [literate programming][] approach, where **code -fragments are extracted from the docs**, then analyzed and tested. -(2) A complementary approach where named **code regions are extracted from -sources**, and docs are refreshed (as needed) when code regions change. - -Both approaches have their merits, but `code_excerpter`, and its companion tool -[code_excerpt_updater][], support (2). More specifically: - -- `code_excerpter` is a builder that can be used to extract code regions from source files. -- [code_excerpt_updater][] can be used to refresh code regions inside docs using - the output from `code_excerpter` - -## Usage synopsis - -1. One-time setup: define a builder config file. -2. Markup your sources with (optionally named) code regions - delimited by `#docregion` / `#enddocregion` pairs, each written - inside a line comment. An example is given below. -3. Run the builder. -4. Use [code_excerpt_updater][] to update your docs. - -Repeat steps 2-4 as the code base evolves. - -## Examples sources - - -```dart -// #docregion imports -import 'dart:async'; -// #enddocregion imports - -// #docregion main, main-stub -void main() async { - // #enddocregion main-stub - print('Compute π using the Monte Carlo method.'); - await for (var estimate in computePi().take(500)) { - print('π ≅ $estimate'); - } - // #docregion main-stub -} -// #enddocregion main, main-stub - -/// Generates a stream of increasingly accurate estimates of π. -Stream computePi({int batch: 100000}) async* { - // ... -} -``` - -The regions defined in the Dart source above are: `imports`, `main`, `main-stub`, -and (implicitly) the **default region** named `''`. -If you don't explicitly delimit the default region, it is assumed to be the -entire file. - -Some of the regions defined in the example above include: - -- `imports` region: - > ```dart - > import 'dart:async'; - > ``` - -- `main-stub` region: - > ```dart - > void main() async { - > // ··· - > } - > ``` - -The `main-stub` region is discontinuous, that is, it has a break in it. -By default, when the [code_excerpt_updater][] renders a region with breaks, -each breaks is replaced by a (language-specific) comment line filled with a -plaster marker (`···`). - -For details concerning the processing of plasters, see the -[code_excerpt_updater][] documentation. - -Notes: - -- If a code region end coincides with the file end, then its closing - `#enddocregion` can be omitted. -- The `code_excerpter` supports source files in all popular languages including - Dart, HTML, YAML, CSS, SCSS, and more. - - -## Syntax - -As illustrated above, the region markers can be followed by zero or more comma-separated region names. - -A legal **region name** is one of: - -- `''` -- A non-empty sequence of alphanumeric characters possibly containing a hyphen (`-`) - or an underscore (`_`). - -## Sample builder config - -To use the builder, create a config file such as the following: - -```yaml -targets: - $default: - sources: - include: [examples/**] - exclude: - - '**/.*/**' - - '**/build/**' - builders: - code_excerpter|code_excerpter: - enabled: true -``` - -Build by running this command: - -```console -> pub run build_runner build --output= -``` - -Yaml files containing excerpts (`*.excerpt.yaml`) will be placed in the build output folder. - -[code_excerpt_updater]: https://github.com/chalin/code_excerpt_updater -[literate programming]: https://en.wikipedia.org/wiki/Literate_programming \ No newline at end of file diff --git a/packages/code_excerpter/analysis_options.yaml b/packages/code_excerpter/analysis_options.yaml deleted file mode 100644 index b9bdf80..0000000 --- a/packages/code_excerpter/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:analysis_defaults/analysis.yaml diff --git a/packages/code_excerpter/build.yaml b/packages/code_excerpter/build.yaml deleted file mode 100644 index e285e02..0000000 --- a/packages/code_excerpter/build.yaml +++ /dev/null @@ -1,31 +0,0 @@ -builders: - code_excerpter: - import: 'package:code_excerpter/builder.dart' - auto_apply: all_packages - builder_factories: [builder] - build_extensions: {'': [.excerpt.yaml]} - # TODO(redbrogdon): Consider removing this if not used elsewhere. - defaults: - generate_for: - include: - - example/** - - examples/** - - lib/** - - test/** - - web/** - exclude: - - '**/.*' - - '**/.*/**' - - '**/.DS_Store' - - '**/build/**' - - '**/node_modules/**' - - '**/*.bmp' - - '**/*.cur' - - '**/*.ico' - - '**/*.jpg' - - '**/*.jpeg' - - '**/*.png' - - '**/*.sum' - - '**/*.tiff' - - '**/*.zip' - - '**/*.gzip' diff --git a/packages/code_excerpter/lib/builder.dart b/packages/code_excerpter/lib/builder.dart deleted file mode 100644 index 0501de2..0000000 --- a/packages/code_excerpter/lib/builder.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'dart:async'; - -import 'package:build/build.dart'; - -import 'src/excerpter.dart'; -import 'src/util/line.dart'; - -const excerptLineLeftBorderChar = '|'; - -Builder builder(BuilderOptions options) => CodeExcerptBuilder(options); - -class CodeExcerptBuilder implements Builder { - static const outputExtension = '.excerpt.yaml'; - - final BuilderOptions? options; - - CodeExcerptBuilder([this.options]); - - @override - Future build(BuildStep buildStep) async { - final assetId = buildStep.inputId; - if (assetId.package.startsWith(r'$') || assetId.path.endsWith(r'$')) return; - - final String content; - try { - content = await buildStep.readAsString(assetId); - } on FormatException { - log.finest('Skipped ${assetId.path} due to failing to read as string.'); - return; - } - - final outputAssetId = assetId.addExtension(outputExtension); - - final excerpter = Excerpter(assetId.path, content); - final yaml = _toYaml(excerpter.weave().excerpts); - if (yaml.isNotEmpty) { - await buildStep.writeAsString(outputAssetId, yaml); - log.info('wrote $outputAssetId'); - } else { - // log.warning(' $outputAssetId has no excerpts'); - } - } - - @override - Map> get buildExtensions => { - '': [outputExtension] - }; - - String _toYaml(Map> excerpts) { - if (excerpts.isEmpty) return ''; - - const yamlExcerptLeftBorderCharKey = '#border'; - final s = StringBuffer(); - - s.writeln("'$yamlExcerptLeftBorderCharKey': '$excerptLineLeftBorderChar'"); - excerpts.forEach((name, lines) { - s.writeln(_yamlEntry(name, lines)); - }); - return s.toString(); - } - - String _yamlEntry(String regionName, List lines) { - final codeAsYamlStringValue = lines - // YAML multiline string: indent by 2 spaces. - .map((line) => ' $excerptLineLeftBorderChar$line') - .join(eol); - return "'$regionName': |+\n$codeAsYamlStringValue"; - } -} diff --git a/packages/code_excerpter/lib/src/directive.dart b/packages/code_excerpter/lib/src/directive.dart deleted file mode 100644 index 7f12dcd..0000000 --- a/packages/code_excerpter/lib/src/directive.dart +++ /dev/null @@ -1,96 +0,0 @@ -/// Directives usually appear inside a line comment. -/// -/// Ignore any close-comment syntax: -/// -/// - CSS and Java-like languages: `*/` -/// - HTML: `-->` -/// -final _directiveRegEx = RegExp( - r'^(\s*)(\S.*?)?#((?:end)?docregion)\b\s*(.*?)(?:\s*(?:-->|\*\/))?\s*$'); - -final _argSeparator = RegExp(r'\s*,\s*'); - -/// Represents a code-excerpter directive (both the model and lexical elements) -class Directive { - static const int _lexemeIndex = 3; - - final Match _match; - final Kind kind; - - late final List _args; - - /// Issues raised while parsing this directive. - final List issues = []; - - Directive._(this.kind, this._match) { - final argsMaybeWithDups = _parseArgs(); - final argCounts = {}; - - for (var arg in argsMaybeWithDups) { - if (arg.isEmpty) { - issues.add('unquoted default region name is deprecated'); - } else if (arg == "''") { - arg = ''; - } - - var argCount = argCounts[arg] ?? 0; - argCount += 1; - - if (argCount == 2) { - issues.add('repeated argument "$arg"'); - } - - argCounts[arg] = argCount; - } - - _args = argCounts.keys.toList(); - } - - String get line => _match[0] ?? ''; - - /// Whitespace before the directive - String get indentation => _match[1] ?? ''; - - /// Characters at the start of the line before the directive lexeme - String get prefix => indentation + (_match[2] ?? ''); - - /// The directive's lexeme or empty if not found - String get lexeme => _match[_lexemeIndex] ?? ''; - - /// Raw string corresponding to the directive's arguments - String get rawArgs => _match[4] ?? ''; - - List get args => _args; - - static Directive? tryParse(String line) { - final match = _directiveRegEx.firstMatch(line); - - if (match == null) return null; - - final lexeme = match[_lexemeIndex]; - final kind = tryParseKind(lexeme); - return kind == null ? null : Directive._(kind, match); - } - - List _parseArgs() => - rawArgs.isEmpty ? const [] : rawArgs.split(_argSeparator); -} - -enum Kind { - startRegion, - endRegion, - plaster, // TO be deprecated -} - -Kind? tryParseKind(String? lexeme) { - switch (lexeme) { - case 'docregion': - return Kind.startRegion; - case 'enddocregion': - return Kind.endRegion; - case 'docplaster': - return Kind.plaster; - default: - return null; - } -} diff --git a/packages/code_excerpter/lib/src/excerpter.dart b/packages/code_excerpter/lib/src/excerpter.dart deleted file mode 100644 index 2bd6ff1..0000000 --- a/packages/code_excerpter/lib/src/excerpter.dart +++ /dev/null @@ -1,186 +0,0 @@ -import 'directive.dart'; -import 'util/line.dart'; -import 'util/logging.dart'; - -/// Key used for excerpt representing the entire file w/o directives -const fullFileKey = '\u0000'; -const defaultRegionKey = ''; -const defaultPlaster = '···'; - -Map> newExcerptsMap() => {}; - -class Excerpter { - final String uri; - final String content; - final List _lines; // content as list of lines - - // Index of next line to process. - int _lineIdx; - int get _lineNum => _lineIdx + 1; - String get _line => _lines[_lineIdx]; - - bool containsDirectives = false; - - int get numExcerpts => excerpts.length; - - Excerpter(this.uri, this.content) - : _lines = content.split(eol), - _lineIdx = 0; - - final Map> excerpts = newExcerptsMap(); - final Set _openExcerpts = {}; - - Excerpter weave() { - final lines = content.split(eol); - - // Collect the full file in case we need it. - _excerptStart(fullFileKey); - - for (_lineIdx = 0; _lineIdx < lines.length; _lineIdx++) { - _processLine(); - } - - // Drop trailing blank lines for all excerpts. - // Normalize indentation for all but the full file. - for (final entry in excerpts.entries) { - final name = entry.key; - final excerpt = entry.value; - - dropTrailingBlankLines(excerpt); - _dropTrailingPlaster(excerpt); - if (name == fullFileKey) continue; - excerpts[name] = maxUnindent(excerpt).toList(); - } - - // Final adjustment to excerpts relative to fullFileKey: - if (!containsDirectives) { - // No directives? Don't report any excerpts - excerpts.clear(); - } else if (excerpts.containsKey(defaultRegionKey)) { - // There was an explicitly named default region. Drop fullFileKey. - excerpts.remove(fullFileKey); - } else { - // Report fullFileKey excerpt for defaultRegionKey - final fullFileExcerpt = excerpts.remove(fullFileKey); - if (fullFileExcerpt != null) { - excerpts[defaultRegionKey] = fullFileExcerpt; - } - } - return this; - } - - void _processLine() { - final directive = Directive.tryParse(_line); - - if (directive == null) { - // Add line to open regions - for (final name in _openExcerpts) { - excerpts[name]?.add(_line); - } - return; - } - - directive.issues.forEach(_warn); - - switch (directive.kind) { - case Kind.startRegion: - containsDirectives = true; - _startRegion(directive); - case Kind.endRegion: - containsDirectives = true; - _endRegion(directive); - default: - throw Exception('Unimplemented directive: $_line'); - } - } - - void _startRegion(Directive directive) { - final regionAlreadyStarted = []; - final regionNames = directive.args; - - log.finer('_startRegion(regionNames = $regionNames)'); - - if (regionNames.isEmpty) regionNames.add(defaultRegionKey); - for (final name in regionNames) { - final isNew = _excerptStart(name); - if (!isNew) { - regionAlreadyStarted.add(_quoteName(name)); - } - } - - _warnRegions( - regionAlreadyStarted, - (regions) => 'repeated start for $regions', - ); - } - - void _endRegion(Directive directive) { - final regionsWithoutStart = []; - final regionNames = directive.args; - log.finer('_endRegion(regionNames = $regionNames)'); - - if (regionNames.isEmpty) { - regionNames.add(''); - // _warn('${directive.lexeme} has no explicit arguments; assuming ""'); - } - - for (final name in regionNames) { - if (_openExcerpts.remove(name)) { - final excerpt = excerpts[name]; - if (excerpt == null) { - return; - } - - if (excerpt.isEmpty) { - _warnRegions( - [name], - (regions) => 'empty $regions', - ); - } - excerpt.add(directive.indentation + defaultPlaster); - } else { - regionsWithoutStart.add(_quoteName(name)); - } - } - - _warnRegions( - regionsWithoutStart, - (regions) => '$regions end without a prior start', - ); - } - - void _warnRegions( - List regions, - String Function(String) msg, - ) { - if (regions.isEmpty) return; - final joinedRegions = regions.join(', '); - final s = joinedRegions.isEmpty - ? '' - : regions.length > 1 - ? 's ($joinedRegions)' - : ' $joinedRegions'; - _warn(msg('region$s')); - } - - /// Registers [name] as an open excerpt. - /// - /// If [name] is a new excerpt, then its value in - /// [excerpts] is set to the empty list. - /// - /// Returns false iff name was already open - bool _excerptStart(String name) { - excerpts.putIfAbsent(name, () => []); - return _openExcerpts.add(name); - } - - void _warn(String msg) => log.warning('$msg at $uri:$_lineNum'); - - /// Quote a region name if it isn't already quoted. - String _quoteName(String name) => name.startsWith("'") ? name : '"$name"'; - - void _dropTrailingPlaster(List excerpt) { - if (excerpt.isEmpty || !excerpt.last.contains(defaultPlaster)) return; - excerpt.removeLast(); - } -} diff --git a/packages/code_excerpter/lib/src/util/line.dart b/packages/code_excerpter/lib/src/util/line.dart deleted file mode 100644 index 7e3497f..0000000 --- a/packages/code_excerpter/lib/src/util/line.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:math' show min; - -const eol = '\n'; - -final blankLine = RegExp(r'^\s*$'); -final _leadingWhitespace = RegExp(r'^[ \t]*'); - -/// WARNING: this method potentially mutates its argument. -void dropTrailingBlankLines(List lines) { - // Drop any blank lines at the end of lines - while (lines.isNotEmpty && blankLine.hasMatch(lines.last)) { - lines.removeLast(); - } -} - -/// Unindent [lines] to the extent possible without losing -/// the relative inter-line indentation. Note that blank -/// lines are ignored in the process computing the maximal -/// left-shift. -Iterable maxUnindent(Iterable lines) { - final nonBlankLines = lines.where((s) => !blankLine.hasMatch(s)); - - // Length of leading spaces to be trimmed - final lengths = nonBlankLines.map((s) { - final matchLength = _leadingWhitespace.firstMatch(s)?[0]?.length; - return matchLength ?? 0; - }); - - if (lengths.isEmpty) { - return lines; - } - - final len = lengths.reduce(min); - return len == 0 - ? lines - : lines.map((line) => line.length < len ? line : line.substring(len)); -} diff --git a/packages/code_excerpter/lib/src/util/logging.dart b/packages/code_excerpter/lib/src/util/logging.dart deleted file mode 100644 index b82f5c6..0000000 --- a/packages/code_excerpter/lib/src/util/logging.dart +++ /dev/null @@ -1,45 +0,0 @@ -/// Exposes a singleton logger via [log]. -/// -/// The singleton logger is initialized as follows: -/// -/// - If the build system logger is defined, that logger is used. -/// - Otherwise, create a new Logger named 'package:code_excerpter' -/// -library; - -import 'dart:async'; - -import 'package:logging/logging.dart'; - -const _buildLogKey = #buildLog; - -/// Initial logging level. It must be set before calling [log]. -Level initLevel = Level.FINE; - -/// The build logger or if there isn't one, a new default logger. -final Logger log = () { - // Use build logger if there is one: - var logger = Zone.current[_buildLogKey] as Logger?; - - if (logger == null) { - logger = Logger('package:code_excerpter'); - Logger.root.level = initLevel; - Logger.root.onRecord.listen((r) { - for (final h in logListeners) { - h(r); - } - }); - } - - return logger; -}(); - -//--------------------------------------------------------- - -typedef LogListener = void Function(LogRecord); - -final List logListeners = [ - printLogRecord, -]; - -void printLogRecord(LogRecord r) => print('${r.level.name}: ${r.message}'); diff --git a/packages/code_excerpter/mono_pkg.yaml b/packages/code_excerpter/mono_pkg.yaml deleted file mode 100644 index d4e257b..0000000 --- a/packages/code_excerpter/mono_pkg.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# See https://github.com/google/mono_repo.dart for details on this file -sdk: -- pubspec -- dev - -stages: -- analyzer_and_format: - - group: - - format - - analyze: --fatal-infos . -- unit_test: - - test: diff --git a/packages/code_excerpter/pubspec.yaml b/packages/code_excerpter/pubspec.yaml deleted file mode 100644 index 4492cc2..0000000 --- a/packages/code_excerpter/pubspec.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: code_excerpter -publish_to: none - -environment: - sdk: ^3.4.0 - -dependencies: - build: ^2.4.1 - logging: ^1.2.0 - path: ^1.9.0 - yaml: ^3.1.2 - -dev_dependencies: - analysis_defaults: - path: ../analysis_defaults - build_runner: ^2.4.9 - test: ^1.25.2 diff --git a/packages/code_excerpter/test/builder_input/example.dart b/packages/code_excerpter/test/builder_input/example.dart deleted file mode 100644 index 3090b05..0000000 --- a/packages/code_excerpter/test/builder_input/example.dart +++ /dev/null @@ -1,19 +0,0 @@ -// #docregion imports -import 'dart:async'; -// #enddocregion imports - -// #docregion main, main-stub -Future main() async { - // #enddocregion main-stub - print('Compute π using the Monte Carlo method.'); - await for (final estimate in computePi().take(500)) { - print('π ≅ $estimate'); - } - // #docregion main-stub -} -// #enddocregion main, main-stub - -/// Generates a stream of increasingly accurate estimates of π. -Stream computePi({int batch = 100000}) async* { - // ... -} diff --git a/packages/code_excerpter/test/builder_input/example.html b/packages/code_excerpter/test/builder_input/example.html deleted file mode 100644 index 01ade72..0000000 --- a/packages/code_excerpter/test/builder_input/example.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Title - - - - - - - - - diff --git a/packages/code_excerpter/test/builder_test.dart b/packages/code_excerpter/test/builder_test.dart deleted file mode 100644 index 3866eb9..0000000 --- a/packages/code_excerpter/test/builder_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'dart:io'; - -import 'package:build/build.dart'; -import 'package:code_excerpter/builder.dart'; -import 'package:test/test.dart'; -import 'package:yaml/yaml.dart'; - -void main() { - test('build.yaml build_extensions matches Builder', () { - final buildYamlFile = File('build.yaml'); - final content = buildYamlFile.readAsStringSync(); - final yaml = loadYaml(content) as YamlMap; - final builders = yaml['builders'] as Map; - expect(builders, isNotNull); - final codeExcerpter = builders['code_excerpter'] as Map; - expect(codeExcerpter, isNotNull); - final buildExtensions = codeExcerpter['build_extensions'] as Map; - expect(buildExtensions, isNotNull); - expect(buildExtensions, CodeExcerptBuilder().buildExtensions); - }); - - test('top-level builder factory function returns a CodeExcerptBuilder', () { - expect(builder(BuilderOptions.empty), isA()); - }); -} diff --git a/packages/code_excerpter/test/directive_test.dart b/packages/code_excerpter/test/directive_test.dart deleted file mode 100644 index 7035825..0000000 --- a/packages/code_excerpter/test/directive_test.dart +++ /dev/null @@ -1,142 +0,0 @@ -import 'package:code_excerpter/src/directive.dart'; -import 'package:test/test.dart'; - -void main() { - group('basic', () { - test('not a directive', () { - final d = Directive.tryParse(''); - expect(d, isNull); - }); - - test(Kind.startRegion, () { - final d = Directive.tryParse('#docregion'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, ''); - expect(d.args, []); - } - }); - - test(Kind.endRegion, () { - final d = Directive.tryParse('#enddocregion'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.endRegion); - expect(d.rawArgs, ''); - expect(d.args, []); - } - }); - }); - - // Leading and trailing text is ignored - group('context insensitive', () { - test(Kind.startRegion, () { - const spaces = ' '; - final d = Directive.tryParse('$spaces// #docregion'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, ''); - expect(d.args, []); - expect(d.indentation, spaces); - } - }); - - test(Kind.endRegion, () { - final d = Directive.tryParse(' #enddocregion a,b, c '); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.endRegion); - expect(d.rawArgs, 'a,b, c'); - expect(d.args, ['a', 'b', 'c']); - expect(d.indentation, ' '); - } - }); - }); - - group('close comment syntax:', () { - group('HTML:', () { - test(Kind.startRegion, () { - final d = Directive.tryParse(''); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, ''); - expect(d.args, []); - expect(d.indentation, ''); - } - }); - - test(Kind.endRegion, () { - final d = Directive.tryParse(' '); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.endRegion); - expect(d.rawArgs, 'a'); - expect(d.args, ['a']); - expect(d.indentation, ''); - } - }); - }); - - group('CSS:', () { - test(Kind.startRegion, () { - final d = Directive.tryParse('/*#docregion*/'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, ''); - expect(d.args, []); - expect(d.indentation, ''); - } - }); - - test(Kind.endRegion, () { - final d = Directive.tryParse('/* #enddocregion a */ '); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.endRegion); - expect(d.rawArgs, 'a'); - expect(d.args, ['a']); - expect(d.indentation, ''); - } - }); - }); - }); - - group('problem cases:', () { - test('Deprecated unquoted default region name', () { - final d = Directive.tryParse('#docregion ,a'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, ',a'); - expect(d.args, ['', 'a']); - expect(d.issues, ['unquoted default region name is deprecated']); - } - }); - - test('Duplicate "a" region', () { - final d = Directive.tryParse('#docregion a,b,c,a'); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, 'a,b,c,a'); - expect(d.args, ['a', 'b', 'c']); - expect(d.issues, ['repeated argument "a"']); - } - }); - - test('Duplicate "" region', () { - final d = Directive.tryParse("#docregion '',''"); - expect(d, isNotNull); - if (d != null) { - expect(d.kind, Kind.startRegion); - expect(d.rawArgs, "'',''"); - expect(d.args, ['']); - expect(d.issues, ['repeated argument ""']); - } - }); - }); -} diff --git a/packages/code_excerpter/test/excerpter_test.dart b/packages/code_excerpter/test/excerpter_test.dart deleted file mode 100644 index aef840e..0000000 --- a/packages/code_excerpter/test/excerpter_test.dart +++ /dev/null @@ -1,337 +0,0 @@ -import 'package:code_excerpter/src/excerpter.dart'; -import 'package:code_excerpter/src/util/logging.dart'; -import 'package:logging/logging.dart'; -import 'package:test/test.dart'; - -// Mock URI used for all content origins. -const uri = 'foo'; - -List contentGeneratingNoExcerpts = [ - '', - 'abc', - 'abc\ndef\n', - 'docregion', // Without leading # -]; - -final emptyLines = List.unmodifiable([]); - -final List logs = []; - -void _expectNoLogs() => expect(logs, []); - -void main() { - setUpAll(() { - logListeners.clear(); // Don't print during tests - logListeners.add(logs.add); - }); - - setUp(logs.clear); - - // Each individual test must check [logs], and then clear them. - // This will catch situations where this is not done. - tearDown(_expectNoLogs); - - test('helper sanity:', () { - const content = ''' - #docregion a - abc - #enddocregion a - #docregion b - def - #enddocregion b - '''; - expect(stripDirectives(content), [ - ' abc', - ' def', - ]); - }); - - group('no excerpts:', () { - for (final content in contentGeneratingNoExcerpts) { - final testName = "'${content.replaceAll('\n', '\\n')}'"; - test(testName, () { - final excerpter = Excerpter(uri, content); - excerpter.weave(); - expect(excerpter.excerpts, >{}); - _expectNoLogs(); - }); - } - }); - - // Independent of indentation - group('basic delimited default region:', () { - test('1-line region', () { - final excerpter = Excerpter(uri, '#docregion\nabc\n#enddocregion'); - excerpter.weave(); - expect(excerpter.excerpts, { - defaultRegionKey: ['abc'] - }); - _expectNoLogs(); - }); - }); - - group('normalized indentation:', () { - test('default region', () { - final excerpter = Excerpter(uri, ''' - #docregion - abc - #enddocregion - '''); - expect(excerpter.weave().excerpts, { - defaultRegionKey: ['abc'] - }); - _expectNoLogs(); - }); - - test('region a', () { - const content = ''' - #docregion a - abc - #enddocregion a - '''; - final excerpter = Excerpter(uri, content); - expect(excerpter.weave().excerpts, { - defaultRegionKey: [' abc'], - 'a': ['abc'], - }); - _expectNoLogs(); - }); - }); - - test('two disjoint regions', () { - const content = ''' - #docregion a - abc - #enddocregion a - #docregion b - def - #enddocregion b - '''; - final excerpter = Excerpter(uri, content); - expect(excerpter.weave().excerpts, { - defaultRegionKey: stripDirectives(content), - 'a': ['abc'], - 'b': ['def'], - }); - _expectNoLogs(); - }); - - group('region not closed:', () { - for (final eol in const ['', '\n']) { - group('empty region:', () { - test('default region', () { - final excerpter = Excerpter(uri, '#docregion$eol'); - expect(excerpter.weave().excerpts, {defaultRegionKey: emptyLines}); - _expectNoLogs(); - }); - - test('region a', () { - final excerpter = Excerpter(uri, '#docregion a$eol'); - expect(excerpter.weave().excerpts, - {defaultRegionKey: emptyLines, 'a': emptyLines}); - _expectNoLogs(); - }); - }); - - test('region with a line', () { - final expectedLines = ['abc']; - final excerpter = Excerpter(uri, '#docregion b\nabc$eol'); - expect(excerpter.weave().excerpts, - {defaultRegionKey: expectedLines, 'b': expectedLines}); - _expectNoLogs(); - }); - } - }); - - group('problems:', problemCases); - group('plaster:', plasterCases); -} - -void problemCases() { - test('empty region', () { - final excerpter = Excerpter(uri, '#docregion\n#enddocregion'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, contains('empty region at $uri:2')); - expect(excerpter.excerpts, {defaultRegionKey: []}); - logs.clear(); - }); - - group('end before start', () { - test('default region', () { - final excerpter = Excerpter(uri, '#enddocregion'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, - contains('region "" end without a prior start at $uri:1')); - expect(excerpter.excerpts, {defaultRegionKey: emptyLines}); - logs.clear(); - }); - - test('region a', () { - final excerpter = Excerpter(uri, 'abc\n#enddocregion a'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, - contains('region "a" end without a prior start at $uri:2')); - expect(excerpter.excerpts, { - defaultRegionKey: ['abc'] - }); - logs.clear(); - }); - - test('region a,b', () { - final excerpter = Excerpter(uri, 'abc\n#enddocregion a,b'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, - contains('regions ("a", "b") end without a prior start at $uri:2')); - expect(excerpter.excerpts, { - defaultRegionKey: ['abc'] - }); - logs.clear(); - }); - - test('start a end default region', () { - final expectedLines = ['abc']; - final excerpter = Excerpter(uri, '#docregion a\nabc\n#enddocregion'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, - contains('region "" end without a prior start at $uri:3')); - expect(excerpter.excerpts, { - defaultRegionKey: expectedLines, - 'a': expectedLines, - }); - logs.clear(); - }); - }); - - group('repeated start:', () { - test('default region', () { - final excerpter = Excerpter(uri, '#docregion\n#docregion'); - excerpter.weave(); - expect(logs.length, 1); - expect( - logs[0].message, contains('repeated start for region "" at $uri:2')); - expect(excerpter.excerpts, { - defaultRegionKey: [], - }); - logs.clear(); - }); - - test('region a', () { - final excerpter = Excerpter(uri, '#docregion a\n#docregion a'); - excerpter.weave(); - expect(logs.length, 1); - expect( - logs[0].message, contains('repeated start for region "a" at $uri:2')); - expect(excerpter.excerpts, { - defaultRegionKey: [], - 'a': [], - }); - logs.clear(); - }); - }); - - group('directives:', () { - test('warn unquoted default region name', () { - final excerpter = Excerpter(uri, '#docregion ,a'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, - contains('unquoted default region name is deprecated at $uri:1')); - expect(excerpter.excerpts, { - defaultRegionKey: [], - 'a': [], - }); - logs.clear(); - }); - - test('dup "a" region', () { - final excerpter = Excerpter(uri, '#docregion a,a'); - excerpter.weave(); - expect(logs.length, 1); - expect(logs[0].message, contains('repeated argument "a" at $uri:1')); - expect(excerpter.excerpts, { - defaultRegionKey: [], - 'a': [], - }); - logs.clear(); - }); - }); -} - -void plasterCases() { - test('region a with 1 plaster', () { - const content = ''' - #docregion a - abc - #enddocregion a - 123 - #docregion a - def - #enddocregion a - '''; - final excerpter = Excerpter(uri, content); - expect(excerpter.weave().excerpts, { - defaultRegionKey: stripDirectives(content), - 'a': ['abc', defaultPlaster, 'def'], - }); - _expectNoLogs(); - }); - - test('overlapping regions', () { - const content = ''' - #docregion a,b,c - abc - #enddocregion b, c - #docregion b - def - #enddocregion a, b - '''; - final excerpter = Excerpter(uri, content); - expect(excerpter.weave().excerpts, { - defaultRegionKey: stripDirectives(content), - 'a': ['abc', 'def'], - 'b': ['abc', defaultPlaster, 'def'], - 'c': ['abc'], - }); - _expectNoLogs(); - }); - - test('plaster with different indentations', () { - const content = ''' - #docregion a,b,c - abc - #enddocregion b, c - #docregion b - def - #enddocregion a, b - '''; - final excerpter = Excerpter(uri, content); - expect(excerpter.weave().excerpts, { - defaultRegionKey: stripDirectives(content), - 'a': ['abc', 'def'], - 'b': ['abc', ' $defaultPlaster', 'def'], - 'c': ['abc'], - }); - _expectNoLogs(); - }); -} - -// Utils - -const eol = '\n'; - -final _directiveRegEx = RegExp(r'#(end)?docregion'); -final _blankLine = RegExp(r'^\s*$'); - -List stripDirectives(String excerpt) { - final lines = excerpt - .split(eol) - .where((line) => !_directiveRegEx.hasMatch(line)) - .toList(); - if (_blankLine.hasMatch(lines.last)) lines.removeLast(); - return lines; -} diff --git a/packages/code_excerpter/test/util_test.dart b/packages/code_excerpter/test/util_test.dart deleted file mode 100644 index 131b145..0000000 --- a/packages/code_excerpter/test/util_test.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:code_excerpter/src/util/line.dart'; -import 'package:test/test.dart'; - -void main() { - group('maxUnindent', () { - test('empty list', () { - expect(maxUnindent([]), []); - }); - - test('no leading space', () { - final lines = ['abc']; - expect(maxUnindent(lines), lines); - }); - - test('with leading space', () { - final lines = [' abc']; - expect(maxUnindent(lines), ['abc']); - }); - - test('trim one leading space', () { - final lines = [' abc', ' def']; - expect(maxUnindent(lines), [' abc', 'def']); - }); - - test('ignore blank lines', () { - final lines = [ - ' abc', - ' ', - ' ', - ' def', - '', - ' ', - ]; - dropTrailingBlankLines(lines); - expect(maxUnindent(lines), [' abc', '', ' ', 'def']); - }); - }); -}