running-tools

A collection of tools for runners and their coaches
git clone https://git.ashermorgan.net/running-tools/
Log | Files | Refs | README

commit 8bcd4be3ac28f2a7df8f3413b52a087a101755aa
parent cb11a47eeb45faac340f7007a1b18bae348fbd79
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Sun, 24 Aug 2025 15:56:50 -0700

Create changelog page generated from CHANGELOG.md

Diffstat:
MCHANGELOG.md | 2+-
Mpackage-lock.json | 101++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mpackage.json | 2++
Msrc/assets/global.css | 23+++++++++++++++++++++++
Msrc/router/index.ts | 10++++++++++
Msrc/views/AboutPage.vue | 26+++-----------------------
Asrc/views/ChangeLog.vue | 16++++++++++++++++
7 files changed, 148 insertions(+), 32 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -21,7 +21,7 @@ - Open the edit target set dialog automatically after a new target set is created -## Removed +### Removed - Remove support for using target sets across multiple calculators (excluding the Batch Calculator, where applicable) diff --git a/package-lock.json b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.4.1", "dependencies": { "feather-icons": "^4.29.2", + "markdown-it": "^14.1.0", "vue": "^3.5.17", "vue-feather": "^2.0.0", "vue-router": "^4.3.2" @@ -17,6 +18,7 @@ "@eslint/js": "^9.22.0", "@playwright/test": "^1.53.1", "@tsconfig/node22": "^22.0.2", + "@types/markdown-it": "^14.1.2", "@types/node": "^24.0.7", "@vitejs/plugin-vue": "^5.2.4", "@vue/eslint-config-typescript": "^14.5.1", @@ -2344,13 +2346,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", - "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -2358,9 +2360,9 @@ } }, "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", - "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3050,6 +3052,31 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "24.0.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.7.tgz", @@ -3809,7 +3836,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { @@ -7273,6 +7299,15 @@ "dev": true, "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7361,6 +7396,35 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/marky": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", @@ -7378,6 +7442,12 @@ "node": ">= 0.4" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -8191,6 +8261,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/puppeteer-core": { "version": "24.10.2", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.10.2.tgz", @@ -9717,6 +9796,12 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/package.json b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "feather-icons": "^4.29.2", + "markdown-it": "^14.1.0", "vue": "^3.5.17", "vue-feather": "^2.0.0", "vue-router": "^4.3.2" @@ -28,6 +29,7 @@ "@eslint/js": "^9.22.0", "@playwright/test": "^1.53.1", "@tsconfig/node22": "^22.0.2", + "@types/markdown-it": "^14.1.2", "@types/node": "^24.0.7", "@vitejs/plugin-vue": "^5.2.4", "@vue/eslint-config-typescript": "^14.5.1", diff --git a/src/assets/global.css b/src/assets/global.css @@ -144,6 +144,29 @@ header h1 { } } +/* long-form text styles */ +.text { + max-width: 800px; + margin: auto; + font-size: 1.1em; +} +.text h2 { + text-align: center; +} +.text * + h2, .text :not(h2) + h3 { + margin-top: 1em; +} +.text p, .text ul { + margin-bottom: 0.5em; +} +.text p { + line-height: 1.3; +} +.text li { + margin-bottom: 0.2em; + margin-left: 1.5em; +} + /* light/default theme */ :root { /* The theme color of the app */ diff --git a/src/router/index.ts b/src/router/index.ts @@ -2,6 +2,7 @@ import { createRouter, createWebHashHistory } from 'vue-router'; import HomePage from '@/views/HomePage.vue'; import AboutPage from '@/views/AboutPage.vue'; import BatchCalculator from '@/views/BatchCalculator.vue'; +import ChangeLog from '@/views/ChangeLog.vue'; import PaceCalculator from '@/views/PaceCalculator.vue'; import RaceCalculator from '@/views/RaceCalculator.vue'; import SplitCalculator from '@/views/SplitCalculator.vue'; @@ -35,6 +36,15 @@ const router = createRouter({ }, }, { + path: '/changelog', + name: 'changelog', + component: ChangeLog, + meta: { + title: 'Change Log', + back: 'home', + }, + }, + { path: '/calculate', redirect: '/home', }, diff --git a/src/views/AboutPage.vue b/src/views/AboutPage.vue @@ -1,10 +1,11 @@ <template> - <div class="about-page"> + <div class="text"> <p> Running Tools is an <a :href="git_url">open source</a> collection of tools for runners and their coaches. All calculations are performed locally on your device. - This is Running Tools version {{ version }}{{ development ? ' (dev)' : '' }}. + This is Running Tools version <router-link :to="{ name: 'changelog' }"> + {{ version }}</router-link>{{ development ? ' (dev)' : '' }}. </p> <h2>Installation</h2> @@ -178,27 +179,6 @@ const git_url: string = repository.url.slice(4); </script> <style scoped> -.about-page { - max-width: 800px; - margin: auto; - font-size: 1.1em; -} -h2 { - text-align: center; -} -h2, h3 { - margin-top: 1em; -} -p, blockquote, ul { - margin-bottom: 0.5em; -} -li { - margin-bottom: 0.2em; - margin-left: 1.5em; -} -p { - line-height: 1.3; -} .questions { font-style: italic; } diff --git a/src/views/ChangeLog.vue b/src/views/ChangeLog.vue @@ -0,0 +1,16 @@ +<template> + <div class="text" v-html="changelog_html"/> +</template> + +<script setup lang="ts"> +import markdownit from 'markdown-it' + +import changelog_md from '/CHANGELOG.md?raw' + +const changelog_html: string = markdownit({ + typographer: true, // needed to convert '--' to en-dash +}).render(changelog_md.slice(changelog_md.indexOf('\n') + 1)); // render without h1 on first line +</script> + +<style scoped> +</style>