pyDiffTools 0.1.49__tar.gz → 0.1.51__tar.gz

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.
Files changed (124) hide show
  1. {pydifftools-0.1.49 → pydifftools-0.1.51}/MANIFEST.in +1 -0
  2. {pydifftools-0.1.49/pyDiffTools.egg-info → pydifftools-0.1.51}/PKG-INFO +50 -8
  3. {pydifftools-0.1.49 → pydifftools-0.1.51}/README.rst +49 -7
  4. {pydifftools-0.1.49 → pydifftools-0.1.51/pyDiffTools.egg-info}/PKG-INFO +50 -8
  5. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyDiffTools.egg-info/SOURCES.txt +5 -0
  6. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/browser_lifecycle.py +30 -1
  7. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/command_line.py +35 -2
  8. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/command_registry.py +7 -0
  9. pydifftools-0.1.51/pydifftools/comment_filter_history.json +145 -0
  10. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_tags.lua +10 -3
  11. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_tags_margin.lua +10 -3
  12. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_tags_no_comments.lua +10 -3
  13. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/continuous.py +470 -155
  14. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/comparison.py +13 -1
  15. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/graph.py +7 -4
  16. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/watch_graph.py +256 -153
  17. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/wgrph_view.js +186 -10
  18. pydifftools-0.1.51/pydifftools/line_alignment.py +391 -0
  19. pydifftools-0.1.51/pydifftools/match_spaces.py +142 -0
  20. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/wrap_sentences.py +80 -340
  21. pydifftools-0.1.51/pydifftools/wrapping_options.py +18 -0
  22. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyproject.toml +2 -1
  23. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_browser_lifecycle.py +56 -0
  24. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_command_line_help.py +126 -0
  25. pydifftools-0.1.51/tests/test_comment_filters.py +441 -0
  26. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_continuous_shutdown.py +47 -17
  27. pydifftools-0.1.51/tests/test_line_alignment.py +131 -0
  28. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_wrap_check.py +305 -23
  29. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_wrapping.py +18 -2
  30. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_zotero.py +1 -1
  31. pydifftools-0.1.49/pydifftools/match_spaces.py +0 -380
  32. {pydifftools-0.1.49 → pydifftools-0.1.51}/LICENSE.md +0 -0
  33. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/_quarto.yml +0 -0
  34. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
  35. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
  36. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
  37. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
  38. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
  39. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
  40. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
  41. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
  42. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
  43. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
  44. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
  45. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
  46. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
  47. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
  48. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
  49. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
  50. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
  51. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
  52. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
  53. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
  54. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
  55. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/.jupyter_cache/global.db +0 -0
  56. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/example.qmd +0 -0
  57. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/example.tex +0 -0
  58. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/index.qmd +0 -0
  59. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
  60. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
  61. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
  62. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
  63. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/independent.qmd +0 -0
  64. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/index.qmd +0 -0
  65. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/tasks.qmd +0 -0
  66. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/test_include.qmd +0 -0
  67. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
  68. {pydifftools-0.1.49 → pydifftools-0.1.51}/example_notebook/project1/test_include.qmd +0 -0
  69. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyDiffTools.egg-info/dependency_links.txt +0 -0
  70. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyDiffTools.egg-info/entry_points.txt +0 -0
  71. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyDiffTools.egg-info/requires.txt +0 -0
  72. {pydifftools-0.1.49 → pydifftools-0.1.51}/pyDiffTools.egg-info/top_level.txt +0 -0
  73. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/__init__.py +0 -0
  74. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/bibliography.py +0 -0
  75. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/check_numbers.py +0 -0
  76. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/citation_dialog.py +0 -0
  77. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_functions.py +0 -0
  78. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_migration.py +0 -0
  79. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comment_toggle.js +0 -0
  80. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comments.css +0 -0
  81. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/comments_author_colors.css +0 -0
  82. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/copy_files.py +0 -0
  83. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/diff-doc.js +0 -0
  84. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/doc_contents.py +0 -0
  85. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/__init__.py +0 -0
  86. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/dot_to_yaml.py +0 -0
  87. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/source_jump.js +0 -0
  88. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
  89. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/forward_search.py +0 -0
  90. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/git_gd.py +0 -0
  91. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/git_gd_history.py +0 -0
  92. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/git_gd_image.py +0 -0
  93. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/git_gd_qt.py +0 -0
  94. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/html_comments.py +0 -0
  95. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/html_uncomments.py +0 -0
  96. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/log_example.py +0 -0
  97. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/notebook/__init__.py +0 -0
  98. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/notebook/display.py +0 -0
  99. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/notebook/fast_build.py +0 -0
  100. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/notebook/tex_to_qmd.py +0 -0
  101. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/onewordify.py +0 -0
  102. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/onewordify_undo.py +0 -0
  103. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/outline.py +0 -0
  104. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/rearrange_tex.py +0 -0
  105. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/searchacro.py +0 -0
  106. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/separate_comments.py +0 -0
  107. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/source_jump.py +0 -0
  108. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/split_conflict.py +0 -0
  109. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/unseparate_comments.py +0 -0
  110. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/update_check.py +0 -0
  111. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/xml2xlsx.vbs +0 -0
  112. {pydifftools-0.1.49 → pydifftools-0.1.51}/pydifftools/zotero.py +0 -0
  113. {pydifftools-0.1.49 → pydifftools-0.1.51}/setup.cfg +0 -0
  114. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_bibliography.py +0 -0
  115. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_check_single_use.py +0 -0
  116. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_comment_migration.py +0 -0
  117. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_forward_search.py +0 -0
  118. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_git_gd_history.py +0 -0
  119. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_git_gd_image.py +0 -0
  120. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_git_gd_qt.py +0 -0
  121. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_rrng.py +0 -0
  122. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_source_jump.py +0 -0
  123. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_tex_to_qmd.py +0 -0
  124. {pydifftools-0.1.49 → pydifftools-0.1.51}/tests/test_update_check.py +0 -0
