djlint 1.30.0 → 1.30.2

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 (368) hide show
  1. package/package.json +3 -2
  2. package/.coveragerc +0 -9
  3. package/.editorconfig +0 -21
  4. package/.flake8 +0 -0
  5. package/.github/FUNDING.yml +0 -2
  6. package/.github/ISSUE_TEMPLATE/config.yml +0 -6
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  8. package/.github/ISSUE_TEMPLATE/formatter_but_report.md +0 -30
  9. package/.github/ISSUE_TEMPLATE/linter_bug_report.md +0 -34
  10. package/.github/ISSUE_TEMPLATE/translation.md +0 -14
  11. package/.github/config.yml +0 -4
  12. package/.github/pull_request_template.md +0 -10
  13. package/.github/workflows/cancel.yml +0 -17
  14. package/.github/workflows/demo.yml +0 -98
  15. package/.github/workflows/issues.yml +0 -23
  16. package/.github/workflows/linkcheck.yaml +0 -21
  17. package/.github/workflows/lint.yml +0 -25
  18. package/.github/workflows/release.yml +0 -57
  19. package/.github/workflows/test.yml +0 -85
  20. package/.pre-commit-config.yaml +0 -45
  21. package/.pre-commit-hooks.yaml +0 -71
  22. package/.prettierignore +0 -7
  23. package/.prettierrc +0 -11
  24. package/.releaserc +0 -16
  25. package/CHANGELOG.md +0 -13
  26. package/MANIFEST.in +0 -2
  27. package/build_demo.sh +0 -17
  28. package/docs/.eleventy.js +0 -425
  29. package/docs/.eleventyignore +0 -2
  30. package/docs/.prettierignore +0 -3
  31. package/docs/.prettierrc +0 -11
  32. package/docs/package.json +0 -73
  33. package/docs/readme.md +0 -17
  34. package/docs/src/_data/configuration.json +0 -646
  35. package/docs/src/_data/eleventyComputed.js +0 -22
  36. package/docs/src/_data/i18n/index.js +0 -159
  37. package/docs/src/_data/js.js +0 -7
  38. package/docs/src/_data/locales.js +0 -17
  39. package/docs/src/_data/site.json +0 -8
  40. package/docs/src/_includes/demo.njk +0 -157
  41. package/docs/src/_includes/docs_layout.njk +0 -34
  42. package/docs/src/_includes/foot.njk +0 -26
  43. package/docs/src/_includes/index.njk +0 -187
  44. package/docs/src/_includes/languages_layout.njk +0 -11
  45. package/docs/src/_includes/layout.njk +0 -111
  46. package/docs/src/_includes/nav.njk +0 -85
  47. package/docs/src/_utils/minify-html.js +0 -14
  48. package/docs/src/_utils/rollupper.js +0 -91
  49. package/docs/src/_utils/scripts.11ty.js +0 -27
  50. package/docs/src/demo.njk +0 -4
  51. package/docs/src/docs/best-practices.md +0 -78
  52. package/docs/src/docs/changelog.md +0 -452
  53. package/docs/src/docs/configuration.md +0 -145
  54. package/docs/src/docs/docs.json +0 -4
  55. package/docs/src/docs/formatter.md +0 -82
  56. package/docs/src/docs/getting-started.md +0 -126
  57. package/docs/src/docs/ignoring-code.md +0 -75
  58. package/docs/src/docs/integrations.md +0 -120
  59. package/docs/src/docs/languages/angular.md +0 -31
  60. package/docs/src/docs/languages/django.md +0 -40
  61. package/docs/src/docs/languages/golang.md +0 -31
  62. package/docs/src/docs/languages/handlebars.md +0 -31
  63. package/docs/src/docs/languages/jinja.md +0 -39
  64. package/docs/src/docs/languages/languages.json +0 -3
  65. package/docs/src/docs/languages/mustache.md +0 -31
  66. package/docs/src/docs/languages/nunjucks.md +0 -39
  67. package/docs/src/docs/languages/twig.md +0 -41
  68. package/docs/src/docs/linter.md +0 -199
  69. package/docs/src/fr/demo.njk +0 -4
  70. package/docs/src/fr/docs/best-practices.md +0 -78
  71. package/docs/src/fr/docs/changelog.md +0 -452
  72. package/docs/src/fr/docs/configuration.md +0 -144
  73. package/docs/src/fr/docs/docs.json +0 -3
  74. package/docs/src/fr/docs/formatter.md +0 -83
  75. package/docs/src/fr/docs/getting-started.md +0 -127
  76. package/docs/src/fr/docs/ignoring-code.md +0 -75
  77. package/docs/src/fr/docs/integrations.md +0 -100
  78. package/docs/src/fr/docs/languages/angular.md +0 -31
  79. package/docs/src/fr/docs/languages/django.md +0 -31
  80. package/docs/src/fr/docs/languages/golang.md +0 -31
  81. package/docs/src/fr/docs/languages/handlebars.md +0 -31
  82. package/docs/src/fr/docs/languages/jinja.md +0 -31
  83. package/docs/src/fr/docs/languages/languages.json +0 -3
  84. package/docs/src/fr/docs/languages/mustache.md +0 -31
  85. package/docs/src/fr/docs/languages/nunjucks.md +0 -31
  86. package/docs/src/fr/docs/languages/twig.md +0 -31
  87. package/docs/src/fr/docs/linter.md +0 -207
  88. package/docs/src/fr/fr.json +0 -4
  89. package/docs/src/fr/index.njk +0 -4
  90. package/docs/src/index.njk +0 -4
  91. package/docs/src/lib/generate-content-hash.js +0 -13
  92. package/docs/src/robots.txt +0 -4
  93. package/docs/src/ru/demo.njk +0 -4
  94. package/docs/src/ru/docs/best-practices.md +0 -78
  95. package/docs/src/ru/docs/changelog.md +0 -453
  96. package/docs/src/ru/docs/configuration.md +0 -142
  97. package/docs/src/ru/docs/docs.json +0 -3
  98. package/docs/src/ru/docs/formatter.md +0 -82
  99. package/docs/src/ru/docs/getting-started.md +0 -127
  100. package/docs/src/ru/docs/ignoring-code.md +0 -75
  101. package/docs/src/ru/docs/integrations.md +0 -100
  102. package/docs/src/ru/docs/languages/angular.md +0 -31
  103. package/docs/src/ru/docs/languages/django.md +0 -31
  104. package/docs/src/ru/docs/languages/golang.md +0 -31
  105. package/docs/src/ru/docs/languages/handlebars.md +0 -31
  106. package/docs/src/ru/docs/languages/jinja.md +0 -31
  107. package/docs/src/ru/docs/languages/languages.json +0 -3
  108. package/docs/src/ru/docs/languages/mustache.md +0 -31
  109. package/docs/src/ru/docs/languages/nunjucks.md +0 -31
  110. package/docs/src/ru/docs/languages/twig.md +0 -31
  111. package/docs/src/ru/docs/linter.md +0 -126
  112. package/docs/src/ru/index.njk +0 -4
  113. package/docs/src/ru/ru.json +0 -4
  114. package/docs/src/sitemap.njk +0 -16
  115. package/docs/src/static/css/site.scss +0 -467
  116. package/docs/src/static/font/fontawesome/stylesheet.scss +0 -78
  117. package/docs/src/static/img/apple-touch-icon.png +0 -0
  118. package/docs/src/static/img/demo-min.gif +0 -0
  119. package/docs/src/static/img/demo.gif +0 -0
  120. package/docs/src/static/img/demo.webm +0 -0
  121. package/docs/src/static/img/favicon-16x16.png +0 -0
  122. package/docs/src/static/img/favicon-32x32.png +0 -0
  123. package/docs/src/static/img/favicon.ico +0 -0
  124. package/docs/src/static/img/icon-square.indd +0 -0
  125. package/docs/src/static/img/icon-square.png +0 -0
  126. package/docs/src/static/img/icon.png +0 -0
  127. package/docs/src/static/img/logo-192x192.png +0 -0
  128. package/docs/src/static/img/logo-512x512.png +0 -0
  129. package/docs/src/static/img/logos/angular.png +0 -0
  130. package/docs/src/static/img/logos/django.png +0 -0
  131. package/docs/src/static/img/logos/golang.png +0 -0
  132. package/docs/src/static/img/logos/handlebars.png +0 -0
  133. package/docs/src/static/img/logos/jinja.png +0 -0
  134. package/docs/src/static/img/logos/mustache.png +0 -0
  135. package/docs/src/static/img/logos/nunjucks.png +0 -0
  136. package/docs/src/static/img/logos/twig.png +0 -0
  137. package/docs/src/static/img/old_demo.gif +0 -0
  138. package/docs/src/static/img/style.css +0 -122
  139. package/docs/src/static/js/animate.js +0 -69
  140. package/docs/src/static/js/editor.js +0 -171
  141. package/docs/src/static/js/hamburger.js +0 -19
  142. package/docs/src/static/js/modal.js +0 -47
  143. package/docs/src/static/js/worker.js +0 -142
  144. package/docs/src/static/py/EditorConfig-99-py3-none-any.whl +0 -0
  145. package/docs/src/static/py/PyYAML-99-py3-none-any.whl +0 -0
  146. package/docs/src/static/py/click-99-py3-none-any.whl +0 -0
  147. package/docs/src/static/py/colorama-99-py3-none-any.whl +0 -0
  148. package/docs/src/static/py/cssbeautifier-99-py3-none-any.whl +0 -0
  149. package/docs/src/static/py/djlint-99-py3-none-any.whl +0 -0
  150. package/docs/src/static/py/html_tag_names-99-py3-none-any.whl +0 -0
  151. package/docs/src/static/py/html_void_elements-99-py3-none-any.whl +0 -0
  152. package/docs/src/static/py/jsbeautifier-99-py3-none-any.whl +0 -0
  153. package/docs/src/static/py/json5-99-py3-none-any.whl +0 -0
  154. package/docs/src/static/py/pathspec-99-py3-none-any.whl +0 -0
  155. package/docs/src/static/py/regex-2023.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +0 -0
  156. package/docs/src/static/py/six-1.16.0-py2.py3-none-any.whl +0 -0
  157. package/docs/src/static/py/tomli-2.0.1-py3-none-any.whl +0 -0
  158. package/docs/src/static/py/tqdm-4.65.0-py3-none-any.whl +0 -0
  159. package/icon.xcf +0 -0
  160. package/poetry.lock +0 -835
  161. package/pyproject.toml +0 -100
  162. package/renovate.json +0 -44
  163. package/scripts/updateVersion.js +0 -16
  164. package/src/djlint/__init__.py +0 -451
  165. package/src/djlint/__main__.py +0 -4
  166. package/src/djlint/formatter/__init__.py +0 -1
  167. package/src/djlint/formatter/attributes.py +0 -212
  168. package/src/djlint/formatter/compress.py +0 -64
  169. package/src/djlint/formatter/condense.py +0 -221
  170. package/src/djlint/formatter/css.py +0 -60
  171. package/src/djlint/formatter/expand.py +0 -111
  172. package/src/djlint/formatter/indent.py +0 -418
  173. package/src/djlint/formatter/js.py +0 -58
  174. package/src/djlint/helpers.py +0 -321
  175. package/src/djlint/lint.py +0 -128
  176. package/src/djlint/output.py +0 -220
  177. package/src/djlint/reformat.py +0 -63
  178. package/src/djlint/rules/H025.py +0 -65
  179. package/src/djlint/rules.yaml +0 -279
  180. package/src/djlint/settings.py +0 -969
  181. package/src/djlint/src.py +0 -91
  182. package/tests/__init__.py +0 -0
  183. package/tests/conftest.py +0 -239
  184. package/tests/test_cli.py +0 -71
  185. package/tests/test_config/__init__.py +0 -0
  186. package/tests/test_config/test_blank_line_after_tag.py +0 -135
  187. package/tests/test_config/test_blank_line_before_tag.py +0 -141
  188. package/tests/test_config/test_close_void_tags.py +0 -31
  189. package/tests/test_config/test_custom_blocks.py +0 -56
  190. package/tests/test_config/test_custom_html.py +0 -45
  191. package/tests/test_config/test_djlintrc/.djlintrc +0 -38
  192. package/tests/test_config/test_djlintrc/__init__.py +0 -0
  193. package/tests/test_config/test_djlintrc/test_config.py +0 -44
  194. package/tests/test_config/test_djlintrc_custom/.djlint-cust +0 -38
  195. package/tests/test_config/test_djlintrc_custom/.djlintrc +0 -2
  196. package/tests/test_config/test_djlintrc_custom/__init__.py +0 -0
  197. package/tests/test_config/test_djlintrc_custom/test_config.py +0 -48
  198. package/tests/test_config/test_excludes/__init__.py +0 -0
  199. package/tests/test_config/test_excludes/excluded.html +0 -1
  200. package/tests/test_config/test_excludes/foo/excluded.html +0 -1
  201. package/tests/test_config/test_excludes/html.html +0 -1
  202. package/tests/test_config/test_excludes/pyproject.toml +0 -3
  203. package/tests/test_config/test_excludes/test_config.py +0 -30
  204. package/tests/test_config/test_extension/__init__.py +0 -0
  205. package/tests/test_config/test_extension/html.test +0 -1
  206. package/tests/test_config/test_extension/pyproject.toml +0 -3
  207. package/tests/test_config/test_extension/test_config.py +0 -27
  208. package/tests/test_config/test_files/.djlintrc_global +0 -9
  209. package/tests/test_config/test_files/test.html +0 -3
  210. package/tests/test_config/test_files/test_config.py +0 -123
  211. package/tests/test_config/test_files/test_two.html +0 -1
  212. package/tests/test_config/test_format_attribute_template_tags.py +0 -280
  213. package/tests/test_config/test_format_css.py +0 -197
  214. package/tests/test_config/test_format_js.py +0 -220
  215. package/tests/test_config/test_gitignore/__init__.py +0 -0
  216. package/tests/test_config/test_gitignore/html_one.html +0 -1
  217. package/tests/test_config/test_gitignore/html_two.html +0 -1
  218. package/tests/test_config/test_gitignore/test_config.py +0 -142
  219. package/tests/test_config/test_ignore/__init__.py +0 -0
  220. package/tests/test_config/test_ignore/html.html +0 -1
  221. package/tests/test_config/test_ignore/html_two.html +0 -12
  222. package/tests/test_config/test_ignore/pyproject.toml +0 -3
  223. package/tests/test_config/test_ignore/test_config.py +0 -32
  224. package/tests/test_config/test_ignore_blocks.py +0 -45
  225. package/tests/test_config/test_ignore_case.py +0 -39
  226. package/tests/test_config/test_indent.py +0 -63
  227. package/tests/test_config/test_linter_output_format/__init__.py +0 -0
  228. package/tests/test_config/test_linter_output_format/html-one.html +0 -1
  229. package/tests/test_config/test_linter_output_format/html-two.html +0 -1
  230. package/tests/test_config/test_linter_output_format/pyproject.toml +0 -3
  231. package/tests/test_config/test_linter_output_format/test_config.py +0 -34
  232. package/tests/test_config/test_max_attribute_length.py +0 -100
  233. package/tests/test_config/test_max_line_length.py +0 -94
  234. package/tests/test_config/test_per_file_ignores/__init__.py +0 -0
  235. package/tests/test_config/test_per_file_ignores/html.html +0 -2
  236. package/tests/test_config/test_per_file_ignores/pyproject.toml +0 -2
  237. package/tests/test_config/test_per_file_ignores/test_config.py +0 -25
  238. package/tests/test_config/test_pragmas/__init__.py +0 -0
  239. package/tests/test_config/test_pragmas/html_five.html +0 -2
  240. package/tests/test_config/test_pragmas/html_four.html +0 -5
  241. package/tests/test_config/test_pragmas/html_one.html +0 -1
  242. package/tests/test_config/test_pragmas/html_six.html +0 -2
  243. package/tests/test_config/test_pragmas/html_three.html +0 -4
  244. package/tests/test_config/test_pragmas/html_two.html +0 -2
  245. package/tests/test_config/test_pragmas/pyproject.toml +0 -3
  246. package/tests/test_config/test_pragmas/test_config.py +0 -142
  247. package/tests/test_config/test_preserve_blank_lines.py +0 -109
  248. package/tests/test_config/test_preserve_leading_space.py +0 -159
  249. package/tests/test_config/test_profile/__init__.py +0 -0
  250. package/tests/test_config/test_profile/html.html +0 -2
  251. package/tests/test_config/test_profile/pyproject.toml +0 -3
  252. package/tests/test_config/test_profile/test_config.py +0 -64
  253. package/tests/test_config/test_pyproject/__init__.py +0 -0
  254. package/tests/test_config/test_pyproject/blank.html +0 -0
  255. package/tests/test_config/test_pyproject/pyproject.toml +0 -36
  256. package/tests/test_config/test_pyproject/test_config.py +0 -44
  257. package/tests/test_django/__init__.py +0 -0
  258. package/tests/test_django/test_asset.py +0 -32
  259. package/tests/test_django/test_autoescape.py +0 -25
  260. package/tests/test_django/test_block.py +0 -29
  261. package/tests/test_django/test_blocktrans.py +0 -236
  262. package/tests/test_django/test_blocktrans_trimmed.py +0 -283
  263. package/tests/test_django/test_comments.py +0 -164
  264. package/tests/test_django/test_filter.py +0 -30
  265. package/tests/test_django/test_for.py +0 -34
  266. package/tests/test_django/test_if.py +0 -34
  267. package/tests/test_django/test_ifchanged.py +0 -37
  268. package/tests/test_django/test_include.py +0 -24
  269. package/tests/test_django/test_load.py +0 -24
  270. package/tests/test_django/test_quoted.py +0 -34
  271. package/tests/test_django/test_spaceless.py +0 -30
  272. package/tests/test_django/test_tag_spaces.py +0 -35
  273. package/tests/test_django/test_templatetag.py +0 -40
  274. package/tests/test_django/test_verbatim.py +0 -24
  275. package/tests/test_django/test_with.py +0 -32
  276. package/tests/test_djlint/-.html +0 -1
  277. package/tests/test_djlint/__init__.py +0 -0
  278. package/tests/test_djlint/bad.html +0 -6
  279. package/tests/test_djlint/bad.html.dj +0 -23
  280. package/tests/test_djlint/bad.html.dj2 +0 -2
  281. package/tests/test_djlint/multiple_files/a/a.html +0 -1
  282. package/tests/test_djlint/multiple_files/b/b1.html +0 -1
  283. package/tests/test_djlint/multiple_files/b/b2.html +0 -1
  284. package/tests/test_djlint/test_djlint.py +0 -242
  285. package/tests/test_golang/__init__.py +0 -0
  286. package/tests/test_golang/test_if.py +0 -24
  287. package/tests/test_golang/test_range.py +0 -24
  288. package/tests/test_handlebars/__init__.py +0 -0
  289. package/tests/test_handlebars/test_each.py +0 -34
  290. package/tests/test_handlebars/test_else.py +0 -24
  291. package/tests/test_handlebars/test_with.py +0 -24
  292. package/tests/test_html/__init__.py +0 -0
  293. package/tests/test_html/test_alpinejs.py +0 -65
  294. package/tests/test_html/test_attributes.py +0 -935
  295. package/tests/test_html/test_aurelia.py +0 -24
  296. package/tests/test_html/test_basics.py +0 -905
  297. package/tests/test_html/test_bracket_same_line.py +0 -177
  298. package/tests/test_html/test_case.py +0 -81
  299. package/tests/test_html/test_cdata.py +0 -34
  300. package/tests/test_html/test_comments.py +0 -333
  301. package/tests/test_html/test_css.py +0 -193
  302. package/tests/test_html/test_doctype_declarations.py +0 -202
  303. package/tests/test_html/test_ignored.py +0 -193
  304. package/tests/test_html/test_interpolation.py +0 -56
  305. package/tests/test_html/test_line_break_after_multiline_tag.py +0 -95
  306. package/tests/test_html/test_next_line_empty.py +0 -53
  307. package/tests/test_html/test_selfclosing.py +0 -55
  308. package/tests/test_html/test_single_attribute_per_line.py +0 -87
  309. package/tests/test_html/test_srcset.py +0 -43
  310. package/tests/test_html/test_svg.py +0 -104
  311. package/tests/test_html/test_symbol_entities.py +0 -34
  312. package/tests/test_html/test_tag_code.py +0 -24
  313. package/tests/test_html/test_tag_dd.py +0 -24
  314. package/tests/test_html/test_tag_details_summary.py +0 -24
  315. package/tests/test_html/test_tag_dt.py +0 -24
  316. package/tests/test_html/test_tag_fig_caption.py +0 -29
  317. package/tests/test_html/test_tag_hr.py +0 -29
  318. package/tests/test_html/test_tag_picture.py +0 -32
  319. package/tests/test_html/test_tag_pre.py +0 -45
  320. package/tests/test_html/test_tag_script.py +0 -516
  321. package/tests/test_html/test_tag_small.py +0 -24
  322. package/tests/test_html/test_tag_span.py +0 -119
  323. package/tests/test_html/test_tag_textarea.py +0 -82
  324. package/tests/test_html/test_tags.py +0 -842
  325. package/tests/test_html/test_text.py +0 -34
  326. package/tests/test_html/test_whitespace.py +0 -477
  327. package/tests/test_html/test_yaml.py +0 -156
  328. package/tests/test_jinja/__init__.py +0 -0
  329. package/tests/test_jinja/test_call.py +0 -34
  330. package/tests/test_jinja/test_parenthesis.py +0 -24
  331. package/tests/test_linter/__init__.py +0 -0
  332. package/tests/test_linter/test_custom_rules/.djlint_rules.yaml +0 -6
  333. package/tests/test_linter/test_custom_rules/__init__.py +0 -0
  334. package/tests/test_linter/test_custom_rules/html.html +0 -1
  335. package/tests/test_linter/test_custom_rules/pyproject.toml +0 -1
  336. package/tests/test_linter/test_custom_rules/test_linter.py +0 -29
  337. package/tests/test_linter/test_custom_rules_bad/.djlint_rules.yaml +0 -24
  338. package/tests/test_linter/test_custom_rules_bad/__init__.py +0 -0
  339. package/tests/test_linter/test_custom_rules_bad/html.html +0 -1
  340. package/tests/test_linter/test_custom_rules_bad/pyproject.toml +0 -1
  341. package/tests/test_linter/test_custom_rules_bad/test_linter.py +0 -29
  342. package/tests/test_linter/test_django_linter.py +0 -476
  343. package/tests/test_linter/test_h005.py +0 -45
  344. package/tests/test_linter/test_h006.py +0 -81
  345. package/tests/test_linter/test_h007.py +0 -45
  346. package/tests/test_linter/test_h008.py +0 -60
  347. package/tests/test_linter/test_h009.py +0 -45
  348. package/tests/test_linter/test_h010.py +0 -44
  349. package/tests/test_linter/test_h037.py +0 -150
  350. package/tests/test_linter/test_ignore_rules.py +0 -45
  351. package/tests/test_linter/test_jinja_linter.py +0 -227
  352. package/tests/test_linter/test_linter.py +0 -691
  353. package/tests/test_linter/test_nunjucks_linter.py +0 -59
  354. package/tests/test_linter/test_python_module_rules/.djlint_rules.yaml +0 -4
  355. package/tests/test_linter/test_python_module_rules/__init__.py +0 -0
  356. package/tests/test_linter/test_python_module_rules/html_bad.html +0 -3
  357. package/tests/test_linter/test_python_module_rules/html_ok.html +0 -3
  358. package/tests/test_linter/test_python_module_rules/my_module.py +0 -32
  359. package/tests/test_linter/test_python_module_rules/pyproject.toml +0 -1
  360. package/tests/test_linter/test_python_module_rules/test_linter.py +0 -26
  361. package/tests/test_nunjucks/__init__.py +0 -0
  362. package/tests/test_nunjucks/test_functions.py +0 -94
  363. package/tests/test_nunjucks/test_macros.py +0 -41
  364. package/tests/test_nunjucks/test_set.py +0 -206
  365. package/tests/test_nunjucks/test_spaceless.py +0 -24
  366. package/tests/test_twig/__init__.py +0 -0
  367. package/tests/test_twig/test_comments.py +0 -51
  368. package/tox.ini +0 -48
