fix(ui): make unicode escape work in wiki (#8923)

Fixes #4118

- Unicode escape now works in wiki
- edit and escape buttons are better placed
- edit icon is now under the warning

Before: https://codeberg.org/attachments/4414f0cb-776a-4e62-a3b5-99de0914bf26
After: https://codeberg.org/attachments/93aad13f-e36b-42f9-a827-7ff7259da581

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8923
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: zokki <zokki.softwareschmiede@gmail.com>
Co-committed-by: zokki <zokki.softwareschmiede@gmail.com>
This commit is contained in:
zokki 2025-09-10 08:10:23 +02:00 committed by 0ko
commit 262a2253aa
5 changed files with 52 additions and 16 deletions

View file

@ -2,7 +2,7 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository wiki view">
{{template "repo/header" .}}
{{$title := .title}}
<div class="ui container">
<div class="ui container file-content">
<div class="repo-button-row">
<div class="tw-flex tw-items-center">
<div class="ui floating filter dropdown" data-no-results="{{ctx.Locale.Tr "repo.pulls.no_results"}}">
@ -53,17 +53,17 @@
</div>
</div>
<div class="eight wide right aligned column">
{{if .EscapeStatus.Escaped}}
<a class="ui small button unescape-button tw-hidden">{{ctx.Locale.Tr "repo.unescape_control_characters"}}</a>
<a class="ui small button escape-button">{{ctx.Locale.Tr "repo.escape_control_characters"}}</a>
{{end}}
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
<div class="ui right">
<div class="ui right">
{{if .EscapeStatus.Escaped}}
<a class="ui small button unescape-button tw-hidden">{{ctx.Locale.Tr "repo.unescape_control_characters"}}</a>
<a class="ui small button escape-button">{{ctx.Locale.Tr "repo.escape_control_characters"}}</a>
{{end}}
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
<a class="ui small button" href="{{.RepoLink}}/wiki/{{.PageURL}}?action=_edit">{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}</a>
<a class="ui small primary button" href="{{.RepoLink}}/wiki?action=_new">{{ctx.Locale.Tr "repo.wiki.new_page_button"}}</a>
<a class="ui small red button delete-button" href="" data-url="{{.RepoLink}}/wiki/{{.PageURL}}?action=_delete" data-id="{{.PageURL}}" data-modal-id="delete-wiki-page">{{ctx.Locale.Tr "repo.wiki.delete_page_button"}}</a>
</div>
{{end}}
{{end}}
</div>
</div>
</div>
</div>
@ -80,17 +80,17 @@
</div>
{{end}}
<div class="markup wiki-content-main {{if or .sidebarTocContent .sidebarPresent}}with-sidebar{{end}}">
<div class="file-view markup wiki-content-main {{if or .sidebarTocContent .sidebarPresent}}with-sidebar{{end}}">
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}}
{{.content | SafeHTML}}
</div>
{{if .sidebarPresent}}
<div class="markup wiki-content-sidebar">
<div class="file-view markup wiki-content-sidebar">
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
<a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
{{end}}
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
{{.sidebarContent | SafeHTML}}
</div>
{{end}}
@ -98,11 +98,11 @@
<div class="tw-clear-both"></div>
{{if .footerPresent}}
<div class="markup wiki-content-footer">
<div class="file-view markup wiki-content-footer">
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
<a class="tw-float-right muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{ctx.Locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
{{end}}
{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}}
{{.footerContent | SafeHTML}}
</div>
{{end}}

View file

@ -21,6 +21,7 @@ import (
"forgejo.org/modules/timeutil"
issue_service "forgejo.org/services/issue"
files_service "forgejo.org/services/repository/files"
"forgejo.org/services/wiki"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
@ -75,10 +76,17 @@ func DeclareGitRepos(t *testing.T) func() {
CommitMsg: "Another commit which mentions @user1 in the title\nand @user2 in the text",
},
}, nil),
newRepo(t, 2, "unicode-escaping", nil, []FileChanges{{
newRepo(t, 2, "unicode-escaping", &tests.DeclarativeRepoOptions{
EnabledUnits: optional.Some([]unit_model.Type{unit_model.TypeCode, unit_model.TypeWiki}),
}, []FileChanges{{
Filename: "a-file",
Versions: []string{"{a}{а}"},
}}, nil),
}}, func(user *user_model.User, repo *repo_model.Repository) {
wiki.InitWiki(db.DefaultContext, repo)
wiki.AddWikiPage(db.DefaultContext, user, repo, "Home", "{a}{а}", "{a}{а}")
wiki.AddWikiPage(db.DefaultContext, user, repo, "_Sidebar", "{a}{а}", "{a}{а}")
wiki.AddWikiPage(db.DefaultContext, user, repo, "_Footer", "{a}{а}", "{a}{а}")
}),
newRepo(t, 2, "multiple-combo-boxes", nil, []FileChanges{{
Filename: ".forgejo/issue_template/multi-combo-boxes.yaml",
Versions: []string{`

View file

@ -41,3 +41,22 @@ test(`Search results show titles (and not file names)`, async ({page}, workerInf
await expect(page.locator('#wiki-search a[href] b')).toHaveText('Page With Spaced Name');
await save_visual(page);
});
test('Wiki unicode-escape', async ({page}) => {
await page.goto('/user2/unicode-escaping/wiki');
await save_visual(page);
expect(await page.locator('.ui.message.unicode-escape-prompt').count()).toEqual(3);
const unescapedElements = page.locator('.ambiguous-code-point');
for (let i = 0; i < await unescapedElements.count(); i++) {
expect(await unescapedElements.nth(i).evaluate((el) => getComputedStyle(el).border)).toEqual('0px solid rgb(24, 24, 27)');
}
await page.locator('a.escape-button').click();
const escapedElements = page.locator('.ambiguous-code-point');
for (let i = 0; i < await escapedElements.count(); i++) {
expect(await escapedElements.nth(i).evaluate((el) => getComputedStyle(el).border)).toEqual('1px solid rgb(202, 138, 4)');
}
});

View file

@ -19,6 +19,10 @@
min-height: 340px; /* This height matches the markdown editor's height */
}
.repository.wiki .ui.message.unicode-escape-prompt {
margin-bottom: 0.5em;
}
.repository.wiki .wiki-content-parts .markup {
border: 1px solid var(--color-secondary);
border-radius: var(--border-radius);

View file

@ -9,6 +9,11 @@ export function initUnicodeEscapeButton() {
const fileContent = btn.closest('.file-content, .non-diff-file-content, .file-preview-box');
const fileView = fileContent?.querySelectorAll('.file-code, .file-view, .file-preview');
if (!fileContent || !fileView) {
console.error('initUnicodeEscapeButton file-content or view not found');
return;
}
if (btn.matches('.escape-button')) {
for (const el of fileView) el.classList.add('unicode-escaped');
hideElem(btn);