@@ -8,6 +8,7 @@ include pydifftools/comments_author_colors.css
8
8
  include pydifftools/comment_tags.lua
9
9
  include pydifftools/comment_tags_margin.lua
10
10
  include pydifftools/comment_tags_no_comments.lua
11
+ include pydifftools/comment_filter_history.json
11
12
  include pydifftools/comment_toggle.js
12
13
  include pydifftools/flowchart/svg-pan-zoom.min.js
13
14
  include pydifftools/flowchart/wgrph_view.js
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyDiffTools
3
- Version: 0.1.49
3
+ Version: 0.1.51
4
4
  Summary: Diff tools
5
5
  Author: J M Franck
6
6
  License: Copyright (c) 2015, jmfranck
@@ -118,6 +118,27 @@ included are (listed in order of fun/utility):
118
118
  matching color. New authors choose a hue in a Qt picker; ``cpb`` adds their
119
119
  ``XXcolor`` field to the header.
120
120
 
121
+ ``cpb`` manages ``comment_tags.lua``, the comment stylesheets and
122
+ ``comment_toggle.js`` beside the Markdown source. A packaged SHA-256
123
+ catalog covers current and historical helpers from Git, including the
124
+ normal, margin and no-comment Lua variants. Known older files trigger an
125
+ update offer; unrecognized files are treated as possible local edits.
126
+ Updating removes generated helpers from Git tracking without deleting
127
+ the working copies, and adds them to ``.gitignore``. Keeping local edits
128
+ or Git tracking requires a second confirmation. An ignored
129
+ ``.pydifft-comment-filter.json`` records the approved file hashes; changing
130
+ any helper causes another prompt. Keeping known older versions applies
131
+ only to the current ``cpb`` session.
132
+
133
+ ``--no-comments`` selects the no-comment Lua variant. Running without
134
+ that flag when the on-disk Lua matches a current or historical no-comment
135
+ version asks whether to show comments. The selection uses the files'
136
+ contents, without active/inactive swapping or remembered mode settings.
137
+ Existing ``.inactive`` copies are migrated, preserving unique local
138
+ edits in ignored recovery files. Maintainers refresh the catalog with
139
+ ``python .github/scripts/update_comment_filter_history.py``; the release
140
+ workflow also refreshes it before building distributions.
141
+
121
142
  Declare a single local ``.bib`` file with ``bibliography: references.bib``
122
143
  in the Markdown YAML header; relative paths are resolved beside the
123
144
  Markdown file. Without that declaration, ``cpb`` uses a single adjacent
@@ -152,11 +173,21 @@ included are (listed in order of fun/utility):
152
173
  ``flowchart/watch_graph.py`` script so all of its functionality is now
153
174
  available through the main ``pydifft`` entry point.
154
175
  Add ``--diff-base HEAD`` (or a branch, tag, commit, or quoted reflog
155
- reference) to compare against that Git snapshot throughout the preview
156
- session. Additions are green, deletions are red and struck through, and
176
+ reference) to open a URL comparing against that Git snapshot.
177
+ Additions are green, deletions are red and struck through, and
157
178
  unchanged content is muted. Renames share one box; date, status, and
158
179
  dependency changes are annotated. Navigation, filters, and reloads retain
159
- the baseline, whose reference and commit appear below the graph.
180
+ the baseline through the ``diff-base`` URL parameter, whose reference and
181
+ commit appear below the graph. All view choices come from the URL:
182
+ ``t`` focuses a task and its ancestors, ``d=1``
183
+ orders dated tasks, and ``p=1`` excludes completed tasks. Command options
184
+ choose the initial URL. Removing ``diff-base`` restores normal rendering;
185
+ clearing the entire query shows the full plan, including completed and
186
+ undated tasks. Each embedded SVG and live refresh uses the same URL mode.
187
+ The search button beside Home and Zoom finds text in the visible graph,
188
+ highlights matches, and centers them at a readable font size. Tab or Enter
189
+ advances to the next match; Shift+Tab or Shift+Enter goes back. Esc closes
190
+ search. Phrases can span wrapped lines and formatted text.
160
191
  Comparison uses the same repository-relative YAML path; a file absent
161
192
  from the revision is treated as an empty plan. Historical file renames
162
193
  are not followed, and comparison markup is never written to YAML.
@@ -215,10 +246,21 @@ included are (listed in order of fun/utility):
215
246
 
216
247
  * this allows you to use an original file with good whitespace formatting as a "template" that you can match other (e.g. pandoc converted file) onto another
217
248
 