@@ -1,321 +0,0 @@
1
- """Collection of shared djLint functions."""
2
- import regex as re
3
-
4
- from .settings import Config
5
-
6
-
7
- def is_ignored_block_opening(config: Config, item: str) -> bool:
8
- """Find ignored group opening.
9
-
10
- A valid ignored group opening tag will not be part of a
11
- single line block.
12
- """
13
- last_index = 0
14
- inline = list(
15
- re.finditer(
16
- config.ignored_blocks_inline,
17
- item,
18
- flags=re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
19
- )
20
- )
21
-
22
- if inline:
23
- last_index = inline[
24
- -1
25
- ].end() # get the last index. The ignored opening should start after this.
26
-
27
- return bool(
28
- re.search(
29
- re.compile(config.ignored_block_opening, re.IGNORECASE | re.VERBOSE),
30
- item[last_index:],
31
- )
32
- )
33
-
34
-
35
- def inside_protected_trans_block(config: Config, html: str, match: re.Match) -> bool:
36
- """Find ignored group closing.
37
-
38
- A valid ignored group closing tag will not be part of a
39
- single line block.
40
-
41
- True = non indentable > inside ignored trans block
42
- False = indentable > either inside a trans trimmed block, or somewhere else, but not a trans non trimmed :)
43
- """
44
- last_index = 0
45
- close_block = re.search(
46
- re.compile(
47
- config.ignored_trans_blocks_closing, flags=re.IGNORECASE | re.VERBOSE
48
- ),
49
- match.group(),
50
- )
51
-
52
- if not close_block:
53
- return False
54
-
55
- non_trimmed = list(
56
- re.finditer(
57
- re.compile(
58
- config.ignored_trans_blocks,
59
- flags=re.IGNORECASE | re.VERBOSE | re.DOTALL,
60
- ),
61
- html,
62
- )
63
- )
64
-
65
- trimmed = list(
66
- re.finditer(
67
- re.compile(
68
- config.trans_trimmed_blocks,
69
- flags=re.IGNORECASE | re.VERBOSE | re.DOTALL,
70
- ),
71
- html,
72
- )
73
- )
74
-
75
- # who is max?
76
- if non_trimmed and (not trimmed or non_trimmed[-1].end() > trimmed[-1].end()):
77
- # non trimmed!
78
- # check that this is not an inline block.
79
- non_trimmed_inline = list(
80
- re.finditer(
81
- re.compile(
82
- config.ignored_trans_blocks,
83
- flags=re.IGNORECASE | re.VERBOSE | re.DOTALL,
84
- ),
85
- match.group(),
86
- )
87
- )
88
-
89
- if non_trimmed_inline:
90
- last_index = non_trimmed[
91
- -1
92
- ].end() # get the last index. The ignored opening should start after this.
93
-
94
- return re.search(
95
- re.compile(
96
- config.ignored_trans_blocks_closing,
97
- flags=re.IGNORECASE | re.VERBOSE,
98
- ),
99
- html[last_index:],
100
- )
101
-
102
- return close_block.end(0) <= non_trimmed[-1].end()
103
-
104
- elif trimmed:
105
- # inside a trimmed block, we can return true to continue as if
106
- # this is a indentable block
107
- return close_block.end(0) > trimmed[-1].end()
108
- return False
109
-
110
- # print(close_block)
111
- # if non_trimmed:
112
- # last_index = non_trimmed[
113
- # -1
114
- # ].end() # get the last index. The ignored opening should start after this.
115
-
116
- # return re.search(
117
- # re.compile(
118
- # config.ignored_trans_blocks_closing, flags=re.IGNORECASE | re.VERBOSE
119
- # ),
120
- # html[last_index:],
121
- # )
122
-
123
-
124
- def is_ignored_block_closing(config: Config, item: str) -> bool:
125
- """Find ignored group closing.
126
-
127
- A valid ignored group closing tag will not be part of a
128
- single line block.
129
- """
130
- last_index = 0
131
- inline = list(
132
- re.finditer(
133
- re.compile(config.ignored_inline_blocks, flags=re.IGNORECASE | re.VERBOSE),
134
- item,
135
- )
136
- )
137
-
138
- if inline:
139
- last_index = inline[
140
- -1
141
- ].end() # get the last index. The ignored opening should start after this.
142
-
143
- return re.search(
144
- re.compile(config.ignored_block_closing, flags=re.IGNORECASE | re.VERBOSE),
145
- item[last_index:],
146
- )
147
-
148
-
149
- def is_safe_closing_tag(config: Config, item: str) -> bool:
150
- """Find ignored group opening.
151
-
152
- A valid ignored group opening tag will not be part of a
153
- single line block.
154
- """
155
- last_index = 0
156
- inline = list(
157
- re.finditer(
158
- re.compile(
159
- config.ignored_inline_blocks + r" | " + config.ignored_blocks,
160
- flags=re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
161
- ),
162
- item,
163
- )
164
- )
165
-
166
- if inline:
167
- last_index = inline[
168
- -1
169
- ].end() # get the last index. The ignored opening should start after this.
170
-
171
- return re.search(
172
- re.compile(config.safe_closing_tag, flags=re.IGNORECASE | re.VERBOSE),
173
- item[last_index:],
174
- )
175
-
176
-
177
- def inside_template_block(config: Config, html: str, match: re.Match) -> bool:
178
- """Check if a re.Match is inside of a template block."""
179
- return any(
180
- ignored_match.start(0) <= match.start() and match.end(0) <= ignored_match.end()
181
- for ignored_match in list(
182
- re.finditer(
183
- re.compile(
184
- config.template_blocks,
185
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE,
186
- ),
187
- html,
188
- )
189
- )
190
- )
191
-
192
-
193
- def inside_ignored_linter_block(config: Config, html: str, match: re.Match) -> bool:
194
- """Check if a re.Match is inside of a ignored linter block."""
195
- return any(
196
- ignored_match.start(0) <= match.start() and match.end(0) <= ignored_match.end()
197
- for ignored_match in list(
198
- re.finditer(
199
- re.compile(
200
- config.ignored_linter_blocks,
201
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE,
202
- ),
203
- html,
204
- )
205
- )
206
- )
207
-
208
-
209
- def inside_ignored_block(config: Config, html: str, match: re.Match) -> bool:
210
- """Do not add whitespace if the tag is in a non indent block."""
211
- return any(
212
- ignored_match.start(0) <= match.start() and match.end(0) <= ignored_match.end()
213
- for ignored_match in list(
214
- re.finditer(
215
- re.compile(
216
- config.ignored_blocks,
217
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE,
218
- ),
219
- html,
220
- )
221
- )
222
- + list(
223
- re.finditer(
224
- re.compile(config.ignored_inline_blocks, re.IGNORECASE | re.VERBOSE),
225
- html,
226
- )
227
- )
228
- )
229
-
230
-
231
- def child_of_unformatted_block(config: Config, html: str, match: re.Match) -> bool:
232
- """Do not add whitespace if the tag is in a non indent block."""
233
- return any(
234
- ignored_match.start(0) < match.start() and match.end(0) <= ignored_match.end()
235
- for ignored_match in list(
236
- re.finditer(
237
- re.compile(
238
- config.unformatted_blocks,
239
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE,
240
- ),
241
- html,
242
- )
243
- )
244
- )
245
-
246
-
247
- def child_of_ignored_block(config: Config, html: str, match: re.Match) -> bool:
248
- """Do not add whitespace if the tag is in a non indent block."""
249
- return any(
250
- ignored_match.start(0) < match.start() and match.end(0) <= ignored_match.end()
251
- for ignored_match in list(
252
- re.finditer(
253
- re.compile(
254
- config.ignored_blocks,
255
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE,
256
- ),
257
- html,
258
- )
259
- )
260
- + list(
261
- re.finditer(
262
- re.compile(config.ignored_inline_blocks, re.IGNORECASE | re.VERBOSE),
263
- html,
264
- )
265
- )
266
- )
267
-
268
-
269
- def overlaps_ignored_block(config: Config, html: str, match: re.Match) -> bool:
270
- """Do not add whitespace if the tag is in a non indent block."""
271
- return any(
272
- # don't require the match to be fully inside the ignored block.
273
- # poorly build html will probably span ignored blocks and should be ignored.
274
- (
275
- ignored_match.start(0) <= match.start()
276
- and match.start() <= ignored_match.end()
277
- )
278
- or (
279
- ignored_match.start(0) <= match.end() and match.end() <= ignored_match.end()
280
- )
281
- for ignored_match in list(
282
- re.finditer(
283
- re.compile(
284
- config.ignored_blocks,
285
- re.DOTALL | re.IGNORECASE | re.VERBOSE | re.MULTILINE | re.DOTALL,
286
- ),
287
- html,
288
- )
289
- )
290
- + list(
291
- re.finditer(
292
- re.compile(config.ignored_inline_blocks, re.IGNORECASE | re.VERBOSE),
293
- html,
294
- )
295
- )
296
- )
297
-
298
-
299
- def inside_ignored_rule(config: Config, html: str, match: re.Match, rule: str) -> bool:
300
- """Check if match is inside an ignored pattern."""
301
- for rule_regex in config.ignored_rules:
302
- for ignored_match in list(
303
- re.finditer(
304
- re.compile(rule_regex, re.DOTALL | re.IGNORECASE | re.VERBOSE),
305
- html,
306
- )
307
- ):
308
- if (
309
- rule in list(set(re.split(r"\s|,", ignored_match.group(1).strip())))
310
- and (
311
- ignored_match.start(0) <= match.start()
312
- and match.start() <= ignored_match.end()
313
- )
314
- or not ignored_match.group(1).strip()
315
- and (
316
- ignored_match.start(0) <= match.end()
317
- and match.end() <= ignored_match.end()
318
- )
319
- ):
320
- return True
321
- return False
@@ -1,128 +0,0 @@
1
- """Djlint html linter."""
2
- import importlib
3
- from pathlib import Path
4
- from typing import Dict, List
5
-
6
- import regex as re
7
-
8
- from .helpers import (
9
- inside_ignored_linter_block,
10
- inside_ignored_rule,
11
- overlaps_ignored_block,
12
- )
13
- from .settings import Config
14
-
15
- flags = {
16
- "re.A": re.A,
17
- "re.ASCII": re.ASCII,
18
- "re.I": re.I,
19
- "re.IGNORECASE": re.IGNORECASE,
20
- "re.M": re.M,
21
- "re.MULTILINE": re.MULTILINE,
22
- "re.S": re.S,
23
- "re.DOTALL": re.DOTALL,
24
- "re.X": re.X,
25
- "re.VERBOSE": re.VERBOSE,
26
- "re.L": re.L,
27
- "re.LOCALE": re.LOCALE,
28
- }
29
-
30
-
31
- def build_flags(flag_list: str) -> int:
32
- """Build list of regex flags."""
33
- split_flags = flag_list.split("|")
34
-
35
- combined_flags = 0
36
- for flag in split_flags:
37
- combined_flags |= flags[flag.strip()]
38
- return combined_flags
39
-
40
-
41
- def get_line(start: int, line_ends: List) -> str:
42
- """Get the line number and index of match."""
43
- line = list(filter(lambda pair: pair["end"] > start, line_ends))[0]
44
-
45
- # pylint: disable=C0209
46
- return "%d:%d" % (line_ends.index(line) + 1, start - line["start"])
47
-
48
-
49
- def linter(config: Config, html: str, filename: str, filepath: str) -> Dict:
50
- """Lint a html string."""
51
- errors: dict = {filename: []}
52
- # build list of line ends for file
53
- line_ends = [
54
- {"start": m.start(), "end": m.end()}
55
- for m in re.finditer(r"(?:.*\n)|(?:[^\n]+$)", html)
56
- ]
57
-
58
- ignored_rules: List[str] = []
59
-
60
- # remove ignored rules for file
61
- for pattern, rules in config.per_file_ignores.items():
62
- if re.search(pattern, filepath, re.VERBOSE):
63
- ignored_rules += [x.strip() for x in rules.split(",")]
64
-
65
- for rule in config.linter_rules:
66
- rule = rule["rule"]
67
-
68
- # skip ignored rules
69
- if rule["name"] in ignored_rules:
70
- continue
71
-
72
- # rule based on python module
73
- if "python_module" in rule:
74
- rule_module = importlib.import_module(rule["python_module"])
75
- module_errors = rule_module.run(
76
- rule=rule,
77
- config=config,
78
- html=html,
79
- filepath=filepath,
80
- line_ends=line_ends,
81
- )
82
- assert isinstance(module_errors, list), (
83
- f"Error: {rule['name']} python_module run() should return a list of "
84
- "dict with keys: code, line, match, message."
85
- )
86
- errors[filename].extend(module_errors)
87
-
88
- # rule based on patterns
89
- else:
90
- for pattern in rule["patterns"]:
91
- for match in re.finditer(
92
- re.compile(
93
- pattern, flags=build_flags(rule.get("flags", "re.DOTALL"))
94
- ),
95
- html,
96
- ):
97
- if (
98
- overlaps_ignored_block(config, html, match) is False
99
- and inside_ignored_rule(config, html, match, rule["name"])
100
- is False
101
- and inside_ignored_linter_block(config, html, match) is False
102
- ):
103
- errors[filename].append(
104
- {
105
- "code": rule["name"],
106
- "line": get_line(match.start(), line_ends),
107
- "match": match.group().strip()[:20],
108
- "message": rule["message"],
109
- }
110
- )
111
-
112
- # remove duplicate matches
113
- for filename, error_dict in errors.items():
114
- unique_errors = []
115
- for dict_ in error_dict:
116
- if dict_ not in unique_errors:
117
- unique_errors.append(dict_)
118
- errors[filename] = unique_errors
119
- return errors
120
-
121
-
122
- def lint_file(config: Config, this_file: Path) -> Dict:
123
- """Check file for formatting errors."""
124
- filename = str(this_file)
125
-
126
- html = this_file.read_text(encoding="utf8")
127
-
128
- return linter(config, html, filename, this_file.as_posix())
@@ -1,220 +0,0 @@
1
- """Build djLint console output."""
2
- import shutil
3
- from collections import Counter
4
- from pathlib import Path
5
- from typing import Any, Dict, List, Optional
6
-
7
- import regex as re
8
- from click import echo
9
- from colorama import Fore, Style
10
-
11
- from .settings import Config
12
-
13
- try:
14
- # this is used for windows + gitbash to set encoding correctly.
15
- import sys
16
-
17
- sys.stdout.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
18
- # pylint:disable=W0703
19
- except BaseException:
20
- pass
21
-
22
-
23
- def print_output(
24
- config: Config, file_errors: List[Dict[Any, Any]], file_count: int
25
- ) -> int:
26
- """Print results to console."""
27
- file_quantity = build_quantity(file_count)
28
- # format errors
29
- reformat_success_message = ""
30
- lint_success_message = ""
31
- lint_error_count = 0
32
- format_error_count = 0
33
- print_blanks = config.stdin is False and config.quiet is False
34
-
35
- if print_blanks:
36
- echo()
37
-
38
- for error in sorted(file_errors, key=lambda x: next(iter(list(x.values())[0]))):
39
- if error.get("format_message") and config.stdin is False:
40
- # reformat message
41
- format_error_count += build_check_output(error["format_message"], config)
42
-
43
- if error.get("lint_message"):
44
- # lint message
45
- lint_error_count += build_output(error["lint_message"], config)
46
-
47
- if config.statistics and config.lint:
48
- build_stats_output([x.get("lint_message") for x in file_errors], config)
49
-
50
- tense_message = (
51
- build_quantity(format_error_count) + " would be"
52
- if config.check is True
53
- else build_quantity_tense(format_error_count)
54
- )
55
- reformat_success_message = f"{tense_message} updated."
56
-
57
- error_case = "error" if lint_error_count == 1 else "errors"
58
- lint_success_message += (
59
- f"Linted {file_quantity}, found {lint_error_count} {error_case}."
60
- )
61
-
62
- if print_blanks:
63
- echo()
64
-
65
- if (
66
- config.quiet is False
67
- and config.stdin is False
68
- and (config.reformat or config.check)
69
- ):
70
- reformat_success_color = (
71
- Fore.RED + Style.BRIGHT if (format_error_count) > 0 else Fore.BLUE
72
- )
73
- echo(f"{reformat_success_color}{reformat_success_message}{Style.RESET_ALL}")
74
-
75
- if config.lint and config.quiet is False:
76
- lint_success_color = (
77
- Fore.RED + Style.BRIGHT if (lint_error_count) > 0 else Fore.BLUE
78
- )
79
- echo(f"{lint_success_color}{lint_success_message}{Style.RESET_ALL}")
80
-
81
- if print_blanks:
82
- echo()
83
-
84
- return lint_error_count + format_error_count
85
-
86
-
87
- def build_relative_path(url: str, project_root: Path) -> str:
88
- """Get path relative to project."""
89
- url_path = Path(url)
90
- if project_root != url_path and project_root in url_path.parents:
91
- return str(url_path.relative_to(project_root.resolve()))
92
-
93
- return url
94
-
95
-
96
- def build_output(error: dict, config: Config) -> int:
97
- """Build output for file errors."""
98
- errors = sorted(
99
- list(error.values())[0], key=lambda x: tuple(map(int, x["line"].split(":")))
100
- )
101
-
102
- width, _ = shutil.get_terminal_size()
103
-
104
- if len(errors) == 0:
105
- return 0
106
-
107
- filename = build_relative_path(list(error.keys())[0], config.project_root.resolve())
108
-
109
- if "{filename}" not in config.linter_output_format and not config.stdin:
110
- echo(
111
- f"{Fore.GREEN}{Style.BRIGHT}\n{filename}\n{Style.DIM}"
112
- + "".join(["─" for x in range(1, width)])
113
- + Style.RESET_ALL
114
- )
115
-
116
- for message_dict in errors:
117
- line = Fore.BLUE + message_dict["line"] + Style.RESET_ALL
118
- code = (
119
- (Fore.RED if message_dict["code"][:1] == "E" else Fore.YELLOW)
120
- + message_dict["code"]
121
- + Style.RESET_ALL
122
- )
123
- message = message_dict["message"]
124
- match = (
125
- Fore.BLUE
126
- + re.sub(r"\s{2,}|\n", " ", message_dict["match"])
127
- + Style.RESET_ALL
128
- )
129
-
130
- echo(
131
- config.linter_output_format.format(
132
- filename=filename, line=line, code=code, message=message, match=match
133
- ),
134
- err=False,
135
- )
136
-
137
- return len(errors)
138
-
139
-
140
- def build_check_output(errors: dict, config: Config) -> int:
141
- """Build output for reformat check."""
142
- if len(errors) == 0:
143
- return 0
144
-
145
- color = {"-": Fore.YELLOW, "+": Fore.GREEN, "@": Style.BRIGHT + Fore.BLUE}
146
- width, _ = shutil.get_terminal_size()
147
-
148
- if config.quiet is False and len(list(errors.values())[0]) > 0:
149
- echo(
150
- Fore.GREEN
151
- + Style.BRIGHT
152
- + "\n"
153
- + build_relative_path(list(errors.keys())[0], config.project_root.resolve())
154
- + "\n"
155
- + Style.DIM
156
- + "".join(["─" for x in range(1, width)])
157
- + Style.RESET_ALL
158
- )
159
-
160
- for diff in list(errors.values())[0][2:]:
161
- echo(
162
- f"{ color.get(diff[:1], Style.RESET_ALL)}{diff}{Style.RESET_ALL}",
163
- err=False,
164
- )
165
-
166
- return len(list(filter(lambda x: len(x) > 0, errors.values())))
167
-
168
-
169
- def build_quantity(size: int) -> str:
170
- """Count files in a list."""
171
- return str(size) + " file" + ("s" if size > 1 or size == 0 else "")
172
-
173
-
174
- def build_quantity_tense(size: int) -> str:
175
- """Count files in a list."""
176
- return (
177
- str(size)
178
- + " file"
179
- + ("s" if size > 1 or size == 0 else "")
180
- + " "
181
- + ("were" if size > 1 or size == 0 else "was")
182
- )
183
-
184
-
185
- def build_stats_output(errors: List[Optional[Any]], config: Config) -> int:
186
- """Build output for linter statistics."""
187
- if len(errors) == 0:
188
- return 0
189
-
190
- codes = []
191
- for error in errors:
192
- if error:
193
- for code in list(error.values())[0]:
194
- codes.append(code["code"])
195
-
196
- messages = {
197
- rule["rule"]["name"]: rule["rule"]["message"] for rule in config.linter_rules
198
- }
199
-
200
- echo()
201
- width, _ = shutil.get_terminal_size()
202
- echo(
203
- f"{Fore.GREEN}{Style.BRIGHT}Statistics{Style.RESET_ALL}\n{Style.DIM}{'─' * width}{Style.RESET_ALL}"
204
- )
205
-
206
- if messages and codes:
207
- longest_code = len(max(messages.keys(), key=len))
208
- longest_count = len(
209
- str(max(Counter(codes).values(), key=lambda x: len(str(x))))
210
- )
211
-
212
- for code in sorted(Counter(codes).items()):
213
- code_space = (longest_code - len(str(code[0]))) * " "
214
- count_space = (longest_count - len(str(code[1]))) * " "
215
-
216
- echo(
217
- f"{Fore.YELLOW}{code[0]}{Fore.BLUE} {code_space}{code[1]}{Style.RESET_ALL} {count_space}{messages[code[0]]}"
218
- )
219
-
220
- return sum(Counter(codes).values())