Skip to content

Commit 443341b

Browse files
committed
moved slugify to shared/utils/html.ts to allow usage in the front & back
releases title's will now use slugify instead of encodeUri to fix issues with encoding
1 parent fabc65d commit 443341b

5 files changed

Lines changed: 25 additions & 24 deletions

File tree

app/components/Changelog/Card.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import type { ReleaseData } from '~~/shared/types/changelog'
3+
import { slugify } from '~~/shared/utils/html'
34
45
const { release } = defineProps<{
56
release: ReleaseData
@@ -13,7 +14,7 @@ const formattedDate = computed(() => {
1314
1415
const cardId = computed(() => (release.publishedAt ? `date-${formattedDate.value}` : undefined))
1516
16-
const navId = computed(() => `release-${encodeURI(release.title)}`)
17+
const navId = computed(() => `release-${slugify(release.title)}`)
1718
1819
function navigateToTitle() {
1920
navigateTo(`#${navId.value}`)

app/components/Changelog/Releases.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script setup lang="ts">
2+
import { slugify } from '~~/shared/utils/html'
3+
24
const { info, requestedDate, requestedVersion } = defineProps<{
35
info: ChangelogReleaseInfo
46
requestedDate?: string
@@ -40,7 +42,7 @@ watch(
4042
if (rv) {
4143
for (const match of matchingDateReleases.value ?? []) {
4244
if (match.title.toLowerCase().includes(rv)) {
43-
navigateTo(`#release-${encodeURI(match.title)}`)
45+
navigateTo(`#release-${slugify(match.title)}`)
4446
return
4547
}
4648
}

server/utils/changelog/markdown.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import {
55
ALLOWED_TAGS,
66
calculateSemanticDepth,
77
isNpmJsUrlThatCanBeRedirected,
8-
slugify,
98
} from '../readme'
10-
import { stripHtmlTags } from '#shared/utils/html'
9+
import { stripHtmlTags, slugify } from '#shared/utils/html'
1110
import sanitizeHtml from 'sanitize-html'
1211
import { hasProtocol } from 'ufo'
1312

server/utils/readme.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html'
33
import { hasProtocol } from 'ufo'
44
import type { ReadmeResponse, TocItem } from '#shared/types/readme'
55
import { convertBlobOrFileToRawUrl, type RepositoryInfo } from '#shared/utils/git-providers'
6-
import { decodeHtmlEntities, stripHtmlTags } from '#shared/utils/html'
6+
import { decodeHtmlEntities, stripHtmlTags, slugify } from '#shared/utils/html'
77
import { convertToEmoji } from '#shared/utils/emoji'
88
import { toProxiedImageUrl } from '#server/utils/image-proxy'
99
import { highlightCodeSync } from './shiki'
@@ -200,25 +200,6 @@ export const ALLOWED_ATTR: Record<string, string[]> = {
200200
'p': ['align'],
201201
}
202202

203-
/**
204-
* Generate a GitHub-style slug from heading text.
205-
* - Convert to lowercase
206-
* - Remove HTML tags
207-
* - Replace spaces with hyphens
208-
* - Remove special characters (keep alphanumeric, hyphens, underscores)
209-
* - Collapse multiple hyphens
210-
*/
211-
export function slugify(text: string): string {
212-
return stripHtmlTags(text)
213-
.replace(/&nbsp;?/g, '') // remove non breaking spaces
214-
.toLowerCase()
215-
.trim()
216-
.replace(/\s+/g, '-') // Spaces to hyphens
217-
.replace(/[^\w\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]/g, '') // Keep alphanumeric, CJK, hyphens
218-
.replace(/-+/g, '-') // Collapse multiple hyphens
219-
.replace(/^-|-$/g, '') // Trim leading/trailing hyphens
220-
}
221-
222203
/**
223204
* Lazy ATX heading extension for marked: allows headings without a space after `#`.
224205
*

shared/utils/html.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,21 @@ export function stripHtmlTags(text: string): string {
2727
} while (result !== previous)
2828
return result
2929
}
30+
/**
31+
* Generate a GitHub-style slug from heading text.
32+
* - Convert to lowercase
33+
* - Remove HTML tags
34+
* - Replace spaces with hyphens
35+
* - Remove special characters (keep alphanumeric, hyphens, underscores)
36+
* - Collapse multiple hyphens
37+
*/
38+
export function slugify(text: string): string {
39+
return stripHtmlTags(text)
40+
.replace(/&nbsp;?/g, '') // remove non breaking spaces
41+
.toLowerCase()
42+
.trim()
43+
.replace(/\s+/g, '-') // Spaces to hyphens
44+
.replace(/[^\w\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]/g, '') // Keep alphanumeric, CJK, hyphens
45+
.replace(/-+/g, '-') // Collapse multiple hyphens
46+
.replace(/^-|-$/g, '') // Trim leading/trailing hyphens
47+
}

0 commit comments

Comments
 (0)