218
- * changed prose lines exceeding 1.5 times the nearby reference width are
219
- wrapped using the same sentence and punctuation rules as ``wr``.
220
- Existing surrounding line breaks are retained; the fallback width is
221
- 80 columns when the reference provides too little prose.
249
+ * ``cpb`` and ``wmatch`` share a matcher that finds changed hunks, aligns
250
+ their words using Git's minimal diff, and restores reference whitespace.
251
+ It then considers extra breaks that preserve an unchanged reference line
252
+ without stranding a tiny edited fragment, and checks wrapping rules.
253
+
254
+ * ``--wrapnumber`` sets the maximum width (79 for ``cpb`` and ``wmatch``).
255
+ Wmatch also uses nearby reference widths for large edits, retaining
256
+ unchanged reference lines and protected Markdown blocks.
257
+
258
+ * ``--trailing-dependent-phrase`` defaults to 20: a clause boundary within
259
+ 20 characters of the maximum width must end the line, even when its
260
+ trailing phrase would still fit. Commas, semicolons, colons, parentheses,
261
+ dashes, and inline-math boundaries are supported. Set it to 0 to disable
262
+ this rule. The option is shared by ``cpb``, ``wmatch``, ``wr`` and
263
+ ``wrchk``; ``--punctuation-slop`` remains an alias.
222
264
 
223
265
  - `pydifft wd` ("word diff"): generate "track changes" word files starting from pandoc markdown in a git history. Assuming that you have copied diff-doc.js (copied + licensed from elsewhere) into your home directory, this will use pandoc to convert the markdown files to MS Word, then use the MS Word comparison tool to generate a document where all relevant changes are shown with "track changes."
224
266
 
@@ -63,6 +63,27 @@ included are (listed in order of fun/utility):
63
63
  matching color. New authors choose a hue in a Qt picker; ``cpb`` adds their
64
64
  ``XXcolor`` field to the header.
65
65
 
66
+ ``cpb`` manages ``comment_tags.lua``, the comment stylesheets and
67
+ ``comment_toggle.js`` beside the Markdown source. A packaged SHA-256
68
+ catalog covers current and historical helpers from Git, including the
69
+ normal, margin and no-comment Lua variants. Known older files trigger an
70
+ update offer; unrecognized files are treated as possible local edits.
71
+ Updating removes generated helpers from Git tracking without deleting
72
+ the working copies, and adds them to ``.gitignore``. Keeping local edits
73
+ or Git tracking requires a second confirmation. An ignored
74
+ ``.pydifft-comment-filter.json`` records the approved file hashes; changing
75
+ any helper causes another prompt. Keeping known older versions applies
76
+ only to the current ``cpb`` session.
77
+
78
+ ``--no-comments`` selects the no-comment Lua variant. Running without
79
+ that flag when the on-disk Lua matches a current or historical no-comment
80
+ version asks whether to show comments. The selection uses the files'
81
+ contents, without active/inactive swapping or remembered mode settings.
82
+ Existing ``.inactive`` copies are migrated, preserving unique local
83
+ edits in ignored recovery files. Maintainers refresh the catalog with
84
+ ``python .github/scripts/update_comment_filter_history.py``; the release
85
+ workflow also refreshes it before building distributions.
86
+
66
87
  Declare a single local ``.bib`` file with ``bibliography: references.bib``
67
88
  in the Markdown YAML header; relative paths are resolved beside the
68
89
  Markdown file. Without that declaration, ``cpb`` uses a single adjacent
@@ -97,11 +118,21 @@ included are (listed in order of fun/utility):
97
118
  ``flowchart/watch_graph.py`` script so all of its functionality is now
98
119
  available through the main ``pydifft`` entry point.
99
120
  Add ``--diff-base HEAD`` (or a branch, tag, commit, or quoted reflog
100
- reference) to compare against that Git snapshot throughout the preview
101
- session. Additions are green, deletions are red and struck through, and
121
+ reference) to open a URL comparing against that Git snapshot.
122
+ Additions are green, deletions are red and struck through, and
102
123
  unchanged content is muted. Renames share one box; date, status, and
103
124
  dependency changes are annotated. Navigation, filters, and reloads retain
104
- the baseline, whose reference and commit appear below the graph.
125
+ the baseline through the ``diff-base`` URL parameter, whose reference and
126
+ commit appear below the graph. All view choices come from the URL:
127
+ ``t`` focuses a task and its ancestors, ``d=1``
128
+ orders dated tasks, and ``p=1`` excludes completed tasks. Command options
129
+ choose the initial URL. Removing ``diff-base`` restores normal rendering;
130
+ clearing the entire query shows the full plan, including completed and
131
+ undated tasks. Each embedded SVG and live refresh uses the same URL mode.
132
+ The search button beside Home and Zoom finds text in the visible graph,
133
+ highlights matches, and centers them at a readable font size. Tab or Enter
134
+ advances to the next match; Shift+Tab or Shift+Enter goes back. Esc closes
135
+ search. Phrases can span wrapped lines and formatted text.
105
136
  Comparison uses the same repository-relative YAML path; a file absent
106
137
  from the revision is treated as an empty plan. Historical file renames
107
138
  are not followed, and comparison markup is never written to YAML.
@@ -160,10 +191,21 @@ included are (listed in order of fun/utility):
160
191
 
161
192
  * this allows you to use an original file with good whitespace formatting as a "template" that you can match other (e.g. pandoc converted file) onto another
162
193
 
