diff --git a/go.mod b/go.mod index a89c2a5c73dfb..3326aad9d4a56 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( github.com/ethantkoenig/rupture v1.0.1 github.com/felixge/fgprof v0.9.5 github.com/fsnotify/fsnotify v1.9.0 + github.com/gkampitakis/go-snaps v0.5.18 github.com/gliderlabs/ssh v0.3.8 github.com/go-ap/activitypub v0.0.0-20250810115208-cb73b20a1742 github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 @@ -195,6 +196,7 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect + github.com/gkampitakis/ciinfo v0.3.2 // indirect github.com/go-ap/errors v0.0.0-20250527110557-c8db454e53fd // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-enry/go-oniguruma v1.2.1 // indirect @@ -202,6 +204,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-webauthn/x v0.1.24 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -224,9 +227,12 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.4.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/libdns/libdns v1.1.1 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/markbates/going v1.0.3 // indirect + github.com/maruel/natural v1.1.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect @@ -257,6 +263,7 @@ require ( github.com/prometheus/procfs v0.17.0 // indirect github.com/rhysd/actionlint v1.7.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -264,6 +271,10 @@ require ( github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect github.com/tinylib/msgp v1.4.0 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/valyala/fastjson v1.6.4 // indirect diff --git a/go.sum b/go.sum index ac70239339ab6..ee49f464635b2 100644 --- a/go.sum +++ b/go.sum @@ -308,6 +308,10 @@ github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sa github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0= github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-snaps v0.5.18 h1:oZaQoonWI4KX3c9LNSWsxby8SM6EL+mex4KgLjzfIWg= +github.com/gkampitakis/go-snaps v0.5.18/go.mod h1:gC3YqxQTPyIXvQrw/Vpt3a8VqR1MO8sVpZFWN4DGwNs= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= @@ -369,6 +373,8 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0= @@ -558,6 +564,8 @@ github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o= github.com/markbates/goth v1.82.0 h1:8j/c34AjBSTNzO7zTsOyP5IYCQCMBTRBHAbBt/PI0bQ= github.com/markbates/goth v1.82.0/go.mod h1:/DRlcq0pyqkKToyZjsL2KgiA1zbF1HIjE7u2uC79rUk= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -687,6 +695,7 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= @@ -750,6 +759,16 @@ github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08Yu github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.4.0 h1:SYOeDRiydzOw9kSiwdYp9UcBgPFtLU2WDHaJXyHruf8= github.com/tinylib/msgp v1.4.0/go.mod h1:cvjFkb4RiC8qSBOPMGPSzSAx47nAsfhLVTCZZNuHv5o= diff --git a/modules/templates/util_date.go b/modules/templates/util_date.go index fc3f3f2339ae6..71b734d8276e5 100644 --- a/modules/templates/util_date.go +++ b/modules/templates/util_date.go @@ -93,14 +93,14 @@ func dateTimeFormat(format string, datetime any) template.HTML { attrs := []string{`weekday=""`, `year="numeric"`} switch format { case "short", "long": // date only - attrs = append(attrs, `month="`+format+`"`, `day="numeric"`) - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) + attrs = append(attrs, `threshold="P0Y"`, `month="`+format+`"`, `prefix=""`) case "full": // full date including time attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`) - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) default: panic("Unsupported format " + format) } + + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) } func timeSinceTo(then any, now time.Time) template.HTML { diff --git a/modules/templates/util_date_test.go b/modules/templates/util_date_test.go index 2c1f2d242ea75..df05fe4b133cc 100644 --- a/modules/templates/util_date_test.go +++ b/modules/templates/util_date_test.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/timeutil" + "github.com/gkampitakis/go-snaps/snaps" "github.com/stretchr/testify/assert" ) @@ -32,13 +33,13 @@ func TestDateTime(t *testing.T) { assert.EqualValues(t, "-", du.AbsoluteShort(timeutil.TimeStamp(0))) actual := du.AbsoluteShort(refTime) - assert.EqualValues(t, `2018-01-01`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2018-01-01")) actual = du.AbsoluteShort(refTimeStamp) - assert.EqualValues(t, `2017-12-31`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2017-12-31")) actual = du.FullTime(refTimeStamp) - assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2017-12-31 19:00:00 -05:00")) } func TestTimeSince(t *testing.T) { @@ -54,11 +55,11 @@ func TestTimeSince(t *testing.T) { refTime, _ := time.Parse(time.RFC3339, refTimeStr) actual := du.TimeSince(refTime) - assert.EqualValues(t, `2018-01-01 00:00:00 +00:00`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2018-01-01 00:00:00 +00:00")) actual = timeSinceTo(&refTime, time.Time{}) - assert.EqualValues(t, `2018-01-01 00:00:00 +00:00`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2018-01-01 00:00:00 +00:00")) actual = du.TimeSince(timeutil.TimeStampNano(refTime.UnixNano())) - assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) + snaps.MatchInlineSnapshot(t, actual, snaps.Inline("2017-12-31 19:00:00 -05:00")) } diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl index cb5aad7b0c14c..ceaf4411e6963 100644 --- a/templates/devtest/gitea-ui.tmpl +++ b/templates/devtest/gitea-ui.tmpl @@ -118,13 +118,12 @@
-

GiteaAbsoluteDate

-
-
-
-
-
-
relative-time:
+

Absolute Dates

+
+
+
+
+
diff --git a/web_src/js/webcomponents/absolute-date.test.ts b/web_src/js/webcomponents/absolute-date.test.ts deleted file mode 100644 index bf591358bd9ba..0000000000000 --- a/web_src/js/webcomponents/absolute-date.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {toAbsoluteLocaleDate} from './absolute-date.ts'; - -test('toAbsoluteLocaleDate', () => { - expect(toAbsoluteLocaleDate('2024-03-15', 'en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - })).toEqual('March 15, 2024'); - - expect(toAbsoluteLocaleDate('2024-03-15T01:02:03', 'de-DE', { - year: 'numeric', - month: 'long', - day: 'numeric', - })).toEqual('15. März 2024'); - - // these cases shouldn't happen - expect(toAbsoluteLocaleDate('2024-03-15 01:02:03', '', {})).toEqual('Invalid Date'); - expect(toAbsoluteLocaleDate('10000-01-01', '', {})).toEqual('Invalid Date'); - - // test different timezone - const oldTZ = process.env.TZ; - process.env.TZ = 'America/New_York'; - expect(new Date('2024-03-15').toLocaleString('en-US')).toEqual('3/14/2024, 8:00:00 PM'); - expect(toAbsoluteLocaleDate('2024-03-15', 'en-US')).toEqual('3/15/2024, 12:00:00 AM'); - process.env.TZ = oldTZ; -}); diff --git a/web_src/js/webcomponents/absolute-date.ts b/web_src/js/webcomponents/absolute-date.ts deleted file mode 100644 index 5ab4deaa14b54..0000000000000 --- a/web_src/js/webcomponents/absolute-date.ts +++ /dev/null @@ -1,41 +0,0 @@ -export function toAbsoluteLocaleDate(date: string, lang?: string, opts?: Intl.DateTimeFormatOptions) { - // only use the date part, it is guaranteed to be in ISO format (YYYY-MM-DDTHH:mm:ss.sssZ) or (YYYY-MM-DD) - // if there is an "Invalid Date" error, there must be something wrong in code and should be fixed. - // TODO: there is a root problem in backend code: the date "YYYY-MM-DD" is passed to backend without timezone (eg: deadline), - // then backend parses it in server's timezone and stores the parsed timestamp into database. - // If the user's timezone is different from the server's, the date might be displayed in the wrong day. - const dateSep = date.indexOf('T'); - date = dateSep === -1 ? date : date.substring(0, dateSep); - return new Date(`${date}T00:00:00`).toLocaleString(lang || [], opts); -} - -window.customElements.define('absolute-date', class extends HTMLElement { - static observedAttributes = ['date', 'year', 'month', 'weekday', 'day']; - - initialized = false; - - update = () => { - const opts: Record = {}; - for (const attr of ['year', 'month', 'weekday', 'day']) { - if (this.getAttribute(attr)) { - opts[attr] = this.getAttribute(attr)!; - } - } - const lang = this.closest('[lang]')?.getAttribute('lang') || - this.ownerDocument.documentElement.getAttribute('lang') || ''; - - if (!this.shadowRoot) this.attachShadow({mode: 'open'}); - this.shadowRoot!.textContent = toAbsoluteLocaleDate(this.getAttribute('date')!, lang, opts); - }; - - attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null) { - if (!this.initialized || oldValue === newValue) return; - this.update(); - } - - connectedCallback() { - this.initialized = false; - this.update(); - this.initialized = true; - } -}); diff --git a/web_src/js/webcomponents/index.ts b/web_src/js/webcomponents/index.ts index 6c0f5558648a8..8251f6ddae48d 100644 --- a/web_src/js/webcomponents/index.ts +++ b/web_src/js/webcomponents/index.ts @@ -2,4 +2,3 @@ import './polyfills.ts'; import '@github/relative-time-element'; import './origin-url.ts'; import './overflow-menu.ts'; -import './absolute-date.ts'; diff --git a/webpack.config.ts b/webpack.config.ts index f0528a7331567..891d7c26781e4 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -40,7 +40,6 @@ const webComponents = new Set([ // our own, in web_src/js/webcomponents 'overflow-menu', 'origin-url', - 'absolute-date', // from dependencies 'markdown-toolbar', 'relative-time',