prosereflect 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +63 -0
- data/.github/workflows/links.yml +97 -0
- data/.gitignore +4 -0
- data/.rubocop_todo.yml +61 -75
- data/README.adoc +2 -0
- data/docs/Gemfile +10 -0
- data/docs/INDEX.adoc +45 -0
- data/docs/_advanced/index.adoc +15 -0
- data/docs/_advanced/schema.adoc +112 -0
- data/docs/_advanced/step-map.adoc +66 -0
- data/docs/_advanced/steps.adoc +88 -0
- data/docs/_advanced/test-builder.adoc +61 -0
- data/docs/_advanced/transform.adoc +92 -0
- data/docs/_config.yml +174 -0
- data/docs/_features/html-input.adoc +69 -0
- data/docs/_features/html-output.adoc +45 -0
- data/docs/_features/index.adoc +15 -0
- data/docs/_features/marks.adoc +86 -0
- data/docs/_features/node-types.adoc +124 -0
- data/docs/_features/user-mentions.adoc +47 -0
- data/docs/_guides/custom-nodes.adoc +107 -0
- data/docs/_guides/index.adoc +13 -0
- data/docs/_guides/round-trip-html.adoc +91 -0
- data/docs/_guides/serialization.adoc +109 -0
- data/docs/_pages/index.adoc +67 -0
- data/docs/_reference/document-api.adoc +49 -0
- data/docs/_reference/index.adoc +14 -0
- data/docs/_reference/node-api.adoc +79 -0
- data/docs/_reference/schema-api.adoc +95 -0
- data/docs/_reference/transform-api.adoc +77 -0
- data/docs/_understanding/document-model.adoc +65 -0
- data/docs/_understanding/fragment.adoc +52 -0
- data/docs/_understanding/index.adoc +14 -0
- data/docs/_understanding/resolved-position.adoc +53 -0
- data/docs/_understanding/slice.adoc +54 -0
- data/docs/lychee.toml +63 -0
- data/lib/prosereflect/blockquote.rb +9 -0
- data/lib/prosereflect/bullet_list.rb +25 -19
- data/lib/prosereflect/code_block.rb +1 -5
- data/lib/prosereflect/fragment.rb +249 -0
- data/lib/prosereflect/horizontal_rule.rb +9 -0
- data/lib/prosereflect/image.rb +9 -0
- data/lib/prosereflect/input/html.rb +96 -0
- data/lib/prosereflect/node.rb +141 -3
- data/lib/prosereflect/ordered_list.rb +2 -0
- data/lib/prosereflect/output/html.rb +227 -0
- data/lib/prosereflect/parser.rb +9 -0
- data/lib/prosereflect/resolved_pos.rb +256 -0
- data/lib/prosereflect/schema/attribute.rb +57 -0
- data/lib/prosereflect/schema/content_match.rb +656 -0
- data/lib/prosereflect/schema/fragment.rb +166 -0
- data/lib/prosereflect/schema/mark.rb +121 -0
- data/lib/prosereflect/schema/mark_type.rb +130 -0
- data/lib/prosereflect/schema/node.rb +236 -0
- data/lib/prosereflect/schema/node_type.rb +274 -0
- data/lib/prosereflect/schema/schema_main.rb +190 -0
- data/lib/prosereflect/schema/spec.rb +92 -0
- data/lib/prosereflect/schema.rb +39 -0
- data/lib/prosereflect/text.rb +24 -0
- data/lib/prosereflect/transform/attr_step.rb +157 -0
- data/lib/prosereflect/transform/insert_step.rb +115 -0
- data/lib/prosereflect/transform/mapping.rb +82 -0
- data/lib/prosereflect/transform/mark_step.rb +269 -0
- data/lib/prosereflect/transform/replace_around_step.rb +181 -0
- data/lib/prosereflect/transform/replace_step.rb +157 -0
- data/lib/prosereflect/transform/slice.rb +91 -0
- data/lib/prosereflect/transform/step.rb +89 -0
- data/lib/prosereflect/transform/step_map.rb +126 -0
- data/lib/prosereflect/transform/structure.rb +120 -0
- data/lib/prosereflect/transform/transform.rb +341 -0
- data/lib/prosereflect/transform.rb +26 -0
- data/lib/prosereflect/version.rb +1 -1
- data/lib/prosereflect.rb +3 -0
- data/spec/fixtures/documents/formatted_text.yaml +14 -0
- data/spec/fixtures/documents/heading_paragraph.yaml +16 -0
- data/spec/fixtures/documents/lists_doc.yaml +32 -0
- data/spec/fixtures/documents/mixed_content.yaml +40 -0
- data/spec/fixtures/documents/nested_doc.yaml +20 -0
- data/spec/fixtures/documents/simple_doc.yaml +6 -0
- data/spec/fixtures/documents/table_doc.yaml +32 -0
- data/spec/fixtures/documents/transform_test.yaml +14 -0
- data/spec/fixtures/schema/custom_schema.rb +37 -0
- data/spec/fixtures/schema/test_schema.rb +46 -0
- data/spec/fixtures/test_builder/helpers.rb +212 -0
- data/spec/prosereflect/document_spec.rb +1 -1
- data/spec/prosereflect/fragment_spec.rb +273 -0
- data/spec/prosereflect/input/html_spec.rb +197 -1
- data/spec/prosereflect/node_spec.rb +128 -0
- data/spec/prosereflect/output/whitespace_spec.rb +248 -0
- data/spec/prosereflect/parser/round_trip_spec.rb +472 -0
- data/spec/prosereflect/resolved_pos_spec.rb +74 -0
- data/spec/prosereflect/schema/conftest.rb +68 -0
- data/spec/prosereflect/schema/content_match_spec.rb +237 -0
- data/spec/prosereflect/schema/mark_spec.rb +274 -0
- data/spec/prosereflect/schema/mark_type_spec.rb +86 -0
- data/spec/prosereflect/schema/node_type_spec.rb +142 -0
- data/spec/prosereflect/schema/schema_spec.rb +194 -0
- data/spec/prosereflect/test_builder/marks_spec.rb +127 -0
- data/spec/prosereflect/transform/equivalence_spec.rb +487 -0
- data/spec/prosereflect/transform/mapping_spec.rb +226 -0
- data/spec/prosereflect/transform/replace_spec.rb +832 -0
- data/spec/prosereflect/transform/replace_step_spec.rb +157 -0
- data/spec/prosereflect/transform/slice_spec.rb +48 -0
- data/spec/prosereflect/transform/step_map_spec.rb +70 -0
- data/spec/prosereflect/transform/step_spec.rb +211 -0
- data/spec/prosereflect/transform/structure_spec.rb +98 -0
- data/spec/prosereflect/transform/transform_spec.rb +238 -0
- data/spec/spec_helper.rb +1 -0
- metadata +90 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d9f70970efc856c322c1d356262ae1492856c2432d2ed6343b7f00a4b96a97a9
|
|
4
|
+
data.tar.gz: 4670d12e397d85fa399ea4bd721d0eaa4d35aa24b7425c0bb7e6b61eb057a173
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 42bb32f0114a3cb597a65498681177c93345f3ddcff24412a2ba03dd8492b1ec0da306797ada94fac95c984e0f80a63631de555fae2a836b647c8805ab73e0b6
|
|
7
|
+
data.tar.gz: d6b5dcf22e6d6b0c923c5b35a1dbccecea6e7103af0001428ca567ad8f2333d2f63fe7652149f087b2ea0383beff80afc69e02b09f086f93b5fd51ee7be1dca1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'docs/**'
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- 'docs/**'
|
|
11
|
+
repository_dispatch:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
pages: write
|
|
17
|
+
id-token: write
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: false
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout
|
|
28
|
+
uses: actions/checkout@v6
|
|
29
|
+
|
|
30
|
+
- name: Setup Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
ruby-version: '3.3'
|
|
34
|
+
bundler-cache: true
|
|
35
|
+
cache-version: 0
|
|
36
|
+
working-directory: docs
|
|
37
|
+
|
|
38
|
+
- name: Setup Pages
|
|
39
|
+
id: pages
|
|
40
|
+
uses: actions/configure-pages@v5
|
|
41
|
+
|
|
42
|
+
- name: Build with Jekyll
|
|
43
|
+
run: bundle exec jekyll build --verbose --trace --baseurl "${{ steps.pages.outputs.base_path }}"
|
|
44
|
+
working-directory: docs
|
|
45
|
+
env:
|
|
46
|
+
JEKYLL_ENV: production
|
|
47
|
+
|
|
48
|
+
- name: Upload artifact
|
|
49
|
+
uses: actions/upload-pages-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
path: docs/_site
|
|
52
|
+
|
|
53
|
+
deploy:
|
|
54
|
+
environment:
|
|
55
|
+
name: github-pages
|
|
56
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
57
|
+
if: ${{ github.ref == 'refs/heads/main' }}
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
needs: build
|
|
60
|
+
steps:
|
|
61
|
+
- name: Deploy to GitHub Pages
|
|
62
|
+
id: deployment
|
|
63
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
name: links
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
pull_request:
|
|
10
|
+
paths:
|
|
11
|
+
- 'docs/**'
|
|
12
|
+
|
|
13
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
pull-requests: write
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
link_checker:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v6
|
|
23
|
+
|
|
24
|
+
- uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: '3.4'
|
|
27
|
+
bundler-cache: true
|
|
28
|
+
working-directory: docs
|
|
29
|
+
|
|
30
|
+
- name: Build site
|
|
31
|
+
env:
|
|
32
|
+
JEKYLL_ENV: production
|
|
33
|
+
run: bundle exec jekyll build --trace
|
|
34
|
+
working-directory: docs
|
|
35
|
+
|
|
36
|
+
- name: Restore lychee cache
|
|
37
|
+
uses: actions/cache@v4
|
|
38
|
+
with:
|
|
39
|
+
path: .lycheecache
|
|
40
|
+
key: cache-lychee-${{ github.sha }}
|
|
41
|
+
restore-keys: cache-lychee-
|
|
42
|
+
|
|
43
|
+
- name: Check if site was built
|
|
44
|
+
run: |
|
|
45
|
+
if [ ! -d "_site" ]; then
|
|
46
|
+
echo "Error: _site directory not created"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
echo "Site built successfully"
|
|
50
|
+
ls -la _site/
|
|
51
|
+
working-directory: docs
|
|
52
|
+
|
|
53
|
+
- name: Link Checker (Built Site)
|
|
54
|
+
uses: lycheeverse/lychee-action@v2
|
|
55
|
+
with:
|
|
56
|
+
args: >-
|
|
57
|
+
--verbose
|
|
58
|
+
--no-progress
|
|
59
|
+
--config lychee.toml
|
|
60
|
+
--root-dir "$(pwd)/_site"
|
|
61
|
+
--scheme https,http
|
|
62
|
+
'_site/**/*.html'
|
|
63
|
+
fail: true
|
|
64
|
+
output: link-check-results.md
|
|
65
|
+
format: markdown
|
|
66
|
+
workingDirectory: docs
|
|
67
|
+
|
|
68
|
+
- name: Upload link check results
|
|
69
|
+
if: always()
|
|
70
|
+
uses: actions/upload-artifact@v4
|
|
71
|
+
with:
|
|
72
|
+
name: link-check-results
|
|
73
|
+
path: |
|
|
74
|
+
docs/link-check-results.md
|
|
75
|
+
retention-days: 30
|
|
76
|
+
|
|
77
|
+
- name: Comment PR with results
|
|
78
|
+
if: failure() && github.event_name == 'pull_request'
|
|
79
|
+
uses: actions/github-script@v7
|
|
80
|
+
with:
|
|
81
|
+
script: |
|
|
82
|
+
const fs = require('fs');
|
|
83
|
+
let comment = '## Link Check Failed\n\n';
|
|
84
|
+
|
|
85
|
+
if (fs.existsSync('docs/link-check-results.md')) {
|
|
86
|
+
const results = fs.readFileSync('docs/link-check-results.md', 'utf8');
|
|
87
|
+
comment += '### Built Site Results\n\n' + results + '\n\n';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
comment += '\n---\n\n*Please fix the broken links and push a new commit.*';
|
|
91
|
+
|
|
92
|
+
github.rest.issues.createComment({
|
|
93
|
+
issue_number: context.issue.number,
|
|
94
|
+
owner: context.repo.owner,
|
|
95
|
+
repo: context.repo.repo,
|
|
96
|
+
body: comment
|
|
97
|
+
});
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-04-
|
|
3
|
+
# on 2026-04-14 23:12:52 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -11,17 +11,29 @@ Gemspec/RequiredRubyVersion:
|
|
|
11
11
|
Exclude:
|
|
12
12
|
- 'prosereflect.gemspec'
|
|
13
13
|
|
|
14
|
-
# Offense count:
|
|
14
|
+
# Offense count: 2
|
|
15
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
16
|
-
|
|
17
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
18
|
-
# SupportedColonStyles: key, separator, table
|
|
19
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
20
|
-
Layout/HashAlignment:
|
|
16
|
+
Layout/ElseAlignment:
|
|
21
17
|
Exclude:
|
|
22
|
-
- '
|
|
18
|
+
- 'lib/prosereflect/schema/schema_main.rb'
|
|
23
19
|
|
|
24
|
-
# Offense count:
|
|
20
|
+
# Offense count: 1
|
|
21
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
22
|
+
# Configuration parameters: EnforcedStyleAlignWith.
|
|
23
|
+
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
|
24
|
+
Layout/EndAlignment:
|
|
25
|
+
Exclude:
|
|
26
|
+
- 'lib/prosereflect/schema/schema_main.rb'
|
|
27
|
+
|
|
28
|
+
# Offense count: 1
|
|
29
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
30
|
+
# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
|
|
31
|
+
# SupportedStylesAlignWith: start_of_line, relative_to_receiver
|
|
32
|
+
Layout/IndentationWidth:
|
|
33
|
+
Exclude:
|
|
34
|
+
- 'lib/prosereflect/schema/schema_main.rb'
|
|
35
|
+
|
|
36
|
+
# Offense count: 264
|
|
25
37
|
# This cop supports safe autocorrection (--autocorrect).
|
|
26
38
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
27
39
|
# URISchemes: http, https
|
|
@@ -29,20 +41,14 @@ Layout/LineLength:
|
|
|
29
41
|
Enabled: false
|
|
30
42
|
|
|
31
43
|
# Offense count: 5
|
|
32
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
33
|
-
# Configuration parameters: AllowInHeredoc.
|
|
34
|
-
Layout/TrailingWhitespace:
|
|
35
|
-
Exclude:
|
|
36
|
-
- 'spec/prosereflect/schema/conftest.rb'
|
|
37
|
-
|
|
38
|
-
# Offense count: 4
|
|
39
44
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
40
45
|
Lint/DuplicateBranch:
|
|
41
46
|
Exclude:
|
|
42
47
|
- 'lib/prosereflect/input/html.rb'
|
|
43
48
|
- 'lib/prosereflect/schema/attribute.rb'
|
|
49
|
+
- 'lib/prosereflect/schema/content_match.rb'
|
|
44
50
|
- 'lib/prosereflect/schema/mark.rb'
|
|
45
|
-
- '
|
|
51
|
+
- 'spec/fixtures/test_builder/helpers.rb'
|
|
46
52
|
|
|
47
53
|
# Offense count: 1
|
|
48
54
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -52,84 +58,60 @@ Lint/UnusedMethodArgument:
|
|
|
52
58
|
Exclude:
|
|
53
59
|
- 'lib/prosereflect/schema/node.rb'
|
|
54
60
|
|
|
55
|
-
# Offense count:
|
|
61
|
+
# Offense count: 57
|
|
56
62
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
57
63
|
Metrics/AbcSize:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- 'lib/prosereflect/schema/node.rb'
|
|
66
|
-
- 'lib/prosereflect/schema/node_type.rb'
|
|
67
|
-
- 'lib/prosereflect/schema/schema_class.rb'
|
|
68
|
-
- 'spec/support/matchers.rb'
|
|
64
|
+
Enabled: false
|
|
65
|
+
|
|
66
|
+
# Offense count: 1
|
|
67
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
68
|
+
# AllowedMethods: refine
|
|
69
|
+
Metrics/BlockLength:
|
|
70
|
+
Max: 27
|
|
69
71
|
|
|
70
72
|
# Offense count: 1
|
|
71
73
|
# Configuration parameters: CountBlocks, CountModifierForms.
|
|
72
74
|
Metrics/BlockNesting:
|
|
73
75
|
Max: 4
|
|
74
76
|
|
|
75
|
-
# Offense count:
|
|
77
|
+
# Offense count: 57
|
|
76
78
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
77
79
|
Metrics/CyclomaticComplexity:
|
|
78
|
-
|
|
79
|
-
- 'lib/prosereflect/code_block.rb'
|
|
80
|
-
- 'lib/prosereflect/input/html.rb'
|
|
81
|
-
- 'lib/prosereflect/node.rb'
|
|
82
|
-
- 'lib/prosereflect/output/html.rb'
|
|
83
|
-
- 'lib/prosereflect/parser.rb'
|
|
84
|
-
- 'lib/prosereflect/schema/attribute.rb'
|
|
85
|
-
- 'lib/prosereflect/schema/fragment.rb'
|
|
86
|
-
- 'lib/prosereflect/schema/mark_type.rb'
|
|
87
|
-
- 'lib/prosereflect/schema/node.rb'
|
|
88
|
-
- 'lib/prosereflect/schema/node_type.rb'
|
|
89
|
-
- 'lib/prosereflect/schema/schema_class.rb'
|
|
90
|
-
- 'spec/support/matchers.rb'
|
|
80
|
+
Enabled: false
|
|
91
81
|
|
|
92
|
-
# Offense count:
|
|
82
|
+
# Offense count: 82
|
|
93
83
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
94
84
|
Metrics/MethodLength:
|
|
95
|
-
Max:
|
|
85
|
+
Max: 93
|
|
96
86
|
|
|
97
|
-
# Offense count:
|
|
87
|
+
# Offense count: 9
|
|
98
88
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
99
89
|
Metrics/ParameterLists:
|
|
100
90
|
Max: 8
|
|
101
91
|
|
|
102
|
-
# Offense count:
|
|
92
|
+
# Offense count: 52
|
|
103
93
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
104
94
|
Metrics/PerceivedComplexity:
|
|
105
|
-
|
|
106
|
-
- 'lib/prosereflect/code_block.rb'
|
|
107
|
-
- 'lib/prosereflect/input/html.rb'
|
|
108
|
-
- 'lib/prosereflect/node.rb'
|
|
109
|
-
- 'lib/prosereflect/output/html.rb'
|
|
110
|
-
- 'lib/prosereflect/parser.rb'
|
|
111
|
-
- 'lib/prosereflect/schema/fragment.rb'
|
|
112
|
-
- 'lib/prosereflect/schema/mark_type.rb'
|
|
113
|
-
- 'lib/prosereflect/schema/node.rb'
|
|
114
|
-
- 'lib/prosereflect/schema/node_type.rb'
|
|
115
|
-
- 'lib/prosereflect/schema/schema_class.rb'
|
|
116
|
-
- 'spec/support/matchers.rb'
|
|
95
|
+
Enabled: false
|
|
117
96
|
|
|
118
|
-
# Offense count:
|
|
97
|
+
# Offense count: 7
|
|
119
98
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
|
120
99
|
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
|
121
100
|
Naming/MethodParameterName:
|
|
122
101
|
Exclude:
|
|
102
|
+
- 'lib/prosereflect/schema/content_match.rb'
|
|
123
103
|
- 'lib/prosereflect/schema/fragment.rb'
|
|
104
|
+
- 'lib/prosereflect/schema/mark.rb'
|
|
124
105
|
- 'lib/prosereflect/schema/node.rb'
|
|
125
106
|
|
|
126
|
-
# Offense count:
|
|
107
|
+
# Offense count: 8
|
|
127
108
|
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
|
128
109
|
# AllowedMethods: call
|
|
129
110
|
# WaywardPredicates: infinite?, nonzero?
|
|
130
111
|
Naming/PredicateMethod:
|
|
131
112
|
Exclude:
|
|
132
113
|
- 'lib/prosereflect/schema/attribute.rb'
|
|
114
|
+
- 'lib/prosereflect/schema/content_match.rb'
|
|
133
115
|
- 'lib/prosereflect/schema/node.rb'
|
|
134
116
|
|
|
135
117
|
# Offense count: 12
|
|
@@ -160,12 +142,12 @@ RSpec/ContextWording:
|
|
|
160
142
|
- 'spec/prosereflect/schema/conftest.rb'
|
|
161
143
|
- 'spec/support/shared_examples.rb'
|
|
162
144
|
|
|
163
|
-
# Offense count:
|
|
145
|
+
# Offense count: 254
|
|
164
146
|
# Configuration parameters: CountAsOne.
|
|
165
147
|
RSpec/ExampleLength:
|
|
166
148
|
Max: 134
|
|
167
149
|
|
|
168
|
-
# Offense count:
|
|
150
|
+
# Offense count: 158
|
|
169
151
|
RSpec/MultipleExpectations:
|
|
170
152
|
Max: 8
|
|
171
153
|
|
|
@@ -174,24 +156,28 @@ RSpec/MultipleExpectations:
|
|
|
174
156
|
RSpec/NestedGroups:
|
|
175
157
|
Max: 4
|
|
176
158
|
|
|
159
|
+
# Offense count: 1
|
|
160
|
+
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
161
|
+
# SupportedInflectors: default, active_support
|
|
162
|
+
RSpec/SpecFilePathFormat:
|
|
163
|
+
Exclude:
|
|
164
|
+
- 'spec/prosereflect/schema/schema_spec.rb'
|
|
165
|
+
|
|
177
166
|
# Offense count: 2
|
|
178
167
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
179
168
|
Style/IdenticalConditionalBranches:
|
|
180
169
|
Exclude:
|
|
181
170
|
- 'lib/prosereflect/schema/mark.rb'
|
|
182
171
|
|
|
183
|
-
# Offense count:
|
|
184
|
-
#
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
Style/TrailingCommaInArguments:
|
|
172
|
+
# Offense count: 1
|
|
173
|
+
# Configuration parameters: EnforcedStyle.
|
|
174
|
+
# SupportedStyles: allow_single_line, disallow
|
|
175
|
+
Style/NumberedParameters:
|
|
188
176
|
Exclude:
|
|
189
|
-
- '
|
|
177
|
+
- 'lib/prosereflect/schema/content_match.rb'
|
|
190
178
|
|
|
191
|
-
# Offense count:
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
195
|
-
Style/TrailingCommaInHashLiteral:
|
|
179
|
+
# Offense count: 1
|
|
180
|
+
# Configuration parameters: AllowedClasses.
|
|
181
|
+
Style/OneClassPerFile:
|
|
196
182
|
Exclude:
|
|
197
|
-
- '
|
|
183
|
+
- 'lib/prosereflect/schema.rb'
|
data/README.adoc
CHANGED
|
@@ -14,6 +14,8 @@ accessing the hierarchical document tree structure represented in ProseMirror's
|
|
|
14
14
|
JSON/YAML format. This allows for convenient traversal and extraction of content
|
|
15
15
|
from rich text documents.
|
|
16
16
|
|
|
17
|
+
https://metanorma.org/prosereflect/[Full documentation] is available on the docs site.
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
== Installation
|
|
19
21
|
|
data/docs/Gemfile
ADDED
data/docs/INDEX.adoc
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Home
|
|
4
|
+
nav_order: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
= Prosereflect Documentation
|
|
8
|
+
|
|
9
|
+
`prosereflect` is a Ruby gem for working with the document structure used by the https://prosemirror.net/[ProseMirror rich text editor].
|
|
10
|
+
|
|
11
|
+
It provides a set of models and utilities for parsing, manipulating, and accessing the hierarchical document tree structure represented in ProseMirror's JSON/YAML format.
|
|
12
|
+
|
|
13
|
+
== Quick Start
|
|
14
|
+
|
|
15
|
+
Install the gem:
|
|
16
|
+
|
|
17
|
+
[source,sh]
|
|
18
|
+
----
|
|
19
|
+
gem install prosereflect
|
|
20
|
+
----
|
|
21
|
+
|
|
22
|
+
Parse a document:
|
|
23
|
+
|
|
24
|
+
[source,ruby]
|
|
25
|
+
----
|
|
26
|
+
require 'prosereflect'
|
|
27
|
+
|
|
28
|
+
doc = Prosereflect::Parser.parse_document({
|
|
29
|
+
"type" => "doc",
|
|
30
|
+
"content" => [
|
|
31
|
+
{ "type" => "paragraph", "content" => [{ "type" => "text", "text" => "Hello world" }] }
|
|
32
|
+
]
|
|
33
|
+
})
|
|
34
|
+
----
|
|
35
|
+
|
|
36
|
+
== Documentation Sections
|
|
37
|
+
|
|
38
|
+
* x:features:node-types[Node Types] -- All available node types and their attributes
|
|
39
|
+
* x:features:marks[Marks] -- Text formatting marks (bold, italic, links, etc.)
|
|
40
|
+
* x:understanding:document-model[Document Model] -- Node hierarchy and content model
|
|
41
|
+
* x:understanding:fragment[Fragment] -- Flat content collections
|
|
42
|
+
* x:understanding:resolved-position[Resolved Positions] -- Position resolution in the document tree
|
|
43
|
+
* x:advanced:transform[Transforms] -- Document transformations and step-based editing
|
|
44
|
+
* x:advanced:schema[Schema] -- Schema definition and validation
|
|
45
|
+
* x:guides:round-trip-html[HTML Round-Trip] -- Convert between HTML and ProseMirror documents
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Advanced
|
|
4
|
+
nav_order: 5
|
|
5
|
+
has_children: true
|
|
6
|
+
---
|
|
7
|
+
= Advanced
|
|
8
|
+
|
|
9
|
+
This section covers advanced topics for power users.
|
|
10
|
+
|
|
11
|
+
* x:transform[Transforms] -- Step-based document transformations
|
|
12
|
+
* x:steps[Step Types] -- Individual step types and their behavior
|
|
13
|
+
* x:step-map[Step Maps and Mappings] -- Position tracking through transforms
|
|
14
|
+
* x:schema[Schema] -- Schema definition and content validation
|
|
15
|
+
* x:test-builder[Test Builder] -- DSL for building test documents
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Schema
|
|
4
|
+
parent: Advanced
|
|
5
|
+
nav_order: 4
|
|
6
|
+
---
|
|
7
|
+
= Schema
|
|
8
|
+
|
|
9
|
+
`Prosereflect::Schema` defines the structure of valid documents: which node types exist, what content they can contain, and which marks are allowed.
|
|
10
|
+
|
|
11
|
+
== Creating a Schema
|
|
12
|
+
|
|
13
|
+
[source,ruby]
|
|
14
|
+
----
|
|
15
|
+
schema = Prosereflect::Schema.new(
|
|
16
|
+
nodes_spec: {
|
|
17
|
+
"doc" => { content: "block+" },
|
|
18
|
+
"paragraph" => { content: "inline*", group: "block" },
|
|
19
|
+
"heading" => { content: "inline*", group: "block", attrs: { "level" => { "default" => 1 } } },
|
|
20
|
+
"text" => { group: "inline" }
|
|
21
|
+
},
|
|
22
|
+
marks_spec: {
|
|
23
|
+
"bold" => {},
|
|
24
|
+
"italic" => {},
|
|
25
|
+
"link" => { attrs: { "href" => {} } }
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
----
|
|
29
|
+
|
|
30
|
+
== Requirements
|
|
31
|
+
|
|
32
|
+
Every schema must define:
|
|
33
|
+
|
|
34
|
+
* A `"doc"` node type (the top-level container)
|
|
35
|
+
* A `"text"` node type (inline text)
|
|
36
|
+
* At least one block node type in the doc's content expression
|
|
37
|
+
|
|
38
|
+
== Content Expressions
|
|
39
|
+
|
|
40
|
+
Content expressions define what children a node can have. Supported syntax:
|
|
41
|
+
|
|
42
|
+
* `"block+"` -- one or more block nodes
|
|
43
|
+
* `"inline*"` -- zero or more inline nodes
|
|
44
|
+
* `"paragraph heading"` -- a paragraph followed by a heading
|
|
45
|
+
* `"(paragraph | heading)"` -- either paragraph or heading
|
|
46
|
+
* `"block{2,4}"` -- between 2 and 4 block nodes
|
|
47
|
+
* `"block?"` -- optional block node
|
|
48
|
+
|
|
49
|
+
== NodeType
|
|
50
|
+
|
|
51
|
+
Access and use node types from a schema:
|
|
52
|
+
|
|
53
|
+
[source,ruby]
|
|
54
|
+
----
|
|
55
|
+
para_type = schema.node_type("paragraph")
|
|
56
|
+
para_type.name # => "paragraph"
|
|
57
|
+
para_type.is_block? # => true
|
|
58
|
+
para_type.is_inline? # => false
|
|
59
|
+
para_type.is_textblock? # => true
|
|
60
|
+
para_type.is_leaf? # => false
|
|
61
|
+
para_type.is_atom? # => false
|
|
62
|
+
----
|
|
63
|
+
|
|
64
|
+
Creating validated nodes:
|
|
65
|
+
|
|
66
|
+
[source,ruby]
|
|
67
|
+
----
|
|
68
|
+
# Create with validation
|
|
69
|
+
node = para_type.create_checked(nil, [text_node])
|
|
70
|
+
|
|
71
|
+
# Create with defaults
|
|
72
|
+
node = para_type.create_and_fill
|
|
73
|
+
|
|
74
|
+
# Check content validity
|
|
75
|
+
para_type.valid_content?(fragment)
|
|
76
|
+
----
|
|
77
|
+
|
|
78
|
+
== MarkType
|
|
79
|
+
|
|
80
|
+
Access and use mark types:
|
|
81
|
+
|
|
82
|
+
[source,ruby]
|
|
83
|
+
----
|
|
84
|
+
bold_type = schema.mark_type("bold")
|
|
85
|
+
mark = bold_type.create # Schema::Mark instance
|
|
86
|
+
mark.attrs # => {}
|
|
87
|
+
|
|
88
|
+
link_type = schema.mark_type("link")
|
|
89
|
+
link = link_type.create("href" => "https://example.com")
|
|
90
|
+
link.attrs # => {"href" => "https://example.com"}
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
== ContentMatch
|
|
94
|
+
|
|
95
|
+
`ContentMatch` is the engine that validates content expressions. It uses an NFA/DFA approach to parse and match content expressions:
|
|
96
|
+
|
|
97
|
+
* `match_type(node_type)` -- try to match a node type, returns next match state or nil
|
|
98
|
+
* `match_fragment(fragment)` -- match a full fragment
|
|
99
|
+
* `valid_end` -- whether this state is a valid end state
|
|
100
|
+
* `fill_before(after:, to_end:)` -- compute filler content
|
|
101
|
+
* `find_wrapping(target_type)` -- find wrapping nodes for content
|
|
102
|
+
* `inline_content?` -- whether this match accepts inline content
|
|
103
|
+
* `default_type` -- the default node type for this match
|
|
104
|
+
|
|
105
|
+
== Validation Errors
|
|
106
|
+
|
|
107
|
+
The schema raises `Prosereflect::SchemaErrors::ValidationError` for:
|
|
108
|
+
|
|
109
|
+
* Missing required node types (doc, text)
|
|
110
|
+
* Name collisions between nodes and marks
|
|
111
|
+
* Invalid content in created nodes
|
|
112
|
+
* Missing required attributes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Step Maps and Mappings
|
|
4
|
+
parent: Advanced
|
|
5
|
+
nav_order: 3
|
|
6
|
+
---
|
|
7
|
+
= Step Maps and Mappings
|
|
8
|
+
|
|
9
|
+
When steps are applied to a document, positions in the original document may no longer correspond to the same locations. Step maps and mappings track these changes.
|
|
10
|
+
|
|
11
|
+
== StepMap
|
|
12
|
+
|
|
13
|
+
`Prosereflect::Transform::StepMap` maps positions through a single step. It stores an array of ranges `[old_start, old_end, new_start, new_end]`.
|
|
14
|
+
|
|
15
|
+
[source,ruby]
|
|
16
|
+
----
|
|
17
|
+
# Create a step map
|
|
18
|
+
map = Prosereflect::Transform::StepMap.new([[0, 5, 0, 8]])
|
|
19
|
+
|
|
20
|
+
# Map a position
|
|
21
|
+
map.map(3) # => new position after the step
|
|
22
|
+
|
|
23
|
+
# Check if a position was deleted
|
|
24
|
+
map.deleted?(3) # => true/false
|
|
25
|
+
|
|
26
|
+
# Map with deletion info
|
|
27
|
+
result = map.map_result(3)
|
|
28
|
+
result.pos # => new position
|
|
29
|
+
result.deleted # => whether the position was deleted
|
|
30
|
+
result.transformed # => whether the position changed
|
|
31
|
+
----
|
|
32
|
+
|
|
33
|
+
=== Factory Methods
|
|
34
|
+
|
|
35
|
+
* `StepMap.empty` -- identity map (no changes)
|
|
36
|
+
* `StepMap.delete(from, to)` -- map for a deletion
|
|
37
|
+
* `StepMap.replace(from, to, target_from, target_to)` -- map for a replacement
|
|
38
|
+
|
|
39
|
+
== Mapping
|
|
40
|
+
|
|
41
|
+
`Prosereflect::Transform::Mapping` composes multiple step maps to track positions through a full transform chain.
|
|
42
|
+
|
|
43
|
+
[source,ruby]
|
|
44
|
+
----
|
|
45
|
+
mapping = Prosereflect::Transform::Mapping.new
|
|
46
|
+
mapping.add_map(step_map_1)
|
|
47
|
+
mapping.add_map(step_map_2)
|
|
48
|
+
|
|
49
|
+
# Map a position through all steps
|
|
50
|
+
mapping.map(5) # => final position
|
|
51
|
+
|
|
52
|
+
# Map with deletion tracking
|
|
53
|
+
result = mapping.map_result(5)
|
|
54
|
+
result[:pos] # => final position
|
|
55
|
+
result[:deleted] # => whether deleted by any step
|
|
56
|
+
|
|
57
|
+
# Map backwards
|
|
58
|
+
mapping.map_reverse(8) # => original position
|
|
59
|
+
----
|
|
60
|
+
|
|
61
|
+
=== Checking Deletions
|
|
62
|
+
|
|
63
|
+
[source,ruby]
|
|
64
|
+
----
|
|
65
|
+
mapping.map_deletes(5) # => whether position 5 was deleted by any step
|
|
66
|
+
----
|