163
- * changed prose lines exceeding 1.5 times the nearby reference width are
164
- wrapped using the same sentence and punctuation rules as ``wr``.
165
- Existing surrounding line breaks are retained; the fallback width is
166
- 80 columns when the reference provides too little prose.
194
+ * ``cpb`` and ``wmatch`` share a matcher that finds changed hunks, aligns
195
+ their words using Git's minimal diff, and restores reference whitespace.
196
+ It then considers extra breaks that preserve an unchanged reference line
197
+ without stranding a tiny edited fragment, and checks wrapping rules.
198
+
199
+ * ``--wrapnumber`` sets the maximum width (79 for ``cpb`` and ``wmatch``).
200
+ Wmatch also uses nearby reference widths for large edits, retaining
201
+ unchanged reference lines and protected Markdown blocks.
202
+
203
+ * ``--trailing-dependent-phrase`` defaults to 20: a clause boundary within
204
+ 20 characters of the maximum width must end the line, even when its
205
+ trailing phrase would still fit. Commas, semicolons, colons, parentheses,
206
+ dashes, and inline-math boundaries are supported. Set it to 0 to disable
207
+ this rule. The option is shared by ``cpb``, ``wmatch``, ``wr`` and
208
+ ``wrchk``; ``--punctuation-slop`` remains an alias.
167
209
 
168
210
  - `pydifft wd` ("word diff"): generate "track changes" word files starting from pandoc markdown in a git history. Assuming that you have copied diff-doc.js (copied + licensed from elsewhere) into your home directory, this will use pandoc to convert the markdown files to MS Word, then use the MS Word comparison tool to generate a document where all relevant changes are shown with "track changes."
169
211
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyDiffTools
3
- Version: 0.1.49
3
+ Version: 0.1.51
4
4
  Summary: Diff tools
5
5
  Author: J M Franck
6
6
  License: Copyright (c) 2015, jmfranck
@@ -118,6 +118,27 @@ included are (listed in order of fun/utility):
118
118
  matching color. New authors choose a hue in a Qt picker; ``cpb`` adds their
119
119
  ``XXcolor`` field to the header.
120
120
 
121
+ ``cpb`` manages ``comment_tags.lua``, the comment stylesheets and
122
+ ``comment_toggle.js`` beside the Markdown source. A packaged SHA-256
123
+ catalog covers current and historical helpers from Git, including the
124
+ normal, margin and no-comment Lua variants. Known older files trigger an
125
+ update offer; unrecognized files are treated as possible local edits.
126
+ Updating removes generated helpers from Git tracking without deleting
127
+ the working copies, and adds them to ``.gitignore``. Keeping local edits
128
+ or Git tracking requires a second confirmation. An ignored
129
+ ``.pydifft-comment-filter.json`` records the approved file hashes; changing
130
+ any helper causes another prompt. Keeping known older versions applies
131
+ only to the current ``cpb`` session.
132
+
133
+ ``--no-comments`` selects the no-comment Lua variant. Running without
134
+ that flag when the on-disk Lua matches a current or historical no-comment
135
+ version asks whether to show comments. The selection uses the files'
136
+ contents, without active/inactive swapping or remembered mode settings.
137
+ Existing ``.inactive`` copies are migrated, preserving unique local
138
+ edits in ignored recovery files. Maintainers refresh the catalog with
139
+ ``python .github/scripts/update_comment_filter_history.py``; the release
140
+ workflow also refreshes it before building distributions.
141
+
121
142
  Declare a single local ``.bib`` file with ``bibliography: references.bib``
122
143
  in the Markdown YAML header; relative paths are resolved beside the
123
144
  Markdown file. Without that declaration, ``cpb`` uses a single adjacent
@@ -152,11 +173,21 @@ included are (listed in order of fun/utility):
152
173
  ``flowchart/watch_graph.py`` script so all of its functionality is now
153
174
  available through the main ``pydifft`` entry point.
154
175
  Add ``--diff-base HEAD`` (or a branch, tag, commit, or quoted reflog
155
- reference) to compare against that Git snapshot throughout the preview
156
- session. Additions are green, deletions are red and struck through, and
176
+ reference) to open a URL comparing against that Git snapshot.
177
+ Additions are green, deletions are red and struck through, and
157
178
  unchanged content is muted. Renames share one box; date, status, and
158
179
  dependency changes are annotated. Navigation, filters, and reloads retain
159
- the baseline, whose reference and commit appear below the graph.
180
+ the baseline through the ``diff-base`` URL parameter, whose reference and
181
+ commit appear below the graph. All view choices come from the URL:
182
+ ``t`` focuses a task and its ancestors, ``d=1``
183
+ orders dated tasks, and ``p=1`` excludes completed tasks. Command options
184
+ choose the initial URL. Removing ``diff-base`` restores normal rendering;
185
+ clearing the entire query shows the full plan, including completed and
186
+ undated tasks. Each embedded SVG and live refresh uses the same URL mode.
187
+ The search button beside Home and Zoom finds text in the visible graph,
188
+ highlights matches, and centers them at a readable font size. Tab or Enter
189
+ advances to the next match; Shift+Tab or Shift+Enter goes back. Esc closes
190
+ search. Phrases can span wrapped lines and formatted text.
160
191
  Comparison uses the same repository-relative YAML path; a file absent
161
192
  from the revision is treated as an empty plan. Historical file renames
162
193
  are not followed, and comparison markup is never written to YAML.
