mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-22 08:42:32 -05:00
Merge pull request '[gitea] v1.21 cherry-pick' (#2340) from earl-warren/forgejo:wip-v1.21-forgejo into v1.21/forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2340 Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
commit
31ca6d8160
15 changed files with 86 additions and 67 deletions
|
@ -743,7 +743,7 @@ rules:
|
|||
wc/no-constructor-params: [2]
|
||||
wc/no-constructor: [2]
|
||||
wc/no-customized-built-in-elements: [2]
|
||||
wc/no-exports-with-element: [2]
|
||||
wc/no-exports-with-element: [0]
|
||||
wc/no-invalid-element-name: [2]
|
||||
wc/no-invalid-extends: [2]
|
||||
wc/no-method-prefixed-with-on: [2]
|
||||
|
|
|
@ -180,11 +180,17 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
|
|||
}
|
||||
|
||||
if len(reqs) > 0 {
|
||||
_, err := b.inner.Client.Bulk().
|
||||
Index(b.inner.VersionedIndexName()).
|
||||
Add(reqs...).
|
||||
Do(ctx)
|
||||
return err
|
||||
esBatchSize := 50
|
||||
|
||||
for i := 0; i < len(reqs); i += esBatchSize {
|
||||
_, err := b.inner.Client.Bulk().
|
||||
Index(b.inner.VersionedIndexName()).
|
||||
Add(reqs[i:min(i+esBatchSize, len(reqs))]...).
|
||||
Do(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ func EnumeratePackageVersions(ctx *context.Context) {
|
|||
}
|
||||
|
||||
type Resource struct {
|
||||
Name string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Checksum string `json:"checksum"`
|
||||
}
|
||||
|
|
|
@ -278,15 +278,13 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
|
|||
}
|
||||
}
|
||||
|
||||
if !isCreated {
|
||||
notify_service.UpdateRelease(gitRepo.Ctx, doer, rel)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !rel.IsDraft {
|
||||
if !isCreated {
|
||||
notify_service.UpdateRelease(gitRepo.Ctx, doer, rel)
|
||||
return nil
|
||||
}
|
||||
notify_service.NewRelease(gitRepo.Ctx, rel)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -351,7 +349,8 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
|
|||
}
|
||||
}
|
||||
|
||||
notify_service.DeleteRelease(ctx, doer, rel)
|
||||
|
||||
if !rel.IsDraft {
|
||||
notify_service.DeleteRelease(ctx, doer, rel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<div>{{ctx.Locale.Tr "repo.commit.contained_in"}}</div>
|
||||
<div class="gt-df gt-mt-3">
|
||||
<div class="gt-p-2">{{svg "octicon-git-branch"}}</div>
|
||||
<div class="branch-area flex-text-block gt-f1"></div>
|
||||
<div class="branch-area flex-text-block gt-fw gt-f1"></div>
|
||||
</div>
|
||||
<div class="gt-df gt-mt-3">
|
||||
<div class="gt-p-2">{{svg "octicon-tag"}}</div>
|
||||
<div class="tag-area flex-text-block gt-f1"></div>
|
||||
<div class="tag-area flex-text-block gt-fw gt-f1"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
{{range $idx, $release := .Releases}}
|
||||
<li class="ui grid">
|
||||
<div class="ui four wide column meta">
|
||||
<a class="muted" href="{{if not .Sha1}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}}</a>
|
||||
{{if .Sha1}}
|
||||
<a class="muted" href="{{if not (and .Sha1 ($.Permission.CanRead $.UnitTypeCode))}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}}</a>
|
||||
{{if and .Sha1 ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
<a class="muted gt-mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}}</a>
|
||||
{{template "repo/branch_dropdown" dict "root" $ "release" .}}
|
||||
{{end}}
|
||||
|
@ -22,36 +22,18 @@
|
|||
<span class="ui yellow label">{{ctx.Locale.Tr "repo.release.draft"}}</span>
|
||||
{{else if .IsPrerelease}}
|
||||
<span class="ui orange label">{{ctx.Locale.Tr "repo.release.prerelease"}}</span>
|
||||
{{else if not .IsTag}}
|
||||
{{else}}
|
||||
<span class="ui green label">{{ctx.Locale.Tr "repo.release.stable"}}</span>
|
||||
{{end}}
|
||||
</h4>
|
||||
<div>
|
||||
{{if and $.CanCreateRelease (not .IsTag)}}
|
||||
{{if $.CanCreateRelease}}
|
||||
<a class="muted" data-tooltip-content="{{ctx.Locale.Tr "repo.release.edit"}}" href="{{$.RepoLink}}/releases/edit/{{.TagName | PathEscapeSegments}}" rel="nofollow">
|
||||
{{svg "octicon-pencil"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsTag}}
|
||||
<p class="text grey">
|
||||
{{if gt .Publisher.ID 0}}
|
||||
<span class="author">
|
||||
{{ctx.AvatarUtils.Avatar .Publisher 20 "gt-mr-2"}}
|
||||
<a href="{{.Publisher.HomeLink}}">{{.Publisher.Name}}</a>
|
||||
</span>
|
||||
<span class="released">
|
||||
{{ctx.Locale.Tr "repo.tagged_this"}}
|
||||
</span>
|
||||
{{if .CreatedUnix}}
|
||||
<span class="time">{{TimeSinceUnix .CreatedUnix ctx.Locale}}</span>
|
||||
{{end}}
|
||||
|
|
||||
{{end}}
|
||||
<span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | PathEscapeSegments}}...{{.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{ctx.Locale.Tr "repo.tag.ahead.target" .TargetBehind}}</span>
|
||||
</p>
|
||||
{{else}}
|
||||
<p class="text grey">
|
||||
<span class="author">
|
||||
{{if .OriginalAuthor}}
|
||||
|
@ -69,11 +51,10 @@
|
|||
{{if .CreatedUnix}}
|
||||
<span class="time">{{TimeSinceUnix .CreatedUnix ctx.Locale}}</span>
|
||||
{{end}}
|
||||
{{if not .IsDraft}}
|
||||
{{if and (not .IsDraft) ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
| <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | PathEscapeSegments}}...{{.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{ctx.Locale.Tr "repo.release.ahead.target" .TargetBehind}}</span>
|
||||
{{end}}
|
||||
</p>
|
||||
{{end}}
|
||||
<div class="markup desc">
|
||||
{{Str2html .Note}}
|
||||
</div>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
{{else if .IsPDFFile}}
|
||||
<div class="pdf-content is-loading" data-src="{{$.RawFileLink}}" data-fallback-button-text="{{ctx.Locale.Tr "diff.view_file"}}"></div>
|
||||
{{else}}
|
||||
<a href="{{$.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>
|
||||
<a href="{{$.RawFileLink}}" rel="nofollow">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else if .FileSize}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{if .EscapeStatus}}
|
||||
{{if .EscapeStatus.HasInvisible}}
|
||||
<div class="ui warning message unicode-escape-prompt gt-text-left">
|
||||
<button class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
|
||||
<button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "repo.invisible_runes_header"}}
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
{{else if .EscapeStatus.HasAmbiguous}}
|
||||
<div class="ui warning message unicode-escape-prompt gt-text-left">
|
||||
<button class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
|
||||
<button class="btn close icon hide-panel" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button>
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "repo.ambiguous_runes_header"}}
|
||||
</div>
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
{{else if .IsPDFFile}}
|
||||
<div class="pdf-content is-loading" data-src="{{$.RawFileLink}}" data-fallback-button-text="{{ctx.Locale.Tr "repo.diff.view_file"}}"></div>
|
||||
{{else}}
|
||||
<a href="{{$.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>
|
||||
<a href="{{$.RawFileLink}}" rel="nofollow">{{ctx.Locale.Tr "repo.file_view_raw"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else if .FileSize}}
|
||||
|
|
|
@ -12,8 +12,10 @@ export function renderCodeCopy() {
|
|||
if (!els.length) return;
|
||||
|
||||
for (const el of els) {
|
||||
if (!el.textContent) continue;
|
||||
const btn = makeCodeCopyButton();
|
||||
btn.setAttribute('data-clipboard-text', el.textContent);
|
||||
// remove final trailing newline introduced during HTML rendering
|
||||
btn.setAttribute('data-clipboard-text', el.textContent.replace(/\r?\n$/, ''));
|
||||
el.after(btn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// for performance considerations, it only uses performant syntax
|
||||
import {isDocumentFragmentOrElementNode} from '../utils/dom.js';
|
||||
|
||||
// for performance considerations, it only uses performant syntax
|
||||
function attachDirAuto(el) {
|
||||
if (el.type !== 'hidden' &&
|
||||
el.type !== 'checkbox' &&
|
||||
|
@ -18,7 +19,7 @@ export function initDirAuto() {
|
|||
const len = mutation.addedNodes.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const addedNode = mutation.addedNodes[i];
|
||||
if (addedNode.nodeType !== Node.ELEMENT_NODE && addedNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) continue;
|
||||
if (!isDocumentFragmentOrElementNode(addedNode)) continue;
|
||||
if (addedNode.nodeName === 'INPUT' || addedNode.nodeName === 'TEXTAREA') attachDirAuto(addedNode);
|
||||
const children = addedNode.querySelectorAll('input, textarea');
|
||||
const len = children.length;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import tippy, {followCursor} from 'tippy.js';
|
||||
import {isDocumentFragmentOrElementNode} from '../utils/dom.js';
|
||||
|
||||
const visibleInstances = new Set();
|
||||
|
||||
|
@ -136,8 +137,6 @@ function attachChildrenLazyTooltip(target) {
|
|||
}
|
||||
}
|
||||
|
||||
const elementNodeTypes = new Set([Node.ELEMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE]);
|
||||
|
||||
export function initGlobalTooltips() {
|
||||
// use MutationObserver to detect new "data-tooltip-content" elements added to the DOM, or attributes changed
|
||||
const observerConnect = (observer) => observer.observe(document, {
|
||||
|
@ -152,11 +151,10 @@ export function initGlobalTooltips() {
|
|||
if (mutation.type === 'childList') {
|
||||
// mainly for Vue components and AJAX rendered elements
|
||||
for (const el of mutation.addedNodes) {
|
||||
if (elementNodeTypes.has(el.nodeType)) {
|
||||
attachChildrenLazyTooltip(el);
|
||||
if (el.hasAttribute('data-tooltip-content')) {
|
||||
attachLazyTooltip(el);
|
||||
}
|
||||
if (!isDocumentFragmentOrElementNode(el)) continue;
|
||||
attachChildrenLazyTooltip(el);
|
||||
if (el.hasAttribute('data-tooltip-content')) {
|
||||
attachLazyTooltip(el);
|
||||
}
|
||||
}
|
||||
} else if (mutation.type === 'attributes') {
|
||||
|
|
|
@ -59,6 +59,17 @@ export function onDomReady(cb) {
|
|||
}
|
||||
}
|
||||
|
||||
// checks whether an element is owned by the current document, and whether it is a document fragment or element node
|
||||
// if it is, it means it is a "normal" element managed by us, which can be modified safely.
|
||||
export function isDocumentFragmentOrElementNode(el) {
|
||||
try {
|
||||
return el.ownerDocument === document && el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
|
||||
} catch {
|
||||
// in case the el is not in the same origin, then the access to nodeType would fail
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// autosize a textarea to fit content. Based on
|
||||
// https://github.com/github/textarea-autosize
|
||||
// ---------------------------------------------------------------------
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
// Convert an absolute or relative URL to an absolute URL with the current origin
|
||||
export function toOriginUrl(urlStr) {
|
||||
try {
|
||||
// only process absolute HTTP/HTTPS URL or relative URLs ('/xxx' or '//host/xxx')
|
||||
if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) {
|
||||
const {origin, protocol, hostname, port} = window.location;
|
||||
const url = new URL(urlStr, origin);
|
||||
url.protocol = protocol;
|
||||
url.hostname = hostname;
|
||||
url.port = port || (protocol === 'https:' ? '443' : '80');
|
||||
return url.toString();
|
||||
}
|
||||
} catch {}
|
||||
return urlStr;
|
||||
}
|
||||
|
||||
window.customElements.define('gitea-origin-url', class extends HTMLElement {
|
||||
connectedCallback() {
|
||||
const urlStr = this.getAttribute('data-url');
|
||||
try {
|
||||
// only process absolute HTTP/HTTPS URL or relative URLs ('/xxx' or '//host/xxx')
|
||||
if (urlStr.startsWith('http://') || urlStr.startsWith('https://') || urlStr.startsWith('/')) {
|
||||
const url = new URL(urlStr, window.origin);
|
||||
url.protocol = window.location.protocol;
|
||||
url.host = window.location.host;
|
||||
this.textContent = url.toString();
|
||||
return;
|
||||
}
|
||||
} catch {}
|
||||
this.textContent = urlStr;
|
||||
this.textContent = toOriginUrl(this.getAttribute('data-url'));
|
||||
}
|
||||
});
|
||||
|
|
17
web_src/js/webcomponents/GiteaOriginUrl.test.js
Normal file
17
web_src/js/webcomponents/GiteaOriginUrl.test.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {toOriginUrl} from './GiteaOriginUrl.js';
|
||||
|
||||
test('toOriginUrl', () => {
|
||||
const oldLocation = window.location;
|
||||
for (const origin of ['https://example.com', 'https://example.com:3000']) {
|
||||
window.location = new URL(`${origin}/`);
|
||||
expect(toOriginUrl('/')).toEqual(`${origin}/`);
|
||||
expect(toOriginUrl('/org/repo.git')).toEqual(`${origin}/org/repo.git`);
|
||||
expect(toOriginUrl('https://another.com')).toEqual(`${origin}/`);
|
||||
expect(toOriginUrl('https://another.com/')).toEqual(`${origin}/`);
|
||||
expect(toOriginUrl('https://another.com/org/repo.git')).toEqual(`${origin}/org/repo.git`);
|
||||
expect(toOriginUrl('https://another.com:4000')).toEqual(`${origin}/`);
|
||||
expect(toOriginUrl('https://another.com:4000/')).toEqual(`${origin}/`);
|
||||
expect(toOriginUrl('https://another.com:4000/org/repo.git')).toEqual(`${origin}/org/repo.git`);
|
||||
}
|
||||
window.location = oldLocation;
|
||||
});
|
Loading…
Reference in a new issue