From 770c70dd5587c032a434b1cceb49e3ae6a5bf727 Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Tue, 26 Nov 2024 09:27:40 -0600 Subject: [PATCH 1/2] Changed the documentation generator from Sphinx to MkDocs. --- .gitignore | 1 - .pre-commit-config.yaml | 2 +- README.md | 5 +- docs/assets/css/cards.css | 200 ++++++++++++++++++ docs/assets/css/extra.css | 54 +++++ docs/assets/css/field-list.css | 34 +++ docs/assets/css/mkdocstrings.css | 39 ++++ docs/assets/favicon.png | Bin 0 -> 3499 bytes docs/assets/images/.gitkeep | 0 docs/assets/logo.svg | 1 + docs/gen_doc_stubs.py | 39 ++++ {docsrc => docs/howtos}/configuration.md | 2 +- .../howtos}/conventional-commits.md | 6 +- .../index.md => docs/howtos/recipes.md | 6 +- {docsrc => docs/howtos}/release-hinting.md | 2 +- {docsrc => docs/howtos}/releasing.md | 0 docs/index.md | 9 + docs/installation.md | 16 ++ docs/quickstart.md | 23 ++ .../reference}/actions/file_processing.md | 0 {docsrc => docs/reference}/actions/index.md | 11 +- .../reference}/actions/metadata.md | 0 {docsrc => docs/reference}/actions/shell.md | 0 .../reference}/actions/text_processing.md | 0 docs/reference/cli.md | 6 + .../reference}/templating/commit-context.md | 18 +- .../reference}/templating/templates.md | 29 ++- docs/tutorials/index.md | 22 ++ docsrc/Makefile | 20 -- docsrc/_static/css/custom.css | 11 - docsrc/_templates/autosummary/base.rst | 9 - docsrc/_templates/autosummary/class.rst | 11 - docsrc/_templates/autosummary/module.rst | 72 ------- docsrc/api.rst | 22 -- docsrc/changelog.md | 2 - docsrc/cli.rst | 3 - docsrc/conf.py | 114 ---------- docsrc/contributing.md | 2 - docsrc/index.md | 36 ---- docsrc/make.bat | 36 ---- docsrc/readme.md | 2 - docsrc/templating/index.md | 12 -- generate_changelog/pipeline.py | 2 +- mkdocs.yml | 106 ++++++++++ .../python/material/docstring/attributes.html | 90 ++++++++ .../python/material/docstring/parameters.html | 98 +++++++++ .../python/material/docstring/raises.html | 72 +++++++ .../python/material/docstring/returns.html | 94 ++++++++ overrides/partials/comments.html | 37 ++++ pyproject.toml | 24 ++- tools/drawioexport.py | 132 ++++++++++++ tools/update_frontmatter.py | 77 +++++++ 52 files changed, 1207 insertions(+), 402 deletions(-) create mode 100644 docs/assets/css/cards.css create mode 100644 docs/assets/css/extra.css create mode 100644 docs/assets/css/field-list.css create mode 100644 docs/assets/css/mkdocstrings.css create mode 100644 docs/assets/favicon.png create mode 100644 docs/assets/images/.gitkeep create mode 100644 docs/assets/logo.svg create mode 100644 docs/gen_doc_stubs.py rename {docsrc => docs/howtos}/configuration.md (97%) rename {docsrc/recipes => docs/howtos}/conventional-commits.md (73%) rename docsrc/recipes/index.md => docs/howtos/recipes.md (91%) rename {docsrc => docs/howtos}/release-hinting.md (93%) rename {docsrc => docs/howtos}/releasing.md (100%) create mode 100644 docs/index.md create mode 100644 docs/installation.md create mode 100644 docs/quickstart.md rename {docsrc => docs/reference}/actions/file_processing.md (100%) rename {docsrc => docs/reference}/actions/index.md (95%) rename {docsrc => docs/reference}/actions/metadata.md (100%) rename {docsrc => docs/reference}/actions/shell.md (100%) rename {docsrc => docs/reference}/actions/text_processing.md (100%) create mode 100644 docs/reference/cli.md rename {docsrc => docs/reference}/templating/commit-context.md (63%) rename {docsrc => docs/reference}/templating/templates.md (73%) create mode 100644 docs/tutorials/index.md delete mode 100644 docsrc/Makefile delete mode 100644 docsrc/_static/css/custom.css delete mode 100644 docsrc/_templates/autosummary/base.rst delete mode 100644 docsrc/_templates/autosummary/class.rst delete mode 100644 docsrc/_templates/autosummary/module.rst delete mode 100644 docsrc/api.rst delete mode 100644 docsrc/changelog.md delete mode 100644 docsrc/cli.rst delete mode 100644 docsrc/conf.py delete mode 100644 docsrc/contributing.md delete mode 100644 docsrc/index.md delete mode 100644 docsrc/make.bat delete mode 100644 docsrc/readme.md delete mode 100644 docsrc/templating/index.md create mode 100644 mkdocs.yml create mode 100644 overrides/mkdocstrings/python/material/docstring/attributes.html create mode 100644 overrides/mkdocstrings/python/material/docstring/parameters.html create mode 100644 overrides/mkdocstrings/python/material/docstring/raises.html create mode 100644 overrides/mkdocstrings/python/material/docstring/returns.html create mode 100644 overrides/partials/comments.html create mode 100644 tools/drawioexport.py create mode 100755 tools/update_frontmatter.py diff --git a/.gitignore b/.gitignore index c0c9ae0..b354cee 100644 --- a/.gitignore +++ b/.gitignore @@ -167,4 +167,3 @@ site-packages reports docsrc/_autosummary/ /docsrc/_build/ -/docs/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7c1f9bf..215cc9d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: - id: check-symlinks - id: check-toml - id: check-yaml - exclude: test.* + exclude: test.*|mkdocs.yml args: [--allow-multiple-documents] - id: debug-statements - id: end-of-file-fixer diff --git a/README.md b/README.md index e28355d..b9ff98c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Use your commit log to make a beautiful changelog file. - [Documentation](https://callowayproject.github.io/generate-changelog/) - [GitHub](https://github.com/callowayproject/generate-changelog) + + `generate-changelog` does what it says: it generates a full changelog, or updates an existing one. Git tags and commits are the inputs by which `generate-changelog` performs its task. The primary goal of this tool was to provide the benefits of [conventional commits](https://www.conventionalcommits.org/) without requiring a strict syntax. `generate-changelog` accomplishes this using configurable regular expressions or commit metadata matching. The thought is natural language is easier for developers to remember and requires less tooling to enforce. @@ -44,7 +46,7 @@ The primary goal of this tool was to provide the benefits of [conventional commi ## Requirements -Python 3.7 or higher. +Python 3.9 or higher. ## Installation @@ -67,3 +69,4 @@ Generate your changelog via: ```bash $ generate-changelog ``` + diff --git a/docs/assets/css/cards.css b/docs/assets/css/cards.css new file mode 100644 index 0000000..95d2e5c --- /dev/null +++ b/docs/assets/css/cards.css @@ -0,0 +1,200 @@ +/************* + Grid Modification +*/ + +.md-typeset .grid.wide-gap { + gap: 1rem; +} + +/************* + Cards +*/ +.card-container { + background-color: white; + color: rgba(0, 0, 0, 0.87); + border-radius: 4px; + box-shadow: rgba(0, 0, 0, 0.2) 0 2px 1px -1px, rgba(0, 0, 0, 0.14) 0 1px 1px 0, rgba(0, 0, 0, 0.12) 0 1px 3px 0; + overflow: hidden; +} + +.card-container.depth-0 { + box-shadow: none; +} + +/************* + Cards - Header +*/ + +.card-header { + padding: 16px 16px 24px; + background: var(--md-primary-fg-color); + color: var(--md-primary-bg-color); +} + +.card-header.backstage-green { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1368' height='401' x='0' y='0' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M437 116C223 116 112 0 112 0h1256v400c-82 0-225-21-282-109-112-175-436-175-649-175z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1368 400V282C891-29 788 40 711 161 608 324 121 372 0 361v39h1368z'/%3e%3cpath fill='url(%23paint2_linear)' d='M1368 244v156H0V94c92-24 198-46 375 0l135 41c176 51 195 109 858 109z'/%3e%3cpath fill='url(%23paint3_linear)' d='M1252 400h116c-14-7-35-14-116-16-663-14-837-128-1013-258l-85-61C98 28 46 8 0 0v400h1252z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M-172-98h1671v601H-172z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='602' x2='1093.5' y1='-960.5' y2='272' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='482' x2='480' y1='1058.5' y2='70.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='424' x2='446.1' y1='-587.5' y2='274.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='587' x2='349' y1='-1120.5' y2='341' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e"), linear-gradient(90deg, rgb(0, 91, 75), rgb(0, 91, 75)); + color: rgb(255, 255, 255); +} + +.card-header.backstage-blue { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='1368' height='400' fill='none'%3e%3cmask id='a' width='1368' height='401' x='0' y='0' maskUnits='userSpaceOnUse'%3e%3cpath fill='url(%23paint0_linear)' d='M437 116C223 116 112 0 112 0h1256v400c-82 0-225-21-282-109-112-175-436-175-649-175z'/%3e%3cpath fill='url(%23paint1_linear)' d='M1368 400V282C891-29 788 40 711 161 608 324 121 372 0 361v39h1368z'/%3e%3cpath fill='url(%23paint2_linear)' d='M1368 244v156H0V94c92-24 198-46 375 0l135 41c176 51 195 109 858 109z'/%3e%3cpath fill='url(%23paint3_linear)' d='M1252 400h116c-14-7-35-14-116-16-663-14-837-128-1013-258l-85-61C98 28 46 8 0 0v400h1252z'/%3e%3c/mask%3e%3cg mask='url(%23a)'%3e%3cpath fill='white' d='M-172-98h1671v601H-172z'/%3e%3c/g%3e%3cdefs%3e%3clinearGradient id='paint0_linear' x1='602' x2='1093.5' y1='-960.5' y2='272' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint1_linear' x1='482' x2='480' y1='1058.5' y2='70.5' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint2_linear' x1='424' x2='446.1' y1='-587.5' y2='274.6' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient id='paint3_linear' x1='587' x2='349' y1='-1120.5' y2='341' gradientUnits='userSpaceOnUse'%3e%3cstop stop-color='white'/%3e%3cstop offset='1' stop-color='white' stop-opacity='0'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e"), linear-gradient(90deg, rgb(0, 109, 143), rgb(0, 73, 161)); + color: rgb(255, 255, 255); +} + +.card-header p.subtitle { + margin: 0; + font-size: 0.8em; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: 500; + line-height: 1.57; +} + +.card-header p.title { + margin: 0; + font-size: 1.14em; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: 700; + line-height: 1.6; + margin-bottom: 2px; +} + +/************* + Cards - Media +*/ + +.card-media { + display: block; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + width: 100%; + object-fit: cover; +} + +.card-media p { + margin: 0; +} + +/************* + Cards - Content +*/ + +.card-content { + padding: 16px; +} + +.card-content p { + margin: 0; +} + +.card-content p + p { + margin-top: 1em; +} + +.card-content-title { + margin-top: 0; + font-weight: 400; + font-size: 1.5rem; + line-height: 1.334; + letter-spacing: 0; + margin-bottom: 0.35em; +} + +.card-content-title p { + margin: 0; +} + +/************* + Cards - Actions +*/ + +.card-actions { + padding: 16px; +} + +.card-actions ul:not([hidden]) { + display: flex; + margin: 0; +} + +.card-actions ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-wrap: wrap; + gap: 16px; +} +.card-actions.right ul { + justify-content: flex-end; +} + +.card-actions p { + margin: 0; +} + +[dir=ltr] .card-actions ul li { + margin: 0; +} + +.card-actions a { + background-color: transparent; + margin-top: 0; + vertical-align: middle; + font-weight: 500; + font-size: 0.8125rem; + line-height: 1.75; + letter-spacing: 0.02857em; + text-transform: uppercase; +} + +/************* + Cards - Tags +*/ + +.card-tags { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + padding: 16px; +} + +.card-tags ul:not([hidden]) { + display: flex; + margin: 0; +} + +.card-tags ul { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-wrap: wrap; + gap: 16px; +} + +[dir=ltr] .card-tags ul li { + padding: 2px 8px; + margin: 0; + box-sizing: border-box; + font-size: 12px; + font-weight: 500; + color: #000; + background-color: rgba(0, 0, 0, 0.12); + border-radius: 16px; + height: 24px; + line-height: 20px; +} + +/************* + Cards - Divider +*/ + +.card-divider { + margin: 0; + padding: 0 16px; +} + +.card-divider hr { + margin: 0; +} diff --git a/docs/assets/css/extra.css b/docs/assets/css/extra.css new file mode 100644 index 0000000..51a8e5b --- /dev/null +++ b/docs/assets/css/extra.css @@ -0,0 +1,54 @@ +/* Indentation. */ +div.doc-contents:not(.first) { + padding-left: 25px; + border-left: .05rem solid var(--md-typeset-table-color); +} + +/* Normal size fonts on parameter tables */ +.md-typeset div.doc-contents table { + font-size: 1em; + width: 100%; + display: table; +} + +/* Mark external links as such. */ +a.autorefs-external::after { + /* https://primer.style/octicons/arrow-up-right-24 */ + background-image: url('data:image/svg+xml,'); + content: ' '; + + display: inline-block; + vertical-align: middle; + position: relative; + bottom: 0.1em; + margin-left: 0.2em; + margin-right: 0.1em; + + height: 0.7em; + width: 0.7em; + border-radius: 100%; + background-color: var(--md-typeset-a-color); +} +a.autorefs-external:hover::after { + background-color: var(--md-accent-fg-color); +} +span.doc-param-annotation:first-child{ + border-top: 1px solid var(--md-typeset-table-color); + padding-top: 5px; + margin-top: 5px; + margin-bottom: -5px; +} +span.doc-param-annotation { + font-size: 0.8em; + display: block; +} +span.doc-param-default { + font-size: 0.8em; + float: unset; +} +.doc-label { border-radius: 15px; padding: 0 5px; } +.doc-label code { background-color: transparent; color: white;} +.doc-label-special { background-color: blue; color: white; } +.doc-label-private { background-color: red; color: white; } +.doc-label-property { background-color: green; color: white; } +.doc-label-read-only { background-color: yellow; color: black; } diff --git a/docs/assets/css/field-list.css b/docs/assets/css/field-list.css new file mode 100644 index 0000000..ace471b --- /dev/null +++ b/docs/assets/css/field-list.css @@ -0,0 +1,34 @@ +dl.field-list .doc-param-default, dl.doc-field-list .doc-param-default { + float: none; +} + +.field-list > dl, dl.field-list, dl.doc-field-list { + display: flex; + flex-flow: row wrap; + padding-left: 10px; +} + +.field-list > dl > dt, dl.field-list > dt, dl.doc-field-list > dt { + flex-basis: 20%; + font-weight: bold; + word-break: break-word; + padding: 10px 0; + border-bottom: 1px solid #e5e5e5; +} + +.field-list > dl > dt:after, dl.field-list > dt:after { + content: ":"; +} + +[dir=ltr] .field-list > dl > dd, dl.field-list > dd.doc-field-def, dl.doc-field-list > dd.doc-field-def { + flex-basis: 70%; + flex-grow: 1; + margin: 0; + padding: 10px 0 10px 10px; + border-bottom: 1px solid #e5e5e5; +} + +dd.doc-field-def > p:last-child { + padding-bottom: 0; + margin-bottom: 0; +} diff --git a/docs/assets/css/mkdocstrings.css b/docs/assets/css/mkdocstrings.css new file mode 100644 index 0000000..6288f53 --- /dev/null +++ b/docs/assets/css/mkdocstrings.css @@ -0,0 +1,39 @@ +/* Indentation. */ +div.doc-contents:not(.first) { + padding-left: 25px; + border-left: .05rem solid var(--md-typeset-table-color); +} + +/* Mark external links as such. */ +a.external::after, +a.autorefs-external::after { + /* https://primer.style/octicons/arrow-up-right-24 */ + mask-image: url('data:image/svg+xml,'); + -webkit-mask-image: url('data:image/svg+xml,'); + content: ' '; + + display: inline-block; + vertical-align: middle; + position: relative; + + height: 1em; + width: 1em; + background-color: var(--md-typeset-a-color); +} + +a.external:hover::after, +a.autorefs-external:hover::after { + background-color: var(--md-accent-fg-color); +} + +.doc-param-key, .doc-field-term, .doc-section-head { + font-weight: bold; +} + +.doc.doc-heading { + text-transform: none; +} + +h5.doc-heading, h6.doc-heading { + font-size: 1em; +} diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c7391588b8cfa6fd3bd0087321e2d32b043fb7e8 GIT binary patch literal 3499 zcmai1d0diN7k&lTKrL<8ilNj}5d<|PaW^&B&|I>aBn8Cb)lrr~mOU=E$S8HmTX1?!_7r6I1=eg%R=brQaNOX3zmS47h82|wC zwl7{NMZU&aB74lkGq;s9V|!ef$s0x2BC z0g4}uPDGAWR3i~IUn0_7-vQ&mw4nIYY{FR-mvBc{pYT8*Ltmtc@iHSG0VD{faL5Q= za1fnM;1Q8ayae#~;x-zISTf-R5|JJb&Ik(zi-OSC(bvHsjh7*eSiV#O$#UmsXK+PC z`g1r;0va6}8mbeD(_ygu(7J|(hG+~Hjm4rs3luwy&LQ(qboS;&iccJt6t)kG#^lf# zbi^Vj`2d5?%={-~2Z#S{9vu8l8f=bL2q?s7QNM}l&jZ-5VN42|L}4?y zEFX$h2!+nsyrjgUE(B*9j}qizNeiaX*`T^aq#pinpy$7U7K|VU%LTkt6e3c0$!AeH zf^9I_kK#`A<@kT$`nqpVq5J(ESd1))yI9&ibQ+io_A8giSB!|Xg&M*YnIy65zg@wQ(usV8RUw*?G>Q4a~|2;qS=jhOjUH4~rM(FPnFj_MBOPhjz zpZ37^2j>X-%OC+4Uq%sy4$dDIIB1@!Ee`|$i5MDKn(s;i09#YJsgJcRcdx87p(fl< zI6x+kH5Z#7OE`{AKazb`x8d5O9KWdZVO^6Q_Sr!vhE}Q>M4_f(&ol!I6EZGeNt6#4 zjX$;Nc_||1&s9$44incHja@GCYOO5jeMi++B2jyLPW-NMXL=N8>fEaB!wJybWff6T z*pS%%%JE7=?}xJ4!n1{Dd-6sTsF`7}55DdT=wR~f%B>!rx2x5t{jq4D^Yr~DWgQd4 z+>n{OWZXtr+&Nnh+mCPVq1&)UI@)NB0zcUAk0Wz`nNGi*MN1rd6YOy>VYxXuR<{=3 zTvyx}$5B3O?dDoPvLMR$wPNXK$tPuMr>k51sH#0lKkfG!WI_57ls_u z#*+;IFy+NZ0?5u?3ji`JY%R@P{rN*#(ZzfAtg17aGQO84VXoVB<2d3vP7i9XJia=U z+@koiLq%+@svn$ZGx9#(;N*uU-;>FuMJD#I?#c0_M;U^U<5z9sLHo)(LrH z)k+cY9#X;oQFv3_s1nQyN+^;qHg=Tm8Q}Hcztwa9IDBxzIp1*GU$5m$Xwv1+|L(8ofUkp(6RD8+tyx3SI6P2fgl36X|r*I2vO7z$i4^{KNo|Fu2m-35hy?j*@`m`m3 zA9|s0SloyL-_x>#T~4W$5=_Z*EWY&Ax(zcKC9j2dUF)YLIxnmn%{ckItxie2JJMKc z`u61YGiGz?0w*FGqTV+S6Sg;Ryg!?HF8tNayD8P3btYz{@a?Ob ztOfnx3jPzN7HL_Ls^o8^(<5G+I@8Odu~561>$7(Z@Z)uy&4XQq!eipb!6CtrVog>Z zziy(}My%yIr!IZg>A5oQ6b}04jYy0Bp<;{N`DP`mXP5;e%a=Jqg{ZKE^egz+e|mI9ZeBE;!EBRO-Fs;~YQ6+%++#z3@&* zxzKrOGD=H{05m?Clk5mH$_cO9Y8P*mmayen(UcR(bG&83_%0DNQ(zDnt_TA1p z#_mqmqS^9QVK3@Zw?}V$gPnq?e7UOO zKUFs{DQ9C5Zu#T75%eCQhiZg%Sx(bVbX! zJvXNnqB1)2^cp=kxkJV$rq0FU0$mJiE(xEC8yyF`@NbK=VtJReVsY0fh)7M$rs>rs z`v%A=X>WtPn{QWS5r?!1gq;9d!mF>Jcu~4h`f8JL`w`Z`#o$+Z6xC8{vglw5u#t8- zsrUtlN$2f|Uk^w!aib5z!>*$;M3zb?|09eT6m%%?-rctLcKk&su=xqz6QG! z<8@%7pc{vqxAP-8+^ahkZYm;E2TIEtTwiOeeOPx9S7{*}iCHCV;c%0!YJ1PVxo-ZV z(VCUEIl=DZzRH6EspY%#v0?@BMX++-utIcmO9jLOHUSEellBPeBj9zngy-!)6G0qZ zF1EN`{&?1(FC$2=JfwZRDZpNXM9n&OsKuS~gW_zFUQmalnntE_ZW!soPwfXqJXsJ60uXhQl*2g$>3O8z)=td!_1IJ-^Yj%UU2`35;ngs^|Qq73y?>3=GEM zaHVP2u%@e`R`QM{O_gil+2g>yI>gQttA^wXK{xAEgNEjV&VUa&6N9EyqX+SdKxsB= zzD+CWkwuX~jfJrG@?q2hm5IQQhr}72;adwHDVD6fCMPmVKf#Oru9#tUpqsXbBRd_$?CE!#(AOLefliUO4OdCcuk~~*Q~O1N9BHKZT(})#dtDqX z9xvM?pkkcE76N=Pws5nF^(A|yg4X({du=-R1O4gl4OJs%1E-?>`BQSfGeX^sW1ai2 zwtU$0R=CTUIS-So(~wxxr(aU^*w~k9cO|1gu&Gg_sJ~vL$P<;!mF<%lhKt~P51%=a z@^iYN{-DmN?#01NWz%S-^F*l$_z~svRu%c4b diff --git a/docs/gen_doc_stubs.py b/docs/gen_doc_stubs.py new file mode 100644 index 0000000..056bf79 --- /dev/null +++ b/docs/gen_doc_stubs.py @@ -0,0 +1,39 @@ +"""Generate documentation stubs.""" + +from pathlib import Path + +import mkdocs_gen_files + +package_name = "generate_changelog" + +nav = mkdocs_gen_files.Nav() +mod_symbol = '' + +src_root = Path(__file__).parent.parent +package_root = src_root / package_name + + +for path in sorted(package_root.rglob("*.py")): + module_path = path.relative_to(src_root).with_suffix("") + doc_path = path.relative_to(src_root).with_suffix(".md") + full_doc_path = Path("reference/api", doc_path) + + parts = tuple(module_path.parts) + + if parts[-1] == "__init__": + parts = parts[:-1] + doc_path = doc_path.with_name("index.md") + full_doc_path = full_doc_path.with_name("index.md") + elif parts[-1].startswith("_"): + continue + + nav[parts] = doc_path.as_posix() + + with mkdocs_gen_files.open(full_doc_path, "w") as fd: + ident = ".".join(parts) + fd.write(f"::: {ident}") + + mkdocs_gen_files.set_edit_path(full_doc_path, path) + +with mkdocs_gen_files.open("reference/api/SUMMARY.md", "w") as nav_file: + nav_file.writelines(nav.build_literate_nav()) diff --git a/docsrc/configuration.md b/docs/howtos/configuration.md similarity index 97% rename from docsrc/configuration.md rename to docs/howtos/configuration.md index 120a51d..c156567 100644 --- a/docsrc/configuration.md +++ b/docs/howtos/configuration.md @@ -155,7 +155,7 @@ Some values accept pipelines, which are a chain of actions that transform an inp :YAML type: [`sequence` of `str`](https://yaml.org/spec/1.2.2/#21-collections) :Description: - Group the commits within a version by these commit attributes. Valid values are any attributes of a [Commit Context](templating/commit-context.md). Use dot notation to specify dictionary keys, object attributes or sequence indexes. For example, `authors.0.name` references the first author's `name` key in the `authors` list. + Group the commits within a version by these commit attributes. Valid values are any attributes of a [Commit Context](../reference/templating/commit-context.md). Use dot notation to specify dictionary keys, object attributes or sequence indexes. For example, `authors.0.name` references the first author's `name` key in the `authors` list. :Default: diff --git a/docsrc/recipes/conventional-commits.md b/docs/howtos/conventional-commits.md similarity index 73% rename from docsrc/recipes/conventional-commits.md rename to docs/howtos/conventional-commits.md index 46b514b..7b4430f 100644 --- a/docsrc/recipes/conventional-commits.md +++ b/docs/howtos/conventional-commits.md @@ -2,7 +2,7 @@ ## Configuration -Add the {class}`~.actions.metadata.ParseConventionalCommit` action to the `summary_pipeline` configuration. +Add the [`ParseConventionalCommit`][generate_changelog.actions.metadata.ParseConventionalCommit] action to the `summary_pipeline` configuration. ```{literalinclude} ../../test/fixtures/conventional-commit.yaml :language: yaml @@ -10,7 +10,7 @@ Add the {class}`~.actions.metadata.ParseConventionalCommit` action to the `summa :emphasize-lines: 9-12 ``` -Add the {class}`~.actions.metadata.ParseBreakingChangeFooter` action to the `body_pipeline` configuration. +Add the [`ParseBreakingChangeFooter`][generate_changelog.actions.metadata.ParseBreakingChangeFooter] action to the `body_pipeline` configuration. ```{literalinclude} ../../test/fixtures/conventional-commit.yaml :language: yaml @@ -18,7 +18,7 @@ Add the {class}`~.actions.metadata.ParseBreakingChangeFooter` action to the `bod :emphasize-lines: 2-5 ``` -Update the `group_by` configuration. This example orders it by the category (set by the [`commit_classifiers`](configuration-commit_classifiers)) and then by the first scope, if it exists. +Update the `group_by` configuration. This example orders it by the category (set by the [`commit_classifiers`][generate_changelog.configuration.Configuration.commit_classifiers) and then by the first scope, if it exists. ```{literalinclude} ../../test/fixtures/conventional-commit.yaml :language: yaml diff --git a/docsrc/recipes/index.md b/docs/howtos/recipes.md similarity index 91% rename from docsrc/recipes/index.md rename to docs/howtos/recipes.md index 469a00f..7614a99 100644 --- a/docsrc/recipes/index.md +++ b/docs/howtos/recipes.md @@ -62,14 +62,14 @@ output_pipeline: With a bit of configuration and custom templating, you can provide a link to each commit and a diff between versions on your git repository. -Add the link to your repository as a [configuration variable](configuration-variables): +Add the link to your repository as a [`configuration variable`][generate_changelog.configuration.Configuration.variables]: ```yaml variables: repo_url: https://github.com/coordt/generate-changelog ``` -Then create a `version_heading.md.jinja` file in `.github/changelog_templates/` or other [configured template directory](configuration-template_dirs). Its contents should be similar to the following: +Then create a `version_heading.md.jinja` file in `.github/changelog_templates/` or other [`configured template directory`][generate_changelog.configuration.Configuration.template_dirs]. Its contents should be similar to the following: ```jinja ## {{ version.label }} ({{ version.date_time.strftime("%Y-%m-%d") }}) @@ -83,7 +83,7 @@ If you use this pattern and generate the changelog before tagging the commit, th You will need to either manually change this or use an automated method such as [bump2version](https://github.com/c4urself/bump2version). [See below for more information.](#incremental-changelog-with-bump2version) ``` -For showing a specific commit link, create a `commit.md.jinja` file in `.github/changelog_templates/ or other [configured template directory](configuration-template_dirs). Its contents should include something like +For showing a specific commit link, create a `commit.md.jinja` file in `.github/changelog_templates/` or other [`configured template directory`][generate_changelog.configuration.Configuration.template_dirs]. Its contents should include something like ```jinja [{{ commit.short_sha }}]({{ repo_url }}/commit/{{ commit.sha }}) ``` diff --git a/docsrc/release-hinting.md b/docs/howtos/release-hinting.md similarity index 93% rename from docsrc/release-hinting.md rename to docs/howtos/release-hinting.md index 0a70a49..3daae08 100644 --- a/docsrc/release-hinting.md +++ b/docs/howtos/release-hinting.md @@ -2,7 +2,7 @@ ## What is a "release hint?" -A release hint provides guidance on if and what type of software release is warranted. The guidance is based on user-defined rules applied to every {class}`~.context.CommitContext` in the unreleased {class}`~.VersionContext`. Each rule may use how the commit is grouped in the release, the files modified, or both. +A release hint provides guidance on if and what type of software release is warranted. The guidance is based on user-defined rules applied to every [`CommitContext`][generate_changelog.context.CommitContext] in the unreleased [`VersionContext`][generate_changelog.context.VersionContext]. Each rule may use how the commit is grouped in the release, the files modified, or both. You can use this release hint as input to your release tooling. diff --git a/docsrc/releasing.md b/docs/howtos/releasing.md similarity index 100% rename from docsrc/releasing.md rename to docs/howtos/releasing.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..faa7968 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,9 @@ +# Generate Changelog + +{% + include-markdown + "../README.md" + start="" + end="" + rewrite-relative-urls=false +%} diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..1014dda --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,16 @@ +--- +title: Installation +summary: How to install generate-changelog. +date: {% now 'local', '%Y-%m-%d' %} +--- + + +## Installing the Stable Release from PyPI + +To install generate-changelog, run this command in your terminal: + +``` console +$ pip install generate-changelog +``` + +This is the preferred method to install `generate-changelog`, as it will always install the most recent stable release. You can also replace `pip` with `pipx`. diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..cc46d9c --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,23 @@ +# Quickstart + +Getting started quickly with Generate Changelog. + +## Install + +```bash +$ pip install generate-changelog +``` + +## Generate a configuration file + +```bash +$ generate-changelog --generate-config +``` +This creates a file named `.changelog-config.yaml`. You can make changes to the default configuration. + + +## Generate your changelog + +```bash +$ generate-changelog +``` diff --git a/docsrc/actions/file_processing.md b/docs/reference/actions/file_processing.md similarity index 100% rename from docsrc/actions/file_processing.md rename to docs/reference/actions/file_processing.md diff --git a/docsrc/actions/index.md b/docs/reference/actions/index.md similarity index 95% rename from docsrc/actions/index.md rename to docs/reference/actions/index.md index ecb019f..cd86714 100644 --- a/docsrc/actions/index.md +++ b/docs/reference/actions/index.md @@ -1,15 +1,6 @@ # Actions and Pipelines -```{toctree} ---- -maxdepth: 2 -caption: Contents ---- -file_processing -metadata -shell -text_processing -``` + ## Introduction Pipelines and actions are modeled after continuous integration systems such as GitHub Actions and Azure Pipelines, but simplified. A pipeline is a list of actions and actions are functions. It is easy to provide and specify custom actions. diff --git a/docsrc/actions/metadata.md b/docs/reference/actions/metadata.md similarity index 100% rename from docsrc/actions/metadata.md rename to docs/reference/actions/metadata.md diff --git a/docsrc/actions/shell.md b/docs/reference/actions/shell.md similarity index 100% rename from docsrc/actions/shell.md rename to docs/reference/actions/shell.md diff --git a/docsrc/actions/text_processing.md b/docs/reference/actions/text_processing.md similarity index 100% rename from docsrc/actions/text_processing.md rename to docs/reference/actions/text_processing.md diff --git a/docs/reference/cli.md b/docs/reference/cli.md new file mode 100644 index 0000000..8308a5f --- /dev/null +++ b/docs/reference/cli.md @@ -0,0 +1,6 @@ +# CLI Reference + +::: mkdocs-click + :module: generate_changelog.cli + :command: cli + :prog_name: generate-changelog diff --git a/docsrc/templating/commit-context.md b/docs/reference/templating/commit-context.md similarity index 63% rename from docsrc/templating/commit-context.md rename to docs/reference/templating/commit-context.md index ba358fe..e40e86d 100644 --- a/docsrc/templating/commit-context.md +++ b/docs/reference/templating/commit-context.md @@ -10,18 +10,18 @@ This is the context structure for each commit in the templates | summary | `string` | The first line of the commit message. | | body | `string` | The commit message sans the first line. | | committer | `string` | The name and email of the committer as `name `. | -| authors | `list` of `dict` with `name` and `email` keys | A list of authors' names and emails related to the commit.

This will always contain the committer. If the {class}`~.ParseTrailers` Action was configured in the {attr}`~.Configuration.body_pipeline` (the default), this will also include names and emails of people included in the commit trailers as configured via {attr}`~.Configuration.valid_author_tokens`. | +| authors | `list` of `dict` with `name` and `email` keys | A list of authors' names and emails related to the commit.

This will always contain the committer. If the [`ParseTrailers`][generate_changelog.actions.metadata.ParseTrailers] Action was configured in the {attr}`~.Configuration.body_pipeline` (the default), this will also include names and emails of people included in the commit trailers as configured via {attr}`~.Configuration.valid_author_tokens`. | | author_names | `list` of `string` | A list of just author names, extracted from `authors`. | | grouping | `tuple` | The values to group this commit based on the {attr}`~.Configuration.group_by` configuration. | | metadata | `dict` | Metadata for this commit parsed from the commit message. Metadata is generated from Actions in a Pipeline. | ## Commit metadata -| Name | Type | Availability | Description | -|---------------------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| -| category | `string` |
  • {class}`~.SummaryRegexMatch`
  • {class}`~.MetadataMatch`
| This value is set using the first Action in the {attr}`~.Configuration.commit_classifiers` configuration that returns a value. | -| trailers | `dict` |
  • {class}`~.ParseTrailers`
| The git trailers parsed out of the commit body. | -| issue | `list` of `string` |
  • {class}`~.ParseIssue`
  • {class}`~.ParseGitHubIssue`
  • {class}`~.ParseJiraIssue`
  • {class}`~.ParseAzureBoardIssue`
| A list of issues parsed from the commit. | -| has_breaking_change | `boolean` |
  • {class}`~.ParseBreakingChangeFooter`
  • {class}`~.ParseConventionalCommit`
| Indicates this commit has a breaking change. It doesn't mean that there is a description of the breaking change. | -| breaking_changes | `string` |
  • {class}`~.ParseBreakingChangeFooter`
| Description of breaking changes as parsed from the commit body. | -| scope | `list` of `string` |
  • {class}`~.ParseConventionalCommit`
| Zero or more scopes parsed from the commit summary. | +| Name | Type | Availability | Description | +|---------------------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| +| category | `string` |
  • [`SummaryRegexMatch`][generate_changelog.actions.matching.SummaryRegexMatch]
  • [`MetadataMatch`][generate_changelog.actions.matching.MetadataMatch]
| This value is set using the first Action in the {attr}`~.Configuration.commit_classifiers` configuration that returns a value. | +| trailers | `dict` |
  • [`ParseTrailers`][generate_changelog.actions.metadata.ParseTrailers]
| The git trailers parsed out of the commit body. | +| issue | `list` of `string` |
  • [`ParseIssue`][generate_changelog.actions.metadata.ParseIssue]
  • [`ParseGitHubIssue`][generate_changelog.actions.metadata.ParseGitHubIssue]
  • [`ParseJiraIssue`][generate_changelog.actions.metadata.ParseJiraIssue]
  • [`ParseAzureBoardIssue`][generate_changelog.actions.metadata.ParseAzureBoardIssue]
| A list of issues parsed from the commit. | +| has_breaking_change | `boolean` |
  • [`ParseBreakingChangeFooter`][generate_changelog.actions.metadata.ParseBreakingChangeFooter]
  • [`ParseConventionalCommit`][generate_changelog.actions.metadata.ParseConventionalCommit]
| Indicates this commit has a breaking change. It doesn't mean that there is a description of the breaking change. | +| breaking_changes | `string` |
  • [`ParseBreakingChangeFooter`][generate_changelog.actions.metadata.ParseBreakingChangeFooter]
| Description of breaking changes as parsed from the commit body. | +| scope | `list` of `string` |
  • [`ParseConventionalCommit`][generate_changelog.actions.metadata.ParseConventionalCommit]
| Zero or more scopes parsed from the commit summary. | diff --git a/docsrc/templating/templates.md b/docs/reference/templating/templates.md similarity index 73% rename from docsrc/templating/templates.md rename to docs/reference/templating/templates.md index 86d2764..3925818 100644 --- a/docsrc/templating/templates.md +++ b/docs/reference/templating/templates.md @@ -2,7 +2,7 @@ The changelog is generated with over-ridable [Jinja templates](https://jinja.palletsprojects.com/en/3.1.x/). You don't have to override all the templates, simply the ones you want to. -You can configure where `generate-changelog` looks for [custom templates](generate_changelog.configuration.Configuration.template_dirs). +You can configure where `generate-changelog` looks for [`custom templates`][generate_changelog.configuration.Configuration.template_dirs]. The core of the changelog is the commit. The rest is just a grouping of the commits in a desired method. @@ -10,24 +10,27 @@ The core of the changelog is the commit. The rest is just a grouping of the comm The base template is rendered when generating the changelog from scratch. Incremental generations will only use the [heading](#headingmdjinja) and [versions](#versionsmdjinja) templates. -```{literalinclude} ../../generate_changelog/templates/base.md.jinja +```jinja title="base.md.jinja" +--8<-- "generate_changelog/templates/base.md.jinja" ``` ## heading.md.jinja The heading template is rendered for the title of the changelog. -```{literalinclude} ../../generate_changelog/templates/heading.md.jinja +```jinja title="heading.md.jinja" +--8<-- "generate_changelog/templates/heading.md.jinja" ``` ## versions.md.jinja -```{literalinclude} ../../generate_changelog/templates/versions.md.jinja +```jinja title="versions.md.jinja" +--8<-- "generate_changelog/templates/versions.md.jinja" ``` To understand how this template works, understanding how the commits are processed and grouped will help. -The commits are enriched with metadata and sorted by the version and grouping values. In this table you can see the commit version and the values of the {attr}`~.Configuration.group_by` configuration, sorted. +The commits are enriched with metadata and sorted by the version and grouping values. In this table you can see the commit version and the values of the [`group_by`][generate_changelog.configuration.Configuration.group_by] configuration, sorted. | version | committer, metadata.category | Commit | |:--------|:-----------------------------|:---------| @@ -42,7 +45,7 @@ The commits are enriched with metadata and sorted by the version and grouping va | 1.0.1 | Charly, Fixes | commit9 | | 1.0.1 | Charly, New | commit3 | -This is consolidated into the context that looks something like this (See the [VersionContext](version-context) for better information): +This is consolidated into the context that looks something like this (See the [VersionContext](version-context.md) for better information): ```python simplified_version_context = { @@ -60,7 +63,7 @@ simplified_version_context = { } ``` -The template looks for changes in the grouping values and renders [section headings](#section_headingmdjinja) for the new value. The result is somthing like: +The template looks for changes in the grouping values and renders [section headings](#section_headingmdjinja) for the new value. The result is something like: ```markdown ## 1.0.1 (2022-01-01) @@ -84,26 +87,30 @@ The template looks for changes in the grouping values and renders [section headi The version heading template is rendered for the title of each tagged version. -```{literalinclude} ../../generate_changelog/templates/version_heading.md.jinja +```jinja title="version_heading.md.jinja" +--8<-- "generate_changelog/templates/version_heading.md.jinja" ``` ## section_heading.md.jinja The section heading template is rendered for the value changes in the grouping. The heading level is adjusted based on the `level` parameter set in the `version_heading.md.jinja` template. -```{literalinclude} ../../generate_changelog/templates/section_heading.md.jinja +```jinja title="section_heading.md.jinja" +--8<-- "generate_changelog/templates/section_heading.md.jinja" ``` ## commit.md.jinja This template is rendered for each commit. -```{literalinclude} ../../generate_changelog/templates/commit.md.jinja +```jinja title="commit.md.jinja" +--8<-- "generate_changelog/templates/commit.md.jinja" ``` ## footer.md.jinja The default footer templaate is blank. You can override this to add your own information. -```{literalinclude} ../../generate_changelog/templates/footer.md.jinja +```jinja title="footer.md.jinja" +--8<-- "generate_changelog/templates/footer.md.jinja" ``` diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md new file mode 100644 index 0000000..5f0d118 --- /dev/null +++ b/docs/tutorials/index.md @@ -0,0 +1,22 @@ +--- +title: Tutorials +summary: Tutorials for how to use {{ cookiecutter.project_short_description }}. +date: {% now 'local', '%Y-%m-%d' %} +--- + +This page provides tutorials on how to use {{cookiecutter.project_name}}. + +!!! warning + + Tutorials not implemented yet! Tutorials are for learning how to use the package. + +Tutorials are lessons that take the reader by the hand through a series of steps to complete a project of some kind. Tutorials are **learning-oriented.** + +- Help newcomers with getting started +- Teach readers about your library by making them write code +- Inspire confidence through examples that work for everyone, repeatably +- Give readers an immediate sense of achievement +- Show concrete examples, no abstractions +- Provide the minimum necessary explanation +- Avoid any distractions +- [More information](https://diataxis.fr/tutorials/) diff --git a/docsrc/Makefile b/docsrc/Makefile deleted file mode 100644 index ffce752..0000000 --- a/docsrc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = python -msphinx -SPHINXPROJ = generate_changelog -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docsrc/_static/css/custom.css b/docsrc/_static/css/custom.css deleted file mode 100644 index e201094..0000000 --- a/docsrc/_static/css/custom.css +++ /dev/null @@ -1,11 +0,0 @@ -.py .sig-prename.descclassname { - display: none; -} -.subheading { - line-height: 1.25; - margin-bottom: 0; - color: #646776; -} -.subheading + section > h1 { - margin-top: 0; -} diff --git a/docsrc/_templates/autosummary/base.rst b/docsrc/_templates/autosummary/base.rst deleted file mode 100644 index 3a6f25c..0000000 --- a/docsrc/_templates/autosummary/base.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. rst-class:: subheading - -{{ fullname }} - -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. auto{{ objtype }}:: {{ objname }} diff --git a/docsrc/_templates/autosummary/class.rst b/docsrc/_templates/autosummary/class.rst deleted file mode 100644 index f01446b..0000000 --- a/docsrc/_templates/autosummary/class.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. rst-class:: subheading - -{{ fullname }} - -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :members: - :undoc-members: diff --git a/docsrc/_templates/autosummary/module.rst b/docsrc/_templates/autosummary/module.rst deleted file mode 100644 index db11e37..0000000 --- a/docsrc/_templates/autosummary/module.rst +++ /dev/null @@ -1,72 +0,0 @@ -.. rst-class:: subheading - -{{ fullname }} - -{{ name | escape | underline}} - -.. currentmodule:: {{ fullname }} - -.. automodule:: {{ fullname }} - {% block attributes %} - {% if attributes %} - .. rubric:: Attributes - - .. autosummary:: - :nosignatures: - {% for item in attributes %} - {{ item }} - {%- endfor %} - {% endif %} - {% endblock %} - - {% block functions %} - {% if functions %} - .. rubric:: Functions - - .. autosummary:: - :nosignatures: - :toctree: {{ name }} - {% for item in functions %} - {{ item }} - {%- endfor %} - {% endif %} - {% endblock %} - - {% block classes %} - {% if classes %} - .. rubric:: Classes - - .. autosummary:: - :nosignatures: - :toctree: {{ name }} - {% for item in classes %} - {{ item }} - {%- endfor %} - {% endif %} - {% endblock %} - - {% block exceptions %} - {% if exceptions %} - .. rubric:: Exceptions - - .. autosummary:: - :nosignatures: - :toctree: {{ name }} - {% for item in exceptions %} - {{ item }} - {%- endfor %} - {% endif %} - {% endblock %} - {% block modules -%} - {% if modules %} - - .. rubric:: Modules - - .. autosummary:: - :toctree: {{ name }} - :recursive: - {% for item in modules %} - {{ item }} - {%- endfor %} - {% endif %} - {% endblock %} diff --git a/docsrc/api.rst b/docsrc/api.rst deleted file mode 100644 index 916a08e..0000000 --- a/docsrc/api.rst +++ /dev/null @@ -1,22 +0,0 @@ -API Reference -============= - -.. currentmodule:: generate_changelog - -.. autosummary:: - :toctree: _autosummary - :nosignatures: - :recursive: - - ~actions - ~cli - ~commits - ~configuration - ~context - ~data_merge - ~git_ops - ~pipeline - ~release_hint - ~templating - ~utilities - ~_attr_docs diff --git a/docsrc/changelog.md b/docsrc/changelog.md deleted file mode 100644 index 66efc0f..0000000 --- a/docsrc/changelog.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../CHANGELOG.md -``` diff --git a/docsrc/cli.rst b/docsrc/cli.rst deleted file mode 100644 index 579faca..0000000 --- a/docsrc/cli.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. click:: generate_changelog.cli:typer_click_object - :prog: generate-changelog - :nested: full diff --git a/docsrc/conf.py b/docsrc/conf.py deleted file mode 100644 index 8cce32d..0000000 --- a/docsrc/conf.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -Sphinx configuration. -""" - -import os -import sys -from datetime import date - -sys.path.insert(0, os.path.abspath("..")) - -import generate_changelog - -project = "generate-changelog" -copyright = f"{date.today():%Y}, Corey Oordt" -author = "Corey Oordt" - -version = generate_changelog.__version__ -release = generate_changelog.__version__ - -# -- General configuration --------------------------------------------- - -extensions = [ - "myst_parser", - "sphinx.ext.autodoc", - "sphinx.ext.viewcode", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.autosectionlabel", - "sphinx.ext.napoleon", - "sphinx_autodoc_typehints", - "sphinx.ext.coverage", - "sphinx.ext.githubpages", - "sphinx_click", -] - -autosectionlabel_prefix_document = True -autosectionlabel_maxdepth = 2 - -autodoc_default_flags = [ - # Make sure that any autodoc declarations show the right members - "members", - "undoc-members", - "private-members", -] -autodoc_class_signature = "separated" -autodoc_member_order = "bysource" -autodoc_typehints = "description" -autodoc_type_aliases = { - "StrOrCallable": "generate_changelog.configuration.StrOrCallable", - "IntOrCallable": "generate_changelog.configuration.IntOrCallable", -} - -autosummary_generate = True - -napoleon_attr_annotations = True -napoleon_include_special_with_doc = True -napoleon_include_private_with_doc = True -napoleon_include_init_with_doc = True -# napolean_use_param = True - -myst_enable_extensions = [ - "amsmath", - "colon_fence", - "deflist", - "dollarmath", - "linkify", - "replacements", - "smartquotes", - "substitution", - "tasklist", - "fieldlist", -] -myst_heading_anchors = 2 -intersphinx_mapping = { - "python": ("https://docs.python.org/3", None), - "gitpython": ("https://gitpython.readthedocs.io/en/stable/", None), -} - -templates_path = ["_templates"] -source_suffix = [".rst", ".md"] -master_doc = "index" -language = "en" -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] -pygments_style = "sphinx" -todo_include_todos = False - - -# -- Options for HTML output ------------------------------------------- - -html_theme = "furo" -html_static_path = ["_static"] -html_css_files = [ - "css/custom.css", -] -html_theme_options = { - "footer_icons": [ - { - "name": "GitHub", - "url": "https://github.com/coordt/generate-changelog", - "html": ( - '' - '' - ), - "class": "", - }, - ], -} -html_title = f"Generate Changelog {release}" diff --git a/docsrc/contributing.md b/docsrc/contributing.md deleted file mode 100644 index 78caf34..0000000 --- a/docsrc/contributing.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../CONTRIBUTING.md -``` diff --git a/docsrc/index.md b/docsrc/index.md deleted file mode 100644 index aeac630..0000000 --- a/docsrc/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -hide-toc: true ---- -# Generate Changelog - -```{include} ../README.md -:start-after: -``` - - -```{toctree} ---- -maxdepth: 2 -caption: Contents -hidden: true ---- -Introduction -how-it-works -Command Line Interface -release-hinting -configuration -templating/index -actions/index -recipes/index -recipes/conventional-commits -api -``` -```{toctree} ---- -caption: Development -hidden: true ---- -contributing -releasing -changelog -``` diff --git a/docsrc/make.bat b/docsrc/make.bat deleted file mode 100644 index 4ef7fdb..0000000 --- a/docsrc/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=python -msphinx -) -set SOURCEDIR=. -set BUILDDIR=_build -set SPHINXPROJ=clgen - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The Sphinx module was not found. Make sure you have Sphinx installed, - echo.then set the SPHINXBUILD environment variable to point to the full - echo.path of the 'sphinx-build' executable. Alternatively you may add the - echo.Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/docsrc/readme.md b/docsrc/readme.md deleted file mode 100644 index 451beda..0000000 --- a/docsrc/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../README.md -``` diff --git a/docsrc/templating/index.md b/docsrc/templating/index.md deleted file mode 100644 index 89e1ef7..0000000 --- a/docsrc/templating/index.md +++ /dev/null @@ -1,12 +0,0 @@ -# Templating - -```{toctree} ---- -maxdepth: 2 -caption: Contents ---- -templates -changelog-context -version-context -commit-context -``` diff --git a/generate_changelog/pipeline.py b/generate_changelog/pipeline.py index efa97b6..ed0419a 100644 --- a/generate_changelog/pipeline.py +++ b/generate_changelog/pipeline.py @@ -153,7 +153,7 @@ def pipeline_factory( action_list: list, commit_metadata_func: Optional[Callable] = None, version_metadata_func: Optional[Callable] = None, - **kwargs, + **kwargs: Any, ) -> Pipeline: """ Create a :py:class:`~Pipeline` from a list of actions specified by dictionaries. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..b218406 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,106 @@ +site_name: Generate Changelog +repo_url: https://github.com/callowayproject/generate-changelog +edit_uri: edit/main/docs/ +theme: + name: material + custom_dir: overrides + logo: assets/logo.svg + favicon: assets/favicon.png + features: + - navigation.sections + - navigation.path + - navigation.indexes + - navigation.top + - content.action.edit + - content.action.view + - content.code.annotate + - content.tabs.link + - toc.integrate + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/toggle-switch-off-outline + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/toggle-switch + name: Switch to light mode +use_directory_urls: true +markdown_extensions: + - abbr + - admonition + - attr_list + - customblocks + - def_list + - footnotes + - md_in_html + - mdx_truly_sane_lists + - mkdocs-click + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight + - pymdownx.snippets + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - smarty + - toc: + permalink: true + - tables + +plugins: + - search +# - git-revision-date-localized + - git-authors: + show_email_address: false + exclude: + - reference/api/* + - include-markdown + - gen-files: + scripts: + - docs/gen_doc_stubs.py + - literate-nav: + nav_file: SUMMARY.md + - mkdocstrings: + handlers: + python: + import: + - https://docs.python.org/3/objects.inv + options: + allow_inspection: true + docstring_style: google + docstring_options: + ignore_init_summary: true + docstring_section_style: spacy + enable_inventory: true + extensions: + - griffe_pydantic: + schema: true + group_by_category: true + members_order: alphabetical + merge_init_into_class: true + separate_signature: true + show_docstring_parameters: true + show_root_toc_entry: true + show_signature_annotations: true + show_source: false + show_symbol_type_heading: true + show_symbol_type_toc: true + show_category_heading: true + +extra_javascript: + - "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML" + +extra_css: + - assets/css/extra.css + - assets/css/mkdocstrings.css + - assets/css/cards.css + - assets/css/field-list.css diff --git a/overrides/mkdocstrings/python/material/docstring/attributes.html b/overrides/mkdocstrings/python/material/docstring/attributes.html new file mode 100644 index 0000000..ce50d65 --- /dev/null +++ b/overrides/mkdocstrings/python/material/docstring/attributes.html @@ -0,0 +1,90 @@ +{{ log.debug("Rendering attributes section") }} + +{% import "language.html" as lang with context %} + +{% if config.docstring_section_style == "table" %} + {% block table_style scoped %} +

{{ section.title or lang.t("Attributes:") }}

+ + + + + + + + + + {% for attribute in section.value %} + + + + + + {% endfor %} + +
{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
{{ attribute.name }} + {% if attribute.annotation %} + {% with expression = attribute.annotation %} + {% include "expression.html" with context %} + {% endwith %} + {% endif %} + +
+ {{ attribute.description|convert_markdown(heading_level, html_id) }} +
+
+ {% endblock table_style %} +{% elif config.docstring_section_style == "list" %} + {% block list_style scoped %} +

{{ section.title or lang.t("Attributes:") }}

+
    + {% for attribute in section.value %} +
  • + {{ attribute.name }} + {% if attribute.annotation %} + {% with expression = attribute.annotation %} + ({% include "expression.html" with context %}) + {% endwith %} + {% endif %} + – +
    + {{ attribute.description|convert_markdown(heading_level, html_id) }} +
    +
  • + {% endfor %} +
+ {% endblock list_style %} +{% elif config.docstring_section_style == "spacy" %} + {% block spacy_style scoped %} + + + + + + + + + {% for attribute in section.value %} + + + + + {% endfor %} + +
{{ (section.title or lang.t("ATTRIBUTE")).rstrip(":").upper() }}{{ lang.t("DESCRIPTION") }}
{{ attribute.name }} +
+ {{ attribute.description|convert_markdown(heading_level, html_id) }} +
+

+ {% if attribute.annotation %} + + TYPE: + {% with expression = attribute.annotation %} + {% include "expression.html" with context %} + {% endwith %} + + {% endif %} +

+
+ {% endblock spacy_style %} +{% endif %} diff --git a/overrides/mkdocstrings/python/material/docstring/parameters.html b/overrides/mkdocstrings/python/material/docstring/parameters.html new file mode 100644 index 0000000..ab4889e --- /dev/null +++ b/overrides/mkdocstrings/python/material/docstring/parameters.html @@ -0,0 +1,98 @@ +{{ log.debug("Rendering parameters section") }} + +{% import "language.html" as lang with context %} + +{% if config.docstring_section_style == "table" %} + {% block table_style scoped %} +

{{ section.title or lang.t("Parameters:") }}

+ + + + + + + + + + + {% for parameter in section.value %} + + + + + + + {% endfor %} + +
{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}{{ lang.t("Default") }}
{{ parameter.name }} + {% if parameter.annotation %} + {% with expression = parameter.annotation %} + {% include "expression.html" with context %} + {% endwith %} + {% endif %} + +
+ {{ parameter.description|convert_markdown(heading_level, html_id) }} +
+
+ {% if parameter.default %} + {% with expression = parameter.default %} + {% include "expression.html" with context %} + {% endwith %} + {% else %} + {{ lang.t("required") }} + {% endif %} +
+ {% endblock table_style %} +{% elif config.docstring_section_style == "list" %} + {% block list_style scoped %} +

{{ section.title or lang.t("Parameters:") }}

+
    + {% for parameter in section.value %} +
  • + {{ parameter.name }} + {% if parameter.annotation %} + {% with expression = parameter.annotation %} + ({% include "expression.html" with context %} + {%- if parameter.default %}, {{ lang.t("default:") }} + {% with expression = parameter.default %} + {% include "expression.html" with context %} + {% endwith %} + {% endif %}) + {% endwith %} + {% endif %} + – +
    + {{ parameter.description|convert_markdown(heading_level, html_id) }} +
    +
  • + {% endfor %} +
+ {% endblock list_style %} +{% elif config.docstring_section_style == "spacy" %} + {% block spacy_style scoped %} +

{{ section.title or lang.t("Parameters:") }}

+
+ {% for parameter in section.value %} +
{{ parameter.name }}
+
+
+ {{ parameter.description|convert_markdown(heading_level, html_id) }} +
+ {% if parameter.annotation %}

+ {{ lang.t("TYPE:") }} + {% with expression = parameter.annotation %} + {% include "expression.html" with context %} + {% endwith %} +

{% endif %} + {% if parameter.default %}

+ {{ lang.t("DEFAULT:") }} + {% with expression = parameter.default %} + {% include "expression.html" with context %} + {% endwith %} +

{% endif %} +
+ {% endfor %} +
+ {% endblock spacy_style %} +{% endif %} diff --git a/overrides/mkdocstrings/python/material/docstring/raises.html b/overrides/mkdocstrings/python/material/docstring/raises.html new file mode 100644 index 0000000..628e41b --- /dev/null +++ b/overrides/mkdocstrings/python/material/docstring/raises.html @@ -0,0 +1,72 @@ +{{ log.debug("Rendering raises section") }} + +{% import "language.html" as lang with context %} + +{% if config.docstring_section_style == "table" %} + {% block table_style scoped %} +

{{ section.title or lang.t("Raises:") }}

+ + + + + + + + + {% for raises in section.value %} + + + + + {% endfor %} + +
{{ lang.t("Type") }}{{ lang.t("Description") }}
+ {% if raises.annotation %} + {% with expression = raises.annotation %} + {% include "expression.html" with context %} + {% endwith %} + {% endif %} + +
+ {{ raises.description|convert_markdown(heading_level, html_id) }} +
+
+ {% endblock table_style %} +{% elif config.docstring_section_style == "list" %} + {% block list_style scoped %} +

{{ lang.t(section.title) or lang.t("Raises:") }}

+
    + {% for raises in section.value %} +
  • + {% if raises.annotation %} + {% with expression = raises.annotation %} + {% include "expression.html" with context %} + {% endwith %} + – + {% endif %} +
    + {{ raises.description|convert_markdown(heading_level, html_id) }} +
    +
  • + {% endfor %} +
+ {% endblock list_style %} +{% elif config.docstring_section_style == "spacy" %} + {% block spacy_style scoped %} +

{{ (section.title or lang.t("Raises:")) }}

+
+ {% for raises in section.value %} +
+ {% with expression = raises.annotation %} + {% include "expression.html" with context %} + {% endwith %} +
+
+
+ {{ raises.description|convert_markdown(heading_level, html_id) }} +
+
+ {% endfor %} +
+ {% endblock spacy_style %} +{% endif %} diff --git a/overrides/mkdocstrings/python/material/docstring/returns.html b/overrides/mkdocstrings/python/material/docstring/returns.html new file mode 100644 index 0000000..bd60840 --- /dev/null +++ b/overrides/mkdocstrings/python/material/docstring/returns.html @@ -0,0 +1,94 @@ +{{ log.debug("Rendering returns section") }} + +{% import "language.html" as lang with context %} + +{% if config.docstring_section_style == "table" %} + {% block table_style scoped %} + {% set name_column = section.value|selectattr("name")|any %} +

{{ section.title or lang.t("Returns:") }}

+ + + + {% if name_column %}{% endif %} + + + + + + {% for returns in section.value %} + + {% if name_column %}{% endif %} + + + + {% endfor %} + +
{{ lang.t("Name") }}{{ lang.t("Type") }}{{ lang.t("Description") }}
{% if returns.name %}{{ returns.name }}{% endif %} + {% if returns.annotation %} + {% with expression = returns.annotation %} + {% include "expression.html" with context %} + {% endwith %} + {% endif %} + +
+ {{ returns.description|convert_markdown(heading_level, html_id) }} +
+
+ {% endblock table_style %} +{% elif config.docstring_section_style == "list" %} + {% block list_style scoped %} +

{{ section.title or lang.t("Returns:") }}

+
    + {% for returns in section.value %} +
  • + {% if returns.name %}{{ returns.name }}{% endif %} + {% if returns.annotation %} + {% with expression = returns.annotation %} + {% if returns.name %} ({% endif %} + {% include "expression.html" with context %} + {% if returns.name %}){% endif %} + {% endwith %} + {% endif %} + – +
    + {{ returns.description|convert_markdown(heading_level, html_id) }} +
    +
  • + {% endfor %} +
+ {% endblock list_style %} +{% elif config.docstring_section_style == "spacy" %} + {% block spacy_style scoped %} +

{{ (section.title or lang.t("Returns:")) }}

+
+ {% for returns in section.value %} +
+ {% if returns.name %} + {{ returns.name }} + {% elif returns.annotation %} + + {% with expression = returns.annotation %} + {% include "expression.html" with context %} + {% endwith %} + + {% endif %} +
+
+
+ {{ returns.description|convert_markdown(heading_level, html_id) }} +
+ {% if returns.name and returns.annotation %} +

+ + {{ lang.t("TYPE:") }} + {% with expression = returns.annotation %} + {% include "expression.html" with context %} + {% endwith %} + +

+ {% endif %} +
+ {% endfor %} +
+ {% endblock spacy_style %} +{% endif %} diff --git a/overrides/partials/comments.html b/overrides/partials/comments.html new file mode 100644 index 0000000..d7ae25a --- /dev/null +++ b/overrides/partials/comments.html @@ -0,0 +1,37 @@ +{% if page.meta.comments %} +

{{ lang.t("meta.comments") }}

+ + + + +{% endif %} diff --git a/pyproject.toml b/pyproject.toml index e94cdab..de28a0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,14 +55,22 @@ dev = [ "git-fame>=1.12.2", ] docs = [ - "furo", - "ghp-import", - "linkify-it-py", - "myst-parser", - "Sphinx", - "sphinx-autodoc-typehints", - "sphinx-click", - "sphinx-copybutton", + "black>=23.3.0", + "griffe-pydantic", + "markdown-customblocks", + "mdx-truly-sane-lists", + "mkdocs>=1.4.3", + "mkdocs-click", + "mkdocs-gen-files>=0.5.0", + "mkdocs-git-authors-plugin", + "mkdocs-git-committers-plugin", + "mkdocs-git-revision-date-localized-plugin", + "mkdocs-include-markdown-plugin", + "mkdocs-literate-nav>=0.6.0", + "mkdocs-material>=9.1.0", + "mkdocs-section-index>=0.3.5", + "mkdocstrings[python]", + "python-frontmatter" ] test = [ "coverage[toml]", diff --git a/tools/drawioexport.py b/tools/drawioexport.py new file mode 100644 index 0000000..a2a3836 --- /dev/null +++ b/tools/drawioexport.py @@ -0,0 +1,132 @@ +"""Draw.io export script.""" + +import os.path +import shutil +import subprocess +import sys +from pathlib import Path +from typing import List, Optional + + +def get_executable_paths() -> list[str]: + """Get the Draw.io executable paths for the platform. + + Declared as a function to allow us to use API/environment information + available only when running under the specified platform. + + Returns: + All known paths. + """ + if sys.platform.startswith("darwin"): + applications = [os.path.expanduser("~/Applications"), "/Applications"] + drawio_path = os.path.join("draw.io.app", "Contents", "MacOS", "draw.io") + return [os.path.join(d, drawio_path) for d in applications] + elif sys.platform.startswith("linux"): + return ["/opt/draw.io/drawio"] + elif sys.platform.startswith("win32"): + program_files = [os.environ["ProgramFiles"]] + if "ProgramFiles(x86)" in os.environ: + program_files.append(os.environ["ProgramFiles(x86)"]) + return [os.path.join(d, "draw.io", "draw.io.exe") for d in program_files] + else: + return [] + + +def get_drawio_executable(executable_names: Optional[List[str]] = None) -> Optional[str]: + """Ensure the Draw.io executable path is configured, or guess it. + + Args: + executable_names: List of executable names to check. + + Returns: + Final Draw.io executable. + """ + executable_names = executable_names or ["draw.io", "drawio"] + + for executable_name in executable_names: + executable = shutil.which(executable_name) + if executable: + return executable + + executable_paths = get_executable_paths() + + return next( + (executable_path for executable_path in executable_paths if os.path.isfile(executable_path)), + None, + ) + + +def use_cached_file(source: Path, cache_filename: Path) -> bool: + """Is the cached copy up to date? + + Args: + source: Source path. + cache_filename: Export cache filename. + + Returns: + True if cache is up to date else False. + """ + return cache_filename.exists() and cache_filename.stat().st_mtime >= source.stat().st_mtime + + +def export_file( + source: Path, + page_index: int, + dest: Path, + export_format: str, +) -> int: + """Export an individual file. + + Args: + source: Source path, absolute. + page_index: Page index, numbered from zero. + dest: Destination path, within cache. + export_format: Export format. + + Returns: + The Draw.io exit status. + """ + drawio_executable = get_drawio_executable() + cmd = [ + str(drawio_executable), + "--export", + str(source), + "--page-index", + str(page_index), + "--output", + str(dest), + "--format", + export_format, + "--embed-svg-images", + "--scale", + "2", + ] + result = subprocess.run(cmd, check=False) # noqa: S603 + return result.returncode + + +def export_file_if_needed(source: Path, page_index: int, dest_path: Path) -> None: + """Export an individual file if needed. + + Args: + source: Source path, absolute. + page_index: Page index, numbered from zero. + dest_path: Destination path. + """ + if not use_cached_file(source, dest_path): + export_file(source, page_index, dest_path, "svg") + else: + print(f"Using cached file {dest_path}") + + +if __name__ == "__main__": + drawio_path = "docs/images/example.drawio" + destination = "docs/images/" + output_files: list[str] = [ + # SVG name for each page in the Draw.io file. + ] + source_path = Path(__file__).parent.parent.joinpath(drawio_path) + dest_path = Path(__file__).parent.parent.joinpath(destination) + for index, filename in enumerate(output_files): + filepath = dest_path.joinpath(filename) + export_file_if_needed(source_path, index, filepath) diff --git a/tools/update_frontmatter.py b/tools/update_frontmatter.py new file mode 100755 index 0000000..076b33c --- /dev/null +++ b/tools/update_frontmatter.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +"""Update frontmatter of markdown files.""" + +import argparse +from pathlib import Path +from typing import Any, Dict, Optional + +import frontmatter + + +def extract_main_heading(markdown_content: str) -> Optional[str]: + """ + Extracts the first level 1 heading from the provided Markdown content. + + Args: + markdown_content: A string containing Markdown text. + + Returns: + The text of the first level 1 heading, or None if no such heading is found. + """ + lines = markdown_content.split("\n") + + return next((line[2:] for line in lines if line.startswith("# ")), None) + + +def calc_title(post: frontmatter.Post) -> str: + """Calculate the title of the post.""" + return extract_main_heading(post.content) or post.get("title", "") + + +def calc_comment(post: frontmatter.Post) -> bool: + """Calculate if the post has comments.""" + return bool(post.get("comments", True)) + + +def calculate_update(post: frontmatter.Post) -> dict: + """Calculate if the frontmatter needs to be updated.""" + expected_title = calc_title(post) + expected_comment = calc_comment(post) + update: Dict[str, Any] = {} + if expected_title and expected_title != post.get("title"): + update["title"] = expected_title + if expected_comment != post.get("comments"): + update["comments"] = expected_comment + return update + + +def process_file(markdown_path: Path) -> None: + """Process a single file.""" + if not (markdown_path.is_file() and markdown_path.suffix == ".md"): + return + raw_text = markdown_path.read_text() + post = frontmatter.loads(raw_text) + + update = calculate_update(post) + if update: + for key, value in update.items(): + post[key] = value + new_text = frontmatter.dumps(post) + print(f"Updating {markdown_path}") + markdown_path.write_text(new_text) + + +def parse_args() -> argparse.Namespace: + """Parse command line arguments.""" + parser = argparse.ArgumentParser(description="Update frontmatter of markdown files") + parser.add_argument("markdown_path", type=str, nargs="+", help="Path or glob to markdown files") + return parser.parse_args() + + +if __name__ == "__main__": + # call `python tools/update_frontmatter.py "docs/**/*.md"` + args = parse_args() + documents = args.markdown_path + for document in documents: + for path in Path().glob(document): + process_file(path) From 68366035abff38e98d79f501bc9aeab233da890e Mon Sep 17 00:00:00 2001 From: Corey Oordt Date: Tue, 26 Nov 2024 09:29:24 -0600 Subject: [PATCH 2/2] Added additional files to documentation --- docs/explanation.md | 54 +++++++++++++++++++ .../reference/templating/changelog-context.md | 11 ++++ docs/reference/templating/version-context.md | 18 +++++++ docsrc/how-it-works.md | 49 ----------------- docsrc/templating/changelog-context.md | 11 ---- docsrc/templating/version-context.md | 18 ------- 6 files changed, 83 insertions(+), 78 deletions(-) create mode 100644 docs/explanation.md create mode 100644 docs/reference/templating/changelog-context.md create mode 100644 docs/reference/templating/version-context.md delete mode 100644 docsrc/how-it-works.md delete mode 100644 docsrc/templating/changelog-context.md delete mode 100644 docsrc/templating/version-context.md diff --git a/docs/explanation.md b/docs/explanation.md new file mode 100644 index 0000000..671d6cb --- /dev/null +++ b/docs/explanation.md @@ -0,0 +1,54 @@ +# How *Generate Changelog* Works + +Generate Changelog requires a git tag to indicate each version, or release, in the git repository. + +The two foundational functions are getting the starting tag and processing the commits from that starting point. Based on the results of these functions, we can suggest a release hint and render a change log and release notes. + +## Get the starting tag + +This step determines the processing starting point using the `--starting-tag` command line option or the `starting_tag_pipeline` configuration. If no starting tag is found, it starts at the first commit. + +## Process commits + +This step filters and processes each commit from a starting point and converts it to a [`CommitContext`][generate_changelog.context.CommitContext]. + +For each commit since the starting point: + +1. Discard the commit if it matches the [`ignore_patterns`][generate_changelog.configuration.Configuration.ignore_patterns] configuration. +2. Run the `summary` line through the [`summary_pipeline`][generate_changelog.configuration.Configuration.summary_pipeline] configuration. +3. Run the `body` through the [`body_pipeline`][generate_changelog.configuration.Configuration.body_pipeline] configuration. +4. Assign the commit a `category` based on the first matching item in the [`commit_classifiers`][generate_changelog.configuration.Configuration.commit_classifiers] configuration. +5. Assign the commit a `grouping` based on the [`group_by`][generate_changelog.configuration.Configuration.group_by] configuration. +6. Create a [`CommitContext`][generate_changelog.context.CommitContext] from the commit's processed attributes. + +## Process tags + +This step gathers and filters all tags from a starting point and converts them to a [`VersionContext`][generate_changelog.context.VersionContext]. + +For each tag since the starting point: + +1. Discard the tag if it does not match the [`tag_pattern`][generate_changelog.configuration.Configuration.tag_pattern] configuration. +2. Convert the tag to a [`VersionContext`][generate_changelog.context.VersionContext]. +3. Assign each [`CommitContext`][generate_changelog.context.CommitContext] to a [`VersionContext`][generate_changelog.context.VersionContext] according to its tag if the underlying commit is tagged or the next valid tag in the timeline. +4. Assign [`CommitContext`][generate_changelog.context.CommitContext]s since the last tag assigned a [`VersionContext`][generate_changelog.context.VersionContext] named [`unreleased_label`][generate_changelog.configuration.Configuration.unreleased_label]. + +5. Each [`VersionContext`][generate_changelog.context.VersionContext] sorts its assigned [`CommitContext`][generate_changelog.context.CommitContext]s by its `grouping` attribute. + +## Optional: suggest a release type + +This is a map-reduce function where each rule in the [`release_hint_rules`][generate_changelog.configuration.Configuration.release_hint_rules] configuration is applied to each [`CommitContext`][generate_changelog.context.CommitContext] in the unreleased [`VersionContext`][generate_changelog.context.VersionContext] and returns a [`release_type`][generate_changelog.configuration.RELEASE_TYPE_ORDER]. The resulting values are reduced to the maximum value according to this listing: + +1. no-release +2. alpha +3. beta +4. dev +5. pre-release +6. release-candidate +7. patch +8. minor +9. major + + +## Render the changelog + +This involves rendering a complete or partial changelog using [Jinja templates](https://jinja.palletsprojects.com). For incremental change logs (those with a starting tag), only the `heading.md.jinja` and `versions.md.jinja` templates are rendered and returned. For full change logs, the `base.md.jinja` template is rendered and returned. diff --git a/docs/reference/templating/changelog-context.md b/docs/reference/templating/changelog-context.md new file mode 100644 index 0000000..b0f3e22 --- /dev/null +++ b/docs/reference/templating/changelog-context.md @@ -0,0 +1,11 @@ +# Changelog Context + +| Name | Type | Description | +|---------------------|-------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| config | [`Configuration`][generate_changelog.configuration.Configuration] | The changelog generation configuration. | +| versions | `list` of [`VersionContext`][generate_changelog.context.VersionContext] | The version contexts to render in the changelog. | +| unreleased_label | `string` | The configured label used as the version title of the changes since the last valid tag. | +| valid_author_tokens | `list` of `string` | The configured tokens in git commit trailers that indicate authorship. | +| group_by | `list` of `string` | The configured grouping aspects for commits within a version. | +| group_depth | `int` | The number of levels version commits are grouped by. | +| diff_index | `function` | The index of the first difference between two lists | diff --git a/docs/reference/templating/version-context.md b/docs/reference/templating/version-context.md new file mode 100644 index 0000000..70c6394 --- /dev/null +++ b/docs/reference/templating/version-context.md @@ -0,0 +1,18 @@ +# Version Context + +| Name | Type | Description | +|-----------------|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------| +| label | `string` | The version label. | +| date_time | `datetime` | The date and time with timezone offset the version was tagged. | +| tag | `string` | The tag. | +| previous_tag | `string` | The previous tag. | +| tagger | `string` | The name and email of the person who tagged this version in `name ` format. | +| grouped_commits | `list` of [`GroupingContext`][generate_changelog.context.GroupingContext] | The sections that group the commits in this version. | +| metadata | `dict` | Metadata for this version parsed from commits. | + +## Grouping Context + +| Name | Type | Description | +|----------|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| grouping | `list` of `string` | The values that group these commits based on the [`group_by`][generate_changelog.configuration.Configuration.group_by] configuration | +| commits | `list` of [`CommitContext`][generate_changelog.context.CommitContext] | The commits with this grouping | diff --git a/docsrc/how-it-works.md b/docsrc/how-it-works.md deleted file mode 100644 index 45255ee..0000000 --- a/docsrc/how-it-works.md +++ /dev/null @@ -1,49 +0,0 @@ -# How Generate Changelog works - -Generate Changelog requires a git tag to indicate each version, or release, in the git repository. - -The two foundational functions are getting the starting tag and processing the commits from that starting point. From the result of the foundational functions we can suggest a release hint and render a change log and release notes. - -## Getting the starting tag - -This step uses the {option}`--starting-tag` command line option or the {ref}`configuration-starting_tag_pipeline` configuration to determine the starting point for processing. If no starting tag is found, it starts at the first commit. - -## Processing commits - -This step filters and processes each commit since a starting point. - -For each commit since the starting point: - -1. Discard the commit if it matches the {ref}`configuration-ignore_patterns` configuration. -2. Run the `summary` line through the {ref}`configuration-summary_pipeline` configuration. -3. Run the `body` through the {ref}`configuration-body_pipeline` configuration. -4. Assign the commit a `category` based on the first matching item in the {ref}`configuration-commit_classifiers` configuration. -5. Assign the commit a `grouping` based on the {ref}`configuration-group_by` configuration. -6. Create a {class}`~.context.CommitContext` from the commit's processed attributes. - -Then we must process the tags and create {class}`~.context.VersionContext`s. This involves gathering the list of tags since the starting point and using the {ref}`configuration-tag_pattern` configuration to filter out unwanted tags. Tags are converted to {class}`~.context.VersionContext`s. - -Each {class}`~.context.CommitContext` is assigned a version according to the next valid tag in the timeline (or their own tag, if the underlying commit itself is tagged). {class}`~.context.CommitContext`s since the last tag assigned a version named {ref}`configuration-unreleased_label`. - -Each {class}`~.context.VersionContext` sorts its assigned {class}`~.context.CommitContext`s by its `grouping` attribute. - -## Suggesting a release type - -This optional step applies rules to every {class}`~.context.CommitContext` in the {class}`~.context.VersionContext` labeled {ref}`configuration-unreleased_label` to determine what type of release (e.g. `patch`, `minor`, or `major`) to suggest. A `no-release` suggestion means that no release is warranted. This can happen if there is not an {ref}`configuration-unreleased_label` version, if {ref}`configuration-unreleased_label` version has no commit, or all the rules returned `no-release`. - -Essentially this is a map-reduce function where each rule in the {ref}`configuration-release_hint_rules` configuration maps a release hint to each {class}`~.context.CommitContext` in the unreleased {class}`~.context.VersionContext`. The resulting values are reduced to the maximum value according to: - -1. no-release -2. alpha -3. beta -4. dev -5. pre-release -6. release-candidate -7. patch -8. minor -9. major - - -## Rendering the changelog - -This involves rendering a complete or partial changelog using [Jinja templates](https://jinja.palletsprojects.com). For incremental change logs (those with a starting tag), only the `heading.md.jinja` and `versions.md.jinja` templates are rendered and returned. For full change logs, the `base.md.jinja` template is rendered and returned. diff --git a/docsrc/templating/changelog-context.md b/docsrc/templating/changelog-context.md deleted file mode 100644 index 49f1784..0000000 --- a/docsrc/templating/changelog-context.md +++ /dev/null @@ -1,11 +0,0 @@ -# Changelog Context - -| Name | Type | Description | -|---------------------|-------------------------------------|-----------------------------------------------------------------------------------------| -| config | {class}`~.Configuration` | The changelog generation configuration. | -| versions | `list` of {class}`~.VersionContext` | The version contexts to render in the changelog. | -| unreleased_label | `string` | The configured label used as the version title of the changes since the last valid tag. | -| valid_author_tokens | `list` of `string` | The configured tokens in git commit trailers that indicate authorship. | -| group_by | `list` of `string` | The configured grouping aspects for commits within a version. | -| group_depth | `int` | The number of levels version commits are grouped by. | -| diff_index | `function` | The index of the first difference between two lists | diff --git a/docsrc/templating/version-context.md b/docsrc/templating/version-context.md deleted file mode 100644 index 43576b0..0000000 --- a/docsrc/templating/version-context.md +++ /dev/null @@ -1,18 +0,0 @@ -# Version Context - -| Name | Type | Description | -|-----------------|--------------------------------------|-------------------------------------------------------------------------------------------| -| label | `string` | The version label. | -| date_time | `datetime` | The date and time with timezone offset the version was tagged. | -| tag | `string` | The tag. | -| previous_tag | `string` | The previous tag. | -| tagger | `string` | The name and email of the person who tagged this version in `name ` format. | -| grouped_commits | `list` of {class}`~.GroupingContext` | The sections that group the commits in this version. | -| metadata | `dict` | Metadata for this version parsed from commits. | - -## Grouping Context - -| Name | Type | Description | -|----------|------------------------------------|--------------------------------------------------------------------------------------------------| -| grouping | `list` of `string` | The values that group these commits based on the {class}`~.Configuration.group_by` configuration | -| commits | `list` of {class}`~.CommitContext` | The commits with this grouping |