@@ -215,10 +246,21 @@ included are (listed in order of fun/utility):
215
246
 
216
247
  * this allows you to use an original file with good whitespace formatting as a "template" that you can match other (e.g. pandoc converted file) onto another
217
248
 
218
- * changed prose lines exceeding 1.5 times the nearby reference width are
219
- wrapped using the same sentence and punctuation rules as ``wr``.
220
- Existing surrounding line breaks are retained; the fallback width is
221
- 80 columns when the reference provides too little prose.
249
+ * ``cpb`` and ``wmatch`` share a matcher that finds changed hunks, aligns
250
+ their words using Git's minimal diff, and restores reference whitespace.
251
+ It then considers extra breaks that preserve an unchanged reference line
252
+ without stranding a tiny edited fragment, and checks wrapping rules.
253
+
254
+ * ``--wrapnumber`` sets the maximum width (79 for ``cpb`` and ``wmatch``).
255
+ Wmatch also uses nearby reference widths for large edits, retaining
256
+ unchanged reference lines and protected Markdown blocks.
257
+
258
+ * ``--trailing-dependent-phrase`` defaults to 20: a clause boundary within
259
+ 20 characters of the maximum width must end the line, even when its
260
+ trailing phrase would still fit. Commas, semicolons, colons, parentheses,
261
+ dashes, and inline-math boundaries are supported. Set it to 0 to disable
262
+ this rule. The option is shared by ``cpb``, ``wmatch``, ``wr`` and
263
+ ``wrchk``; ``--punctuation-slop`` remains an alias.
222
264
 
223
265
  - `pydifft wd` ("word diff"): generate "track changes" word files starting from pandoc markdown in a git history. Assuming that you have copied diff-doc.js (copied + licensed from elsewhere) into your home directory, this will use pandoc to convert the markdown files to MS Word, then use the MS Word comparison tool to generate a document where all relevant changes are shown with "track changes."
224
266
 
@@ -51,6 +51,7 @@ pydifftools/check_numbers.py
51
51
  pydifftools/citation_dialog.py
52
52
  pydifftools/command_line.py
53
53
  pydifftools/command_registry.py
54
+ pydifftools/comment_filter_history.json
54
55
  pydifftools/comment_functions.py
55
56
  pydifftools/comment_migration.py
56
57
  pydifftools/comment_tags.lua
@@ -70,6 +71,7 @@ pydifftools/git_gd_image.py
70
71
  pydifftools/git_gd_qt.py
71
72
  pydifftools/html_comments.py
72
73
  pydifftools/html_uncomments.py
74
+ pydifftools/line_alignment.py
73
75
  pydifftools/log_example.py
74
76
  pydifftools/match_spaces.py
75
77
  pydifftools/onewordify.py
@@ -83,6 +85,7 @@ pydifftools/split_conflict.py
83
85
  pydifftools/unseparate_comments.py
84
86
  pydifftools/update_check.py
85
87
  pydifftools/wrap_sentences.py
88
+ pydifftools/wrapping_options.py
86
89
  pydifftools/xml2xlsx.vbs
87
90
  pydifftools/zotero.py
88
91
  pydifftools/flowchart/__init__.py
@@ -101,12 +104,14 @@ tests/test_bibliography.py
101
104
  tests/test_browser_lifecycle.py
102
105
  tests/test_check_single_use.py
103
106
  tests/test_command_line_help.py
107
+ tests/test_comment_filters.py
104
108
  tests/test_comment_migration.py
105
109
  tests/test_continuous_shutdown.py
106
110
  tests/test_forward_search.py
107
111
  tests/test_git_gd_history.py
108
112
  tests/test_git_gd_image.py
109
113
  tests/test_git_gd_qt.py
114
+ tests/test_line_alignment.py
110
115
  tests/test_rrng.py
111
116
  tests/test_source_jump.py
112
117
  tests/test_tex_to_qmd.py
@@ -33,11 +33,40 @@ def launch_chrome(webdriver, **kwargs):
33
33
  "do not match; retrying with the driver version check disabled.",
34
34
  file=sys.stderr,
35
35
  )
36
- kwargs["service"] = Service(service_args=["--disable-build-check"])
36
+ service = kwargs.get("service")
37
+ kwargs["service"] = Service(
38
+ executable_path=service.path if service else None,
39
+ service_args=[
40
+ *(service.service_args if service else []),
41
+ "--disable-build-check",
42
+ ],
43
+ )
37
44
  return webdriver.Chrome(**kwargs)
38
45
  # }}}
39
46
 
40
47
 
48
+ def start_chrome():
49
+ """Use an installed driver without an online Selenium Manager lookup."""
50
+ # Keep Selenium imports lazy, as in the watch commands.
51
+ from selenium import webdriver
52
+ from selenium.webdriver.chrome.service import Service
53
+
54
+ driver_path = shutil.which("chromedriver")
55
+ if driver_path:
56
+ options = webdriver.ChromeOptions()
57
+ # Debian's driver defaults to Chromium even if Chrome is installed;
58
+ # retain Selenium Manager's preference for Google Chrome.
59
+ browser_path = shutil.which("google-chrome") or shutil.which(
60
+ "google-chrome-stable"
61
+ )
62
+ if browser_path:
63
+ options.binary_location = browser_path
64
+ return launch_chrome(
65
+ webdriver, service=Service(driver_path), options=options
66
+ )
67
+ return launch_chrome(webdriver)
68
+
69
+
41
70
  def prepare_for_dialog():
