mirror of
https://github.com/go-gitea/gitea.git
synced 2025-12-10 00:18:33 +01:00
Merge 17071180257ba3c8915b49ea9c7078a80acc7235 into 98ef79d73a6a546241dd02959ae17f136369b604
This commit is contained in:
commit
b30f7a3bfa
@ -164,6 +164,7 @@ type Repository struct {
|
||||
OriginalURL string `xorm:"VARCHAR(2048)"`
|
||||
DefaultBranch string
|
||||
DefaultWikiBranch string
|
||||
DefaultWikiFormat string
|
||||
|
||||
NumWatches int
|
||||
NumStars int
|
||||
|
||||
@ -48,6 +48,7 @@ var (
|
||||
DisableMigrations bool
|
||||
DisableStars bool `ini:"DISABLE_STARS"`
|
||||
DefaultBranch string
|
||||
DefaultWikiFormat string
|
||||
AllowAdoptionOfUnadoptedRepositories bool
|
||||
AllowDeleteOfUnadoptedRepositories bool
|
||||
DisableDownloadSourceArchives bool
|
||||
@ -172,6 +173,7 @@ var (
|
||||
DisableMigrations: false,
|
||||
DisableStars: false,
|
||||
DefaultBranch: "main",
|
||||
DefaultWikiFormat: "markdown",
|
||||
AllowForkWithoutMaximumLimit: true,
|
||||
StreamArchives: true,
|
||||
|
||||
@ -284,6 +286,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
|
||||
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https")
|
||||
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
|
||||
Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString(Repository.DefaultBranch)
|
||||
Repository.DefaultWikiFormat = sec.Key("WIKI_FORMAT").MustString(Repository.DefaultWikiFormat)
|
||||
RepoRootPath = sec.Key("ROOT").MustString(filepath.Join(AppDataPath, "gitea-repositories"))
|
||||
if !filepath.IsAbs(RepoRootPath) {
|
||||
RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)
|
||||
|
||||
@ -2227,6 +2227,10 @@ settings.advanced_settings = Advanced Settings
|
||||
settings.wiki_desc = Enable Repository Wiki
|
||||
settings.use_internal_wiki = Use Built-In Wiki
|
||||
settings.default_wiki_branch_name = Default Wiki Branch Name
|
||||
settings.default_wiki_format = Default Wiki Format
|
||||
settings.default_wiki_format.markdown = Markdown
|
||||
settings.default_wiki_format.org = Org-mode
|
||||
settings.default_wiki_format.both = Both
|
||||
settings.failed_to_change_default_wiki_branch = Failed to change the default wiki branch.
|
||||
settings.use_external_wiki = Use External Wiki
|
||||
settings.external_wiki_url = External Wiki URL
|
||||
|
||||
@ -510,7 +510,8 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string {
|
||||
// wikiContentsByName returns the contents of a wiki page, along with a boolean
|
||||
// indicating whether the page exists. Writes to ctx if an error occurs.
|
||||
func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName wiki_service.WebPath, isSidebarOrFooter bool) (string, string) {
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName)
|
||||
repoDefaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName, repoDefaultWikiFormat)
|
||||
entry, err := findEntryForFile(commit, gitFilename)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
|
||||
@ -554,6 +554,18 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Update DefaultWikiFormat if wiki is enabled
|
||||
if form.EnableWiki && !form.EnableExternalWiki {
|
||||
defaultWikiFormat := form.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
if repo.DefaultWikiFormat != defaultWikiFormat {
|
||||
repo.DefaultWikiFormat = defaultWikiFormat
|
||||
repoChanged = true
|
||||
}
|
||||
}
|
||||
|
||||
if form.EnableIssues && form.EnableExternalTracker && !unit_model.TypeExternalTracker.UnitGlobalDisabled() {
|
||||
if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
|
||||
|
||||
@ -146,21 +146,68 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
|
||||
// The last return value indicates whether the file should be returned as a raw file
|
||||
func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) {
|
||||
isRaw := false
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName)
|
||||
repoDefaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName, repoDefaultWikiFormat)
|
||||
entry, err := findEntryForFile(commit, gitFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
if entry == nil {
|
||||
// check if the file without ".md" suffix exists
|
||||
gitFilename := strings.TrimSuffix(gitFilename, ".md")
|
||||
entry, err = findEntryForFile(commit, gitFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
// Get default wiki format from repository, using global setting as fallback
|
||||
defaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
|
||||
// Check if gitFilename already has .md or .org extension and extract base filename
|
||||
baseFilename, hasMdSuffix := strings.CutSuffix(gitFilename, ".md")
|
||||
var hasOrgSuffix bool
|
||||
if !hasMdSuffix {
|
||||
baseFilename, hasOrgSuffix = strings.CutSuffix(gitFilename, ".org")
|
||||
if !hasOrgSuffix {
|
||||
baseFilename = gitFilename
|
||||
}
|
||||
}
|
||||
|
||||
// Try alternative formats based on DefaultWikiFormat setting
|
||||
if defaultWikiFormat == "markdown" || defaultWikiFormat == "both" {
|
||||
if !hasMdSuffix && !hasOrgSuffix {
|
||||
entry, err = findEntryForFile(commit, baseFilename+".md")
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
if entry != nil {
|
||||
gitFilename = baseFilename + ".md"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if entry == nil && (defaultWikiFormat == "org" || defaultWikiFormat == "both") {
|
||||
if !hasMdSuffix && !hasOrgSuffix {
|
||||
entry, err = findEntryForFile(commit, baseFilename+".org")
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
if entry != nil {
|
||||
gitFilename = baseFilename + ".org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
entry, err = findEntryForFile(commit, baseFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
if entry != nil {
|
||||
gitFilename = baseFilename
|
||||
isRaw = true
|
||||
}
|
||||
}
|
||||
isRaw = true
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, "", true, false
|
||||
@ -193,12 +240,31 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
ctx.ServerError("ListEntries", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get default wiki format from repository, using global setting as fallback
|
||||
defaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.IsRegular() {
|
||||
continue
|
||||
}
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Name())
|
||||
entryName := entry.Name()
|
||||
|
||||
// Filter by DefaultWikiFormat
|
||||
hasMdSuffix := strings.HasSuffix(entryName, ".md")
|
||||
hasOrgSuffix := strings.HasSuffix(entryName, ".org")
|
||||
if defaultWikiFormat == "markdown" && hasOrgSuffix {
|
||||
continue
|
||||
}
|
||||
if defaultWikiFormat == "org" && hasMdSuffix {
|
||||
continue
|
||||
}
|
||||
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entryName)
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
@ -212,7 +278,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
pages = append(pages, PageMeta{
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Name(),
|
||||
GitEntryName: entryName,
|
||||
})
|
||||
}
|
||||
ctx.Data["Pages"] = pages
|
||||
@ -252,7 +318,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
|
||||
rctx := renderhelper.NewRenderContextRepoWiki(ctx, ctx.Repo.Repository)
|
||||
|
||||
renderFn := func(data []byte) (escaped *charset.EscapeStatus, output template.HTML, err error) {
|
||||
renderFn := func(data []byte, filename string) (escaped *charset.EscapeStatus, output template.HTML, err error) {
|
||||
buf := &strings.Builder{}
|
||||
markupRd, markupWr := io.Pipe()
|
||||
defer markupWr.Close()
|
||||
@ -265,13 +331,21 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
close(done)
|
||||
}()
|
||||
|
||||
err = markdown.Render(rctx, bytes.NewReader(data), markupWr)
|
||||
// Detect markup type from filename and use the appropriate renderer
|
||||
// (.md -> markdown, .org -> orgmode)
|
||||
markupType := markup.DetectMarkupTypeByFileName(filename)
|
||||
if markupType == "" {
|
||||
// Default to markdown if detection fails
|
||||
markupType = markdown.MarkupName
|
||||
}
|
||||
fileRctx := rctx.WithMarkupType(markupType).WithRelativePath(filename)
|
||||
err = markup.Render(fileRctx, bytes.NewReader(data), markupWr)
|
||||
_ = markupWr.CloseWithError(err)
|
||||
<-done
|
||||
return escaped, output, err
|
||||
}
|
||||
|
||||
ctx.Data["EscapeStatus"], ctx.Data["WikiContentHTML"], err = renderFn(data)
|
||||
ctx.Data["EscapeStatus"], ctx.Data["WikiContentHTML"], err = renderFn(data, pageFilename)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
@ -286,26 +360,38 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
}
|
||||
|
||||
if !isSideBar {
|
||||
sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
|
||||
sidebarContent, sidebarEntry, sidebarFilename, _ := wikiContentsByName(ctx, commit, "_Sidebar")
|
||||
if ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Data["WikiSidebarEscapeStatus"], ctx.Data["WikiSidebarHTML"], err = renderFn(sidebarContent)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
if sidebarEntry != nil && sidebarContent != nil {
|
||||
// Use the git filename returned by wikiContentsByName, which correctly handles .org files
|
||||
if sidebarFilename == "" {
|
||||
sidebarFilename = sidebarEntry.Name()
|
||||
}
|
||||
ctx.Data["WikiSidebarEscapeStatus"], ctx.Data["WikiSidebarHTML"], err = renderFn(sidebarContent, sidebarFilename)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !isFooter {
|
||||
footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
|
||||
footerContent, footerEntry, footerFilename, _ := wikiContentsByName(ctx, commit, "_Footer")
|
||||
if ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Data["WikiFooterEscapeStatus"], ctx.Data["WikiFooterHTML"], err = renderFn(footerContent)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
if footerEntry != nil && footerContent != nil {
|
||||
// Use git filename here too to handle .org files correctly
|
||||
if footerFilename == "" {
|
||||
footerFilename = footerEntry.Name()
|
||||
}
|
||||
ctx.Data["WikiFooterEscapeStatus"], ctx.Data["WikiFooterHTML"], err = renderFn(footerContent, footerFilename)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +578,9 @@ func Wiki(ctx *context.Context) {
|
||||
}
|
||||
|
||||
wikiPath := entry.Name()
|
||||
if markup.DetectMarkupTypeByFileName(wikiPath) != markdown.MarkupName {
|
||||
detectedMarkupType := markup.DetectMarkupTypeByFileName(wikiPath)
|
||||
if detectedMarkupType == "" {
|
||||
// Only show warning if no renderer was found for this file type
|
||||
ext := strings.ToUpper(filepath.Ext(wikiPath))
|
||||
ctx.Data["FormatWarning"] = ext + " rendering is not supported at the moment. Rendered as Markdown."
|
||||
}
|
||||
@ -575,12 +663,30 @@ func WikiPages(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get default wiki format from repository, using global setting as fallback
|
||||
defaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.Entry.IsRegular() {
|
||||
continue
|
||||
}
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Entry.Name())
|
||||
entryName := entry.Entry.Name()
|
||||
|
||||
// Filter by DefaultWikiFormat
|
||||
hasMdSuffix := strings.HasSuffix(entryName, ".md")
|
||||
hasOrgSuffix := strings.HasSuffix(entryName, ".org")
|
||||
if defaultWikiFormat == "markdown" && hasOrgSuffix {
|
||||
continue
|
||||
}
|
||||
if defaultWikiFormat == "org" && hasMdSuffix {
|
||||
continue
|
||||
}
|
||||
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entryName)
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
@ -592,7 +698,7 @@ func WikiPages(ctx *context.Context) {
|
||||
pages = append(pages, PageMeta{
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Entry.Name(),
|
||||
GitEntryName: entryName,
|
||||
UpdatedUnix: timeutil.TimeStamp(entry.Commit.Author.When.Unix()),
|
||||
})
|
||||
}
|
||||
@ -614,7 +720,8 @@ func WikiRaw(ctx *context.Context) {
|
||||
}
|
||||
|
||||
providedWebPath := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
providedGitPath := wiki_service.WebPathToGitPath(providedWebPath)
|
||||
repoDefaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
providedGitPath := wiki_service.WebPathToGitPath(providedWebPath, repoDefaultWikiFormat)
|
||||
var entry *git.TreeEntry
|
||||
if commit != nil {
|
||||
// Try to find a file with that name
|
||||
@ -625,12 +732,40 @@ func WikiRaw(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
// Try to find a wiki page with that name
|
||||
providedGitPath = strings.TrimSuffix(providedGitPath, ".md")
|
||||
entry, err = findEntryForFile(commit, providedGitPath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
// Get default wiki format from repository, using global setting as fallback
|
||||
defaultWikiFormat := ctx.Repo.Repository.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
|
||||
// Try to find a wiki page with that name based on DefaultWikiFormat
|
||||
basePath, _ := strings.CutSuffix(providedGitPath, ".md")
|
||||
if basePath == providedGitPath {
|
||||
basePath, _ = strings.CutSuffix(providedGitPath, ".org")
|
||||
}
|
||||
|
||||
if defaultWikiFormat == "markdown" || defaultWikiFormat == "both" {
|
||||
entry, err = findEntryForFile(commit, basePath+".md")
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if entry == nil && (defaultWikiFormat == "org" || defaultWikiFormat == "both") {
|
||||
entry, err = findEntryForFile(commit, basePath+".org")
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
entry, err = findEntryForFile(commit, basePath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.
|
||||
entries, err := commit.ListEntries()
|
||||
assert.NoError(t, err)
|
||||
for _, entry := range entries {
|
||||
if entry.Name() == wiki_service.WebPathToGitPath(wikiName) {
|
||||
if entry.Name() == wiki_service.WebPathToGitPath(wikiName, repo.DefaultWikiFormat) {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +110,7 @@ type RepoSettingForm struct {
|
||||
// Advanced settings
|
||||
EnableCode bool
|
||||
|
||||
DefaultWikiFormat string
|
||||
EnableWiki bool
|
||||
EnableExternalWiki bool
|
||||
DefaultWikiBranch string
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
)
|
||||
@ -54,12 +55,26 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
|
||||
|
||||
// prepareGitPath try to find a suitable file path with file name by the given raw wiki name.
|
||||
// return: existence, prepared file path with name, error
|
||||
func prepareGitPath(gitRepo *git.Repository, defaultWikiBranch string, wikiPath WebPath) (bool, string, error) {
|
||||
unescaped := string(wikiPath) + ".md"
|
||||
gitPath := WebPathToGitPath(wikiPath)
|
||||
func prepareGitPath(gitRepo *git.Repository, defaultWikiBranch string, wikiPath WebPath, defaultWikiFormat string) (bool, string, error) {
|
||||
unescapedMd := string(wikiPath) + ".md"
|
||||
unescapedOrg := string(wikiPath) + ".org"
|
||||
gitPath := WebPathToGitPath(wikiPath, defaultWikiFormat)
|
||||
|
||||
// Look for both files
|
||||
filesInIndex, err := gitRepo.LsTree(defaultWikiBranch, unescaped, gitPath)
|
||||
// Build list of files to look for based on defaultWikiFormat
|
||||
var filesToCheck []string
|
||||
checkMarkdown := defaultWikiFormat == "markdown" || defaultWikiFormat == "both"
|
||||
checkOrg := defaultWikiFormat == "org" || defaultWikiFormat == "both"
|
||||
|
||||
if checkMarkdown {
|
||||
filesToCheck = append(filesToCheck, unescapedMd)
|
||||
}
|
||||
if checkOrg {
|
||||
filesToCheck = append(filesToCheck, unescapedOrg)
|
||||
}
|
||||
filesToCheck = append(filesToCheck, gitPath)
|
||||
|
||||
// Look for files based on format setting
|
||||
filesInIndex, err := gitRepo.LsTree(defaultWikiBranch, filesToCheck...)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Not a valid object name") {
|
||||
return false, gitPath, nil // branch doesn't exist
|
||||
@ -71,9 +86,15 @@ func prepareGitPath(gitRepo *git.Repository, defaultWikiBranch string, wikiPath
|
||||
foundEscaped := false
|
||||
for _, filename := range filesInIndex {
|
||||
switch filename {
|
||||
case unescaped:
|
||||
// if we find the unescaped file return it
|
||||
return true, unescaped, nil
|
||||
// if we find unescaped file (.md or .org) return it
|
||||
case unescapedMd:
|
||||
if checkMarkdown {
|
||||
return true, unescapedMd, nil
|
||||
}
|
||||
case unescapedOrg:
|
||||
if checkOrg {
|
||||
return true, unescapedOrg, nil
|
||||
}
|
||||
case gitPath:
|
||||
foundEscaped = true
|
||||
}
|
||||
@ -139,7 +160,11 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
}
|
||||
}
|
||||
|
||||
isWikiExist, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, newWikiName)
|
||||
defaultWikiFormat := repo.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
isWikiExist, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, newWikiName, defaultWikiFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -155,7 +180,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
isOldWikiExist := true
|
||||
oldWikiPath := newWikiPath
|
||||
if oldWikiName != newWikiName {
|
||||
isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, repo.DefaultWikiBranch, oldWikiName)
|
||||
isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, repo.DefaultWikiBranch, oldWikiName, defaultWikiFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -291,7 +316,11 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
return fmt.Errorf("unable to read HEAD tree to index in: %s %w", basePath, err)
|
||||
}
|
||||
|
||||
found, wikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, wikiName)
|
||||
defaultWikiFormat := repo.DefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
found, wikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, wikiName, defaultWikiFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
@ -76,7 +77,7 @@ func unescapeSegment(s string) (string, error) {
|
||||
}
|
||||
|
||||
func escapeSegToWeb(s string, hadDashMarker bool) string {
|
||||
if hadDashMarker || strings.Contains(s, "-") || strings.HasSuffix(s, ".md") {
|
||||
if hadDashMarker || strings.Contains(s, "-") || strings.HasSuffix(s, ".md") || strings.HasSuffix(s, ".org") {
|
||||
s = addDashMarker(s)
|
||||
} else {
|
||||
s = strings.ReplaceAll(s, " ", "-")
|
||||
@ -93,12 +94,20 @@ func WebPathSegments(s WebPath) []string {
|
||||
return a
|
||||
}
|
||||
|
||||
func WebPathToGitPath(s WebPath) string {
|
||||
if strings.HasSuffix(string(s), ".md") {
|
||||
ret, _ := url.PathUnescape(string(s))
|
||||
func WebPathToGitPath(s WebPath, repoDefaultWikiFormat string) string {
|
||||
str := string(s)
|
||||
// Accept only .md or .org directly
|
||||
if strings.HasSuffix(str, ".md") || strings.HasSuffix(str, ".org") {
|
||||
ret, _ := url.PathUnescape(str)
|
||||
return util.PathJoinRelX(ret)
|
||||
}
|
||||
|
||||
// Prioritize repository's DefaultWikiFormat, fallback to global setting if empty
|
||||
defaultWikiFormat := repoDefaultWikiFormat
|
||||
if defaultWikiFormat == "" {
|
||||
defaultWikiFormat = setting.Repository.DefaultWikiFormat
|
||||
}
|
||||
|
||||
a := strings.Split(string(s), "/")
|
||||
for i := range a {
|
||||
shouldAddDashMarker := hasDashMarker(a[i])
|
||||
@ -107,14 +116,26 @@ func WebPathToGitPath(s WebPath) string {
|
||||
a[i] = strings.ReplaceAll(a[i], "%20", " ") // space is safe to be kept in git path
|
||||
a[i] = strings.ReplaceAll(a[i], "+", " ")
|
||||
}
|
||||
return strings.Join(a, "/") + ".md"
|
||||
basePath := strings.Join(a, "/")
|
||||
|
||||
// Determine extension based on format setting
|
||||
if defaultWikiFormat == "org" {
|
||||
return basePath + ".org"
|
||||
}
|
||||
// For "both" or "markdown", default to .md
|
||||
return basePath + ".md"
|
||||
}
|
||||
|
||||
func GitPathToWebPath(s string) (wp WebPath, err error) {
|
||||
if !strings.HasSuffix(s, ".md") {
|
||||
// Trim .md or .org suffix if present
|
||||
if before, ok := strings.CutSuffix(s, ".md"); ok {
|
||||
s = before
|
||||
} else if before, ok := strings.CutSuffix(s, ".org"); ok {
|
||||
s = before
|
||||
} else {
|
||||
// If it doesn't end with .md or .org, it's not a valid wiki file
|
||||
return "", repo_model.ErrWikiInvalidFileName{FileName: s}
|
||||
}
|
||||
s = strings.TrimSuffix(s, ".md")
|
||||
a := strings.Split(s, "/")
|
||||
for i := range a {
|
||||
shouldAddDashMarker := hasDashMarker(a[i])
|
||||
@ -132,6 +153,9 @@ func WebPathToUserTitle(s WebPath) (dir, display string) {
|
||||
if before, ok := strings.CutSuffix(display, ".md"); ok {
|
||||
display = before
|
||||
display, _ = url.PathUnescape(display)
|
||||
} else if before, ok := strings.CutSuffix(display, ".org"); ok {
|
||||
display = before
|
||||
display, _ = url.PathUnescape(display)
|
||||
}
|
||||
display, _ = unescapeSegment(display)
|
||||
return dir, display
|
||||
|
||||
@ -81,7 +81,7 @@ func TestWebPathToGitPath(t *testing.T) {
|
||||
{"2000-01-02-meeting.md", "2000-01-02+meeting"},
|
||||
{"2000-01-02 meeting.-.md", "2000-01-02%20meeting.-"},
|
||||
} {
|
||||
assert.Equal(t, test.Expected, WebPathToGitPath(test.WikiName))
|
||||
assert.Equal(t, test.Expected, WebPathToGitPath(test.WikiName, "markdown"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,11 +129,11 @@ func TestUserWebGitPathConsistency(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
webPath := UserTitleToWebPath("", userTitle)
|
||||
gitPath := WebPathToGitPath(webPath)
|
||||
gitPath := WebPathToGitPath(webPath, "markdown")
|
||||
|
||||
webPath1, _ := GitPathToWebPath(gitPath)
|
||||
_, userTitle1 := WebPathToUserTitle(webPath1)
|
||||
gitPath1 := WebPathToGitPath(webPath1)
|
||||
gitPath1 := WebPathToGitPath(webPath1, "markdown")
|
||||
|
||||
assert.Equal(t, userTitle, userTitle1, "UserTitle for userTitle: %q", userTitle)
|
||||
assert.Equal(t, webPath, webPath1, "WebPath for userTitle: %q", userTitle)
|
||||
@ -173,7 +173,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
|
||||
defer gitRepo.Close()
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
gitPath := WebPathToGitPath(webPath)
|
||||
gitPath := WebPathToGitPath(webPath, repo.DefaultWikiFormat)
|
||||
entry, err := masterTree.GetTreeEntryByPath(gitPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gitPath, entry.Name(), "%s not added correctly", userTitle)
|
||||
@ -218,7 +218,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
gitPath := WebPathToGitPath(webPath)
|
||||
gitPath := WebPathToGitPath(webPath, repo.DefaultWikiFormat)
|
||||
entry, err := masterTree.GetTreeEntryByPath(gitPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gitPath, entry.Name(), "%s not edited correctly", newWikiName)
|
||||
@ -244,7 +244,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
||||
defer gitRepo.Close()
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
gitPath := WebPathToGitPath("Home")
|
||||
gitPath := WebPathToGitPath("Home", repo.DefaultWikiFormat)
|
||||
_, err = masterTree.GetTreeEntryByPath(gitPath)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
@ -279,7 +279,7 @@ func TestPrepareWikiFileName(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
webPath := UserTitleToWebPath("", tt.arg)
|
||||
existence, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, webPath)
|
||||
existence, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, webPath, "both")
|
||||
if (err != nil) != tt.wantErr {
|
||||
assert.NoError(t, err)
|
||||
return
|
||||
@ -310,7 +310,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
|
||||
|
||||
defer gitRepo.Close()
|
||||
|
||||
existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home")
|
||||
existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home", "both")
|
||||
assert.False(t, existence)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Home.md", newWikiPath)
|
||||
|
||||
@ -337,6 +337,34 @@
|
||||
<label>{{ctx.Locale.Tr "repo.settings.default_wiki_branch_name"}}</label>
|
||||
<input name="default_wiki_branch" value="{{.Repository.DefaultWikiBranch}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.default_wiki_format"}}</label>
|
||||
{{$defaultWikiFormat := .Repository.DefaultWikiFormat}}
|
||||
<div class="ui dropdown selection">
|
||||
<select name="default_wiki_format">
|
||||
<option value="markdown" {{if or (not $defaultWikiFormat) (eq $defaultWikiFormat "markdown")}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.default_wiki_format.markdown"}}</option>
|
||||
<option value="org" {{if eq $defaultWikiFormat "org"}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.default_wiki_format.org"}}</option>
|
||||
<option value="both" {{if eq $defaultWikiFormat "both"}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.default_wiki_format.both"}}</option>
|
||||
</select>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="default text">
|
||||
{{if (eq $defaultWikiFormat "markdown")}}
|
||||
{{ctx.Locale.Tr "repo.settings.default_wiki_format.markdown"}}
|
||||
{{else if (eq $defaultWikiFormat "org")}}
|
||||
{{ctx.Locale.Tr "repo.settings.default_wiki_format.org"}}
|
||||
{{else if (eq $defaultWikiFormat "both")}}
|
||||
{{ctx.Locale.Tr "repo.settings.default_wiki_format.both"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "repo.settings.default_wiki_format.markdown"}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="markdown">{{ctx.Locale.Tr "repo.settings.default_wiki_format.markdown"}}</div>
|
||||
<div class="item" data-value="org">{{ctx.Locale.Tr "repo.settings.default_wiki_format.org"}}</div>
|
||||
<div class="item" data-value="both">{{ctx.Locale.Tr "repo.settings.default_wiki_format.both"}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user