42
71
  """Let watch commands close their preview before a dialog appears."""
43
72
  for callback in list(dialog_callbacks):
@@ -11,6 +11,7 @@ import nbformat
11
11
  import difflib
12
12
  import shutil
13
13
  import importlib.util
14
+ import importlib.metadata
14
15
  from pathlib import Path
15
16
  from . import (
16
17
  match_spaces,
@@ -46,6 +47,9 @@ from .notebook.fast_build import (
46
47
  )
47
48
 
48
49
  from .command_registry import _COMMAND_SPECS, register_command
50
+ from .wrapping_options import (
51
+ DEFAULT_WIDTH, DEFAULT_TRAILING_DEPENDENT_PHRASE, WRAPPING_ARGUMENTS,
52
+ )
49
53
 
50
54
  _ARGCOMPLETE_SPEC = importlib.util.find_spec("argcomplete")
51
55
  if (
@@ -366,9 +370,19 @@ def gvr(arguments):
366
370
  @register_command(
367
371
  "match whitespace",
368
372
  filename_extensions={"arguments": [".md", ".tex"]},
373
+ argument_options={
374
+ **WRAPPING_ARGUMENTS,
375
+ "arguments": {
376
+ "nargs": 2, "metavar": ("REFERENCE", "FILE"),
377
+ "help": "Reference file and current file to reflow.",
378
+ },
379
+ },
369
380
  )
370
- def wmatch(arguments):
371
- match_spaces.run(arguments)
381
+ def wmatch(
382
+ arguments, wrapnumber=DEFAULT_WIDTH,
383
+ trailing_dependent_phrase=DEFAULT_TRAILING_DEPENDENT_PHRASE,
384
+ ):
385
+ match_spaces.run(arguments, wrapnumber, trailing_dependent_phrase)
372
386
 
373
387
 
374
388
  @register_command("split conflict")
@@ -879,6 +893,12 @@ def build_parser():
879
893
  formatter_class=argparse.RawDescriptionHelpFormatter,
880
894
  is_root_parser=True,
881
895
  )
896
+ parser.add_argument(
897
+ "--ver",
898
+ "--version",
899
+ action="version",
900
+ version=importlib.metadata.version("pyDiffTools"),
901
+ )
882
902
  parser.epilog = _subcommand_help_hint(parser.prog)
883
903
  parser._pydifft_subparsers = {}
884
904
  subparsers = parser.add_subparsers(dest="command")
@@ -913,6 +933,9 @@ def build_parser():
913
933
  def main(argv=None):
914
934
  if argv is None:
915
935
  argv = sys.argv[1:]
936
+ if argv and argv[0] in ("--ver", "--version"):
937
+ build_parser().parse_args(argv)
938
+ return
916
939
  # Run the PyPI update check once per UTC day so users see a notice but
917
940
  # startup stays fast when offline. The date is stored in the
918
941
  # PYDIFFTOOLS_UPDATE_CHECK_LAST_RAN_UTC_DATE environment variable.
@@ -959,6 +982,16 @@ def main(argv=None):
959
982
  parser._pydifft_subparsers[subcommand].print_help()
960
983
  return
961
984
  namespace = parser.parse_args(argv)
985
+ # Shared wrapping arguments are validated identically for each command.
986
+ if hasattr(namespace, "wrapnumber") and namespace.wrapnumber < 1:
987
+ parser._pydifft_subparsers[namespace.command].error(
988
+ "--wrapnumber must be at least 1"
989
+ )
990
+ if getattr(namespace, "trailing_dependent_phrase",
991
+ getattr(namespace, "punctuation_slop", 0)) < 0:
992
+ parser._pydifft_subparsers[namespace.command].error(
993
+ "--trailing-dependent-phrase must be nonnegative"
994
+ )
962
995
  if (
963
996
  namespace.command == "cpb"
964
997
  and namespace.comments_to_margin
@@ -15,6 +15,7 @@ def register_command(
15
15
  description=None,
16
16
  help=None,
17
17
  filename_extensions=None,
18
+ argument_options=None,
18
19
  ):
19
20
  """Register a command handler for the CLI dispatcher."""
20
21
 
@@ -108,6 +109,12 @@ def register_command(
108
109
  kwargs["type"] = type(parameter.default)
109
110
  if parameter.name in argument_help:
110
111
  kwargs["help"] = argument_help[parameter.name].strip()
112
+ if argument_options is not None:
113
+ kwargs.update(argument_options.get(parameter.name, {}))
114
+ override_flags = kwargs.pop("flags", None)
115
+ if override_flags is not None:
116
+ flags = override_flags
117
+ kwargs["dest"] = parameter.name
111
118
  argument_spec = {"flags": flags, "kwargs": kwargs}
112
119
  if parameter.name in completion_allowednames:
113
120
  argument_spec["completion_allowednames"] = (
@@ -0,0 +1,145 @@
1
+ {
2
+ "comment_tags.lua": {
3
+ "2a0ffaf315c28059d7e8fb67388dd38275f78eb911b640dfb567763bbf63e089": {
4
+ "commit": "73d51e080667e0b4cf8a13146a615e2866207e04",
5
+ "mode": "margin",
6
+ "path": "pydifftools/comment_tags_margin.lua"
7
+ },
8
+ "2c16914eb312e46715316ec896c0952483c0f70c519ef3a3d022f28b3047ca54": {
9
+ "commit": "016080494be7e90d49f94b0f0aeb88c47dc9241a",
10
+ "mode": "margin",
11
+ "path": "pydifftools/comment_tags_margin.lua"
12
+ },
13
+ "380c20c350751b7e9a107b8855d4f3c1c022daf410dadd1842cffbb5d6b20cd6": {
14
+ "commit": "697bbdd00d3215c46216669f419014f0d41da526",
15
+ "mode": "margin",
16
+ "path": "pydifftools/comment_tags_margin.lua"
17
+ },
18
+ "54ab119b5a0868f5349bdf224ec134be59c81b925e7d35b6a1d9173eca2671fa": {
19
+ "commit": "308647bb0cd7dc153c945703862503eea6a3da9b",
20
+ "mode": "margin",
21
+ "path": "pydifftools/comment_tags_margin.lua"
22
+ },
23
+ "5a6a27bfb21a0b674adb10b7dcc5b9bf1b34152256391ed77b354dc666e944cf": {
24
+ "commit": "697bbdd00d3215c46216669f419014f0d41da526",
25
+ "mode": "none",
26
+ "path": "pydifftools/comment_tags_no_comments.lua"
27
+ },
28
+ "5ffa678cca561170bdaa83ae0d06d6197f3781cb4be01033a5d6c03c4dbcedc3": {
29
+ "commit": "268d61dac16384984a395bef0067100ac763cb3d",
30
+ "mode": "none",
31
+ "path": "pydifftools/comment_tags_no_comments.lua"
32
+ },
33
+ "a994853143e845328e43c642b9445202b115ec07762fe85d30763006d71f7389": {
34
+ "commit": "308647bb0cd7dc153c945703862503eea6a3da9b",
35
+ "mode": "default",
36
+ "path": "pydifftools/comment_tags.lua"
37
+ },
38
+ "aecfb5915c837c724b0d9a7c9404166103da912fe2cb99834b48073b8d637ca1": {
39
+ "commit": "e2eb0fba6cb03884889a257f776a3f64c3a3185e",
40
+ "mode": "default",
41
+ "path": "pydifftools/comment_tags.lua"
42
+ },
43
+ "ba2f1e784187a3bb8dc110d1065b23bc3dd9f5993db988542009c105ee3fb925": {
44
+ "commit": "016080494be7e90d49f94b0f0aeb88c47dc9241a",
45
+ "mode": "default",
46
+ "path": "pydifftools/comment_tags.lua"
47
+ },
48
+ "d0f1a6f876382334184f3b0a1341159c827845efcccfb6d5cd06a70207660e1a": {
49
+ "commit": "697bbdd00d3215c46216669f419014f0d41da526",
50
+ "mode": "default",
51
+ "path": "pydifftools/comment_tags.lua"
52
+ },
53
+ "deea0b807c92875c8a450875ac10a7df841ffa76350f320140ee1dcb5c1445fb": {
54
+ "commit": "73d51e080667e0b4cf8a13146a615e2866207e04",
55
+ "mode": "default",
56
+ "path": "pydifftools/comment_tags.lua"
57
+ },
58
+ "fcebc0022c806cec34b467086116428cc1f48e5b23225bf5a9561f273cd7218b": {
59
+ "commit": "308647bb0cd7dc153c945703862503eea6a3da9b",
60
+ "mode": "none",
61
+ "path": "pydifftools/comment_tags_no_comments.lua"
62
+ },
63
+ "ffc14453e371f701d2a49e9a0cc29746b589372d0066c42f0c5c18f8953286f7": {
64
+ "commit": "7d2847f50b5f261c4128a89d858391f8a8c76f0c",
65
+ "mode": "default",
66
+ "path": "pydifftools/comment_tags.lua"
67
+ }
68
+ },
69
+ "comment_toggle.js": {
70
+ "1f19e86fa7bc272b15dfd4feae155ae2cb328d28fe38476306d8200329126de4": {
71
+ "commit": "60e573de785f3ad10043e6ccc7fe14b4c0292019",
72
+ "mode": "shared",
73
+ "path": "pydifftools/comment_toggle.js"
74
+ },
75
+ "34d3a67a4f79aa0711c434a8d315aa74fcb5aad95b6cbc23ba19c4a29e9dd66f": {
76
+ "commit": "9a4a907da65467eecc1595035b215e34be742441",
77
+ "mode": "shared",
78
+ "path": "pydifftools/comment_toggle.js"
79
+ },
80
+ "617107e0c5c58b1b1b15b8a2485860eb1345536974ba76caa625fa2b809516ce": {
81
+ "commit": "7e84fc03bb8daf6e1081a3ec3f93ceb934088687",
82
+ "mode": "shared",
83
+ "path": "pydifftools/comment_toggle.js"
84
+ },
85
+ "c9129af481db475469341bb2a8b6b2ba3739bddd8dc1f8601b43168519d51172": {
86
+ "commit": "e2eb0fba6cb03884889a257f776a3f64c3a3185e",
87
+ "mode": "shared",
88
+ "path": "pydifftools/comment_toggle.js"
89
+ },
90
+ "d3b405f1158b80455c998b375939e7daecbb0b7f33c8406823bc350b20096ecd": {
91
+ "commit": "016080494be7e90d49f94b0f0aeb88c47dc9241a",
92
+ "mode": "shared",
93
+ "path": "pydifftools/comment_toggle.js"
94
+ }
95
+ },
96
+ "comments.css": {
97
+ "0ad0f6ce759b071bf3e5568fb97f327db7678cbb203c2b93550b0ca32f1dd44c": {
98
+ "commit": "7e84fc03bb8daf6e1081a3ec3f93ceb934088687",
99
+ "mode": "shared",
100
+ "path": "pydifftools/comments.css"
101
+ },
102
+ "1ca5a5d10356bdf194fc05f0eab2aa4f1741d0e6d50418caa15b66f9da28c5ec": {
103
+ "commit": "8245633092781d39638f6cbf90c91090a7cccd8f",
104
+ "mode": "shared",
105
+ "path": "pydifftools/comments.css"
106
+ },
107
+ "998852f3328d0c2fb717b441e8804baf9047c1fbe5377a237e162465c37d13e3": {
108
+ "commit": "60e573de785f3ad10043e6ccc7fe14b4c0292019",
109
+ "mode": "shared",
110
+ "path": "pydifftools/comments.css"
111
+ },
112
+ "a1bb5ffd9d5a8d1a1867db36fe179c6f1070378c3719b4c68e3eebfda07a4805": {
113
+ "commit": "e2eb0fba6cb03884889a257f776a3f64c3a3185e",
114
+ "mode": "shared",
115
+ "path": "pydifftools/comments.css"
116
+ },
117
+ "a9a0686877e33d4fd640a8f513af7ff750ace05387e95e3a7fb292a94585e771": {
118
+ "commit": "73d51e080667e0b4cf8a13146a615e2866207e04",
119
+ "mode": "shared",
120
+ "path": "pydifftools/comments.css"
121
+ },
122
+ "ac1c93065a777c4f185293be2baac9011ad5d5014f67e4947b21aa353d6609cc": {
123
+ "commit": "9a4a907da65467eecc1595035b215e34be742441",
124
+ "mode": "shared",
125
+ "path": "pydifftools/comments.css"
126
+ },
127
+ "d730a992c3b6570e0a1c26b2fe351338a1b0ac7d6a8e17ace0a5292b92ba6ff5": {
128
+ "commit": "518379efe37292e5d3d9b5dfa687c0842b5e9c1d",
129
+ "mode": "shared",
130
+ "path": "pydifftools/comments.css"
131
+ },
132
+ "ea39254a85879468c2c47cf30267602afff0328ba9ae3acbe236af6501061502": {
133
+ "commit": "016080494be7e90d49f94b0f0aeb88c47dc9241a",
134
+ "mode": "shared",
135
+ "path": "pydifftools/comments.css"
136
+ }
137
+ },
138
+ "comments_author_colors.css": {
139
+ "a5e409852c32f3e80482b111c96bd6d87b37a0e3750a33d5f4f499bd6af849fe": {
140
+ "commit": "697bbdd00d3215c46216669f419014f0d41da526",
141
+ "mode": "shared",
142
+ "path": "pydifftools/comments_author_colors.css"
143
+ }
144
+ }
145
+ }
@@ -237,9 +237,13 @@ local function detect_block_opener(block)
237
237
  end
238
238
 
239
239
  if para_like_t(block) then
240
- for k, opener_spec in pairs(OPENERS) do
241
- local found, before, after = split_inline_block_at_tag(block, k)
242
- if found then
240
+ -- Scan the paragraph once, regardless of the number of authors.
241
+ local content = block.content
242
+ for index = 1, #content do
243
+ local tag = raw_inline_html(content[index])
244
+ local opener_spec = tag and OPENERS[tag] or nil
245
+ if opener_spec then
246
+ local _, before, after = split_inline_block_at_tag(block, tag)
243
247
  return opener_spec, before, after
244
248
  end
245
249
  end
@@ -452,3 +456,6 @@ function Pandoc(doc)
452
456
  end
453
457
  return doc:walk({ Inlines = Inlines, Blocks = Blocks, Div = Div })
454
458
  end
459
+
460
+ -- Initialize authors before walking comments, without an implicit first walk.
461
+ return {{ Pandoc = Pandoc }}
@@ -273,9 +273,13 @@ local function detect_block_opener(block)
273
273
  end
274
274
 
275
275
  if para_like_t(block) then
276
- for k, opener_spec in pairs(OPENERS) do
277
- local found, before, after = split_inline_block_at_tag(block, k)
278
- if found then
276
+ -- Scan the paragraph once, regardless of the number of authors.
277
+ local content = block.content
278
+ for index = 1, #content do
279
+ local tag = raw_inline_html(content[index])
280
+ local opener_spec = tag and OPENERS[tag] or nil
281
+ if opener_spec then
282
+ local _, before, after = split_inline_block_at_tag(block, tag)
279
283
  return opener_spec, before, after
280
284
  end
281
285
  end
@@ -487,3 +491,6 @@ function Pandoc(doc)
487
491
  end
488
492
  return doc:walk({ Inlines = Inlines, Blocks = Blocks, Div = Div })
489
493
  end
494
+
495
+ -- Initialize authors before walking comments, without an implicit first walk.
496
+ return {{ Pandoc = Pandoc }}