mirror of
https://github.com/lichess-org/lila.git
synced 2026-05-26 13:51:00 +00:00
Merge branch 'master' into image-hosting-errwhere
This commit is contained in:
@@ -59,13 +59,13 @@ Feel free to use the [Lichess API](https://lichess.org/api) in your applications
|
||||
|
||||
| Name | Version | Notes |
|
||||
| ----------------- | ------- | ------------------------------------------------- |
|
||||
| Chromium / Chrome | last 10 | Full support |
|
||||
| Firefox | 75+ | Full support (fastest local analysis since FF 79) |
|
||||
| Edge | 91+ | Full support (reasonable support for 79+) |
|
||||
| Opera | 66+ | Reasonable support |
|
||||
| Safari | 11.1+ | Reasonable support |
|
||||
| Firefox | 115+ | Full support (recommended) |
|
||||
| Chromium / Chrome | 112+ | Full support |
|
||||
| Edge | 109+ | Full support |
|
||||
| Opera | 91+ | Reasonable support |
|
||||
| Safari | 13.1+ | Reasonable support |
|
||||
|
||||
Older browsers (including any version of Internet Explorer) will not work.
|
||||
Older browsers will not work.
|
||||
For your own sake, please upgrade. Security and performance, think about it!
|
||||
|
||||
## License
|
||||
|
||||
+28
-27
@@ -30,33 +30,34 @@ final class Study(
|
||||
apiC: => Api
|
||||
) extends LilaController(env):
|
||||
|
||||
def search(text: String, page: Int) = OpenOrScopedBody(parse.anyContent)(_.Study.Read, _.Web.Mobile):
|
||||
Reasonable(page):
|
||||
WithProxy: proxy ?=>
|
||||
val maxLen =
|
||||
if proxy.isFloodish then 50
|
||||
else if HTTPRequest.isCrawler(req).yes then 80
|
||||
else if ctx.isAnon then 100
|
||||
else 200
|
||||
text.trim.some.filter(_.nonEmpty).filter(_.sizeIs > 2).filter(_.sizeIs < maxLen) match
|
||||
case None =>
|
||||
for
|
||||
pag <- env.study.pager.all(Orders.default, page)
|
||||
_ <- preloadMembers(pag)
|
||||
res <- negotiate(
|
||||
Ok.page(views.study.list.all(pag, Orders.default)),
|
||||
apiStudies(pag)
|
||||
)
|
||||
yield res
|
||||
case Some(clean) =>
|
||||
limit.enumeration.search(rateLimited):
|
||||
env
|
||||
.studySearch(clean.take(100), page)
|
||||
.flatMap: pag =>
|
||||
negotiate(
|
||||
Ok.page(views.study.list.search(pag, text)),
|
||||
apiStudies(pag)
|
||||
)
|
||||
def search(text: String, page: Int, order: Option[Order]) =
|
||||
OpenOrScopedBody(parse.anyContent)(_.Study.Read, _.Web.Mobile):
|
||||
Reasonable(page):
|
||||
WithProxy: proxy ?=>
|
||||
val maxLen =
|
||||
if proxy.isFloodish then 50
|
||||
else if HTTPRequest.isCrawler(req).yes then 80
|
||||
else if ctx.isAnon then 100
|
||||
else 200
|
||||
text.trim.some.filter(_.nonEmpty).filter(_.sizeIs > 2).filter(_.sizeIs < maxLen) match
|
||||
case None =>
|
||||
for
|
||||
pag <- env.study.pager.all(Orders.default, page)
|
||||
_ <- preloadMembers(pag)
|
||||
res <- negotiate(
|
||||
Ok.page(views.study.list.all(pag, Orders.default)),
|
||||
apiStudies(pag)
|
||||
)
|
||||
yield res
|
||||
case Some(clean) =>
|
||||
limit.enumeration.search(rateLimited):
|
||||
env
|
||||
.studySearch(clean.take(100), order | Order.relevant, page)
|
||||
.flatMap: pag =>
|
||||
negotiate(
|
||||
Ok.page(views.study.list.search(pag, order | Order.relevant, text)),
|
||||
apiStudies(pag)
|
||||
)
|
||||
|
||||
def homeLang = LangPage(routes.Study.allDefault())(allResults(Order.hot, 1))
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ let currentCategory = '';
|
||||
const names: string[] = [];
|
||||
const wgets: string[] = [];
|
||||
|
||||
$('div').each((i, el) => {
|
||||
$('div').each((_, el) => {
|
||||
const category = $(el)
|
||||
.text()
|
||||
.split('\n')
|
||||
@@ -78,7 +78,7 @@ $('div').each((i, el) => {
|
||||
|
||||
$(el)
|
||||
.find('a')
|
||||
.each((i, el) => {
|
||||
.each((_, el) => {
|
||||
let name = $(el).attr('href');
|
||||
const url = $(el).attr('data-src');
|
||||
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ GET /study/likes/:order controllers.Study.mineLikes(order: StudyO
|
||||
GET /study/by/:username controllers.Study.byOwnerDefault(username: UserStr, page: Int ?= 1)
|
||||
GET /study/by/:username/export.pgn controllers.Study.exportPgn(username: UserStr)
|
||||
GET /study/by/:username/:order controllers.Study.byOwner(username: UserStr, order: StudyOrder, page: Int ?= 1)
|
||||
GET /study/search controllers.Study.search(q ?= "", page: Int ?= 1)
|
||||
GET /study/search controllers.Study.search(q ?= "", page: Int ?= 1, order: Option[StudyOrder] ?= None)
|
||||
GET /study/$id<\w{8}> controllers.Study.show(id: StudyId)
|
||||
POST /study controllers.Study.create
|
||||
POST /study/as controllers.Study.createAs
|
||||
|
||||
@@ -37,4 +37,9 @@ case class StartStudy(studyId: StudyId)
|
||||
case class RemoveStudy(studyId: StudyId)
|
||||
|
||||
enum Order:
|
||||
case hot, newest, oldest, updated, popular, alphabetical, mine
|
||||
case hot, newest, oldest, updated, popular, alphabetical, mine, relevant
|
||||
def key = toString
|
||||
|
||||
object Order:
|
||||
def all: List[Order] = values.toList
|
||||
val byKey = values.mapBy(_.key)
|
||||
|
||||
@@ -2060,6 +2060,7 @@ object I18nKey:
|
||||
val `youCanAlsoScrollOverTheBoardToMoveInTheGame`: I18nKey = "youCanAlsoScrollOverTheBoardToMoveInTheGame"
|
||||
val `scrollOverComputerVariationsToPreviewThem`: I18nKey = "scrollOverComputerVariationsToPreviewThem"
|
||||
val `analysisShapesHowTo`: I18nKey = "analysisShapesHowTo"
|
||||
val `primaryColorArrowsHowTo`: I18nKey = "primaryColorArrowsHowTo"
|
||||
val `letOtherPlayersMessageYou`: I18nKey = "letOtherPlayersMessageYou"
|
||||
val `receiveForumNotifications`: I18nKey = "receiveForumNotifications"
|
||||
val `shareYourInsightsData`: I18nKey = "shareYourInsightsData"
|
||||
@@ -2456,6 +2457,7 @@ object I18nKey:
|
||||
val `recentlyUpdated`: I18nKey = "study:recentlyUpdated"
|
||||
val `mostPopular`: I18nKey = "study:mostPopular"
|
||||
val `alphabetical`: I18nKey = "study:alphabetical"
|
||||
val `relevant`: I18nKey = "study:relevant"
|
||||
val `addNewChapter`: I18nKey = "study:addNewChapter"
|
||||
val `addMembers`: I18nKey = "study:addMembers"
|
||||
val `inviteToTheStudy`: I18nKey = "study:inviteToTheStudy"
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.time.LocalDate
|
||||
|
||||
import lila.common.Form.*
|
||||
import lila.core.i18n.Translate
|
||||
import lila.search.spec.{ DateRange, IntRange, Query, Sorting as SpecSorting }
|
||||
import lila.search.spec.{ DateRange, IntRange, Query, GameSorting as SpecSorting }
|
||||
|
||||
final private[gameSearch] class GameSearchForm:
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package lila.gameSearch
|
||||
|
||||
import lila.core.i18n.{ I18nKey as trans, Translate }
|
||||
|
||||
case class Sorting(f: String, order: String)
|
||||
|
||||
@@ -110,6 +110,8 @@ final class StudyPager(
|
||||
case Order.alphabetical => $sort.asc("name")
|
||||
// mine filter for topic view
|
||||
case Order.mine => $sort.desc("rank")
|
||||
// relevant not used here
|
||||
case Order.relevant => $sort.desc("rank")
|
||||
,
|
||||
hint = hint
|
||||
).mapFutureList(withChaptersAndLiking())
|
||||
@@ -146,9 +148,10 @@ final class StudyPager(
|
||||
object Orders:
|
||||
import lila.core.study.Order
|
||||
val default = Order.hot
|
||||
val list = Order.values.toList
|
||||
val list = Order.all.filter(_ != Order.relevant)
|
||||
val withoutMine = list.filterNot(_ == Order.mine)
|
||||
val withoutSelector = withoutMine.filter(o => o != Order.oldest && o != Order.alphabetical)
|
||||
val search = List(Order.hot, Order.newest, Order.popular, Order.alphabetical, Order.relevant)
|
||||
private val byKey = list.mapBy(_.toString)
|
||||
def apply(key: String): Order = byKey.getOrElse(key, default)
|
||||
val name: Order => I18nKey =
|
||||
@@ -159,3 +162,4 @@ object Orders:
|
||||
case Order.popular => I18nKey.study.mostPopular
|
||||
case Order.alphabetical => I18nKey.study.alphabetical
|
||||
case Order.mine => I18nKey.study.myStudies
|
||||
case Order.relevant => I18nKey.study.relevant
|
||||
|
||||
@@ -37,7 +37,7 @@ object StudyPgnTags:
|
||||
def validate(name: String, value: String): Option[Tag] = for
|
||||
tpe <- Tag.tagTypesByLowercase.get(name.toLowerCase).filter(relevantTypeSet)
|
||||
cleaned = lila.common.String.fullCleanUp(value)
|
||||
if cleaned.nonEmpty && cleaned.length <= 140
|
||||
if cleaned.length <= 140
|
||||
yield Tag(tpe, cleaned)
|
||||
|
||||
def validateTagTypes(tags: Tags): Either[String, Tags] =
|
||||
|
||||
@@ -96,7 +96,7 @@ final class ListUi(helpers: Helpers, bits: StudyBits):
|
||||
url = routes.Study.minePrivate(_)
|
||||
)
|
||||
|
||||
def search(pag: Paginator[WithChaptersAndLiked], text: String)(using Context) =
|
||||
def search(pag: Paginator[WithChaptersAndLiked], order: Order, text: String)(using Context) =
|
||||
Page(text)
|
||||
.css("analyse.study.index")
|
||||
.js(infiniteScrollEsmInit):
|
||||
@@ -104,10 +104,11 @@ final class ListUi(helpers: Helpers, bits: StudyBits):
|
||||
menu("search", Orders.default),
|
||||
main(cls := "page-menu__content study-index box")(
|
||||
div(cls := "box__top")(
|
||||
searchForm(trans.search.search.txt(), text),
|
||||
searchForm(trans.search.search.txt(), text, order),
|
||||
bits.orderSelect(order, "search", url = o => routes.Study.search(text, 1, o.some)),
|
||||
bits.newForm()
|
||||
),
|
||||
paginate(pag, routes.Study.search(text))
|
||||
paginate(pag, routes.Study.search(text, pag.currentPage, order.some))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -127,7 +128,7 @@ final class ListUi(helpers: Helpers, bits: StudyBits):
|
||||
menu(active, order, topics.so(_.value)),
|
||||
main(cls := "page-menu__content study-index box")(
|
||||
div(cls := "box__top")(
|
||||
searchForm(title, s"$searchFilter${searchFilter.nonEmpty.so(" ")}"),
|
||||
searchForm(title, s"$searchFilter${searchFilter.nonEmpty.so(" ")}", order),
|
||||
bits.orderSelect(order, active, url),
|
||||
bits.newForm()
|
||||
),
|
||||
@@ -171,8 +172,8 @@ final class ListUi(helpers: Helpers, bits: StudyBits):
|
||||
)(trs.whatAreStudies())
|
||||
)
|
||||
|
||||
def searchForm(placeholder: String, value: String) =
|
||||
form(cls := "search", action := routes.Study.search(), method := "get")(
|
||||
def searchForm(placeholder: String, value: String, order: Order) =
|
||||
form(cls := "search", action := routes.Study.search(order = order.some), method := "get")(
|
||||
input(name := "q", st.placeholder := placeholder, st.value := value, enterkeyhint := "search"),
|
||||
submitButton(cls := "button", dataIcon := Icon.Search)
|
||||
)
|
||||
|
||||
@@ -12,7 +12,8 @@ final class StudyBits(helpers: Helpers):
|
||||
|
||||
def orderSelect(order: Order, active: String, url: Order => Call)(using Context) =
|
||||
val orders =
|
||||
if active == "all" then Orders.withoutSelector
|
||||
if active == "search" then Orders.search
|
||||
else if active == "all" then Orders.withoutSelector
|
||||
else if active.startsWith("topic") then Orders.list
|
||||
else Orders.withoutMine
|
||||
lila.ui.bits.mselect(
|
||||
|
||||
@@ -5,8 +5,10 @@ import scalalib.paginator.*
|
||||
|
||||
import lila.search.*
|
||||
import lila.search.client.SearchClient
|
||||
import lila.search.spec.Query
|
||||
import lila.search.spec.{ Query, StudySorting }
|
||||
import lila.study.Study
|
||||
import lila.search.spec.{ Order as SpecOrder, StudySortField }
|
||||
import lila.core.study.Order
|
||||
|
||||
final class Env(
|
||||
studyRepo: lila.study.StudyRepo,
|
||||
@@ -16,13 +18,30 @@ final class Env(
|
||||
|
||||
val api: StudySearchApi = wire[StudySearchApi]
|
||||
|
||||
def apply(text: String, page: Int)(using me: Option[Me]) =
|
||||
def apply(text: String, order: Order, page: Int)(using me: Option[Me]) =
|
||||
Paginator[Study.WithChaptersAndLiked](
|
||||
adapter = new AdapterLike[Study]:
|
||||
def query = Query.study(text.take(100), me.map(_.userId.value))
|
||||
def query =
|
||||
Query.study(
|
||||
text.take(100),
|
||||
order.toSpec,
|
||||
me.map(_.userId.value)
|
||||
)
|
||||
def nbResults = api.count(query).dmap(_.toInt)
|
||||
def slice(offset: Int, length: Int) = api.search(query, From(offset), Size(length))
|
||||
.mapFutureList(pager.withChaptersAndLiking()),
|
||||
currentPage = page,
|
||||
maxPerPage = pager.maxPerPage
|
||||
)
|
||||
|
||||
extension (x: Order)
|
||||
def toSpec: Option[StudySorting] =
|
||||
x.match
|
||||
case Order.alphabetical => StudySorting(StudySortField.Name, SpecOrder.Asc).some
|
||||
case Order.hot => StudySorting(StudySortField.Hot, SpecOrder.Desc).some
|
||||
case Order.newest => StudySorting(StudySortField.CreatedAt, SpecOrder.Desc).some
|
||||
case Order.oldest => StudySorting(StudySortField.CreatedAt, SpecOrder.Asc).some
|
||||
case Order.popular => StudySorting(StudySortField.Likes, SpecOrder.Desc).some
|
||||
case Order.updated => StudySorting(StudySortField.UpdatedAt, SpecOrder.Desc).some
|
||||
case Order.mine => StudySorting(StudySortField.Likes, SpecOrder.Asc).some
|
||||
case Order.relevant => none
|
||||
|
||||
@@ -38,9 +38,16 @@ object LilaRouter:
|
||||
given PathBindable[Color] =
|
||||
strPath[Color](Color.fromName, "Invalid chess color, should be white or black", _.name)
|
||||
given PathBindable[Uci] = strPath[Uci](Uci.apply, "Invalid UCI move", _.uci)
|
||||
given PathBindable[StudyOrder] = strPath[StudyOrder](
|
||||
s => scala.util.Try(StudyOrder.valueOf(s).some).getOrElse(None),
|
||||
"Invalid study order"
|
||||
|
||||
given PathBindable[StudyOrder] = strPath(
|
||||
StudyOrder.byKey.get,
|
||||
s"Invalid study order ${StudyOrder.all.mkString(", ")}"
|
||||
)
|
||||
|
||||
given QueryStringBindable[StudyOrder] = strQueryString(
|
||||
StudyOrder.byKey.get,
|
||||
s"Invalid study order ${StudyOrder.all.mkString(", ")}",
|
||||
_.key
|
||||
)
|
||||
|
||||
private def urlEncode(str: String) = java.net.URLEncoder.encode(str, "utf-8")
|
||||
|
||||
@@ -137,7 +137,12 @@ object help:
|
||||
ul(
|
||||
li(trans.site.youCanAlsoScrollOverTheBoardToMoveInTheGame()),
|
||||
li(trans.site.scrollOverComputerVariationsToPreviewThem()),
|
||||
li(trans.site.analysisShapesHowTo())
|
||||
li(
|
||||
trans.site.analysisShapesHowTo(),
|
||||
ul(
|
||||
li(trans.site.primaryColorArrowsHowTo())
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
+2
-2
@@ -28,13 +28,13 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@lichess-org/chessground": "9.8.3",
|
||||
"@lichess-org/chessground": "9.8.4",
|
||||
"@lichess-org/pgn-viewer": "2.5.2",
|
||||
"@types/lichess": "workspace:*",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"ab": "github:lichess-org/ab-stub",
|
||||
"chessops": "^0.15.0",
|
||||
"chessops": "^0.15",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-plugin-compat": "^6.0.2",
|
||||
"lint-staged": "^16.2.4",
|
||||
|
||||
Generated
+65
-51
@@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@lichess-org/chessground':
|
||||
specifier: 9.8.3
|
||||
version: 9.8.3
|
||||
specifier: 9.8.4
|
||||
version: 9.8.4
|
||||
'@lichess-org/pgn-viewer':
|
||||
specifier: 2.5.2
|
||||
version: 2.5.2
|
||||
@@ -27,7 +27,7 @@ importers:
|
||||
specifier: github:lichess-org/ab-stub
|
||||
version: https://codeload.github.com/lichess-org/ab-stub/tar.gz/94236bf34dbc9c05daf50f4c9842d859b9142be0
|
||||
chessops:
|
||||
specifier: ^0.15.0
|
||||
specifier: ^0.15
|
||||
version: 0.15.0
|
||||
eslint:
|
||||
specifier: ^9.38.0
|
||||
@@ -155,7 +155,7 @@ importers:
|
||||
specifier: ^1.9.3
|
||||
version: 1.9.3
|
||||
cropperjs:
|
||||
specifier: ^1.6.2
|
||||
specifier: 1.6.2
|
||||
version: 1.6.2
|
||||
debounce-promise:
|
||||
specifier: ^3.1.2
|
||||
@@ -761,6 +761,12 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.0':
|
||||
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
|
||||
'@eslint-community/regexpp@4.12.1':
|
||||
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
|
||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||
@@ -830,8 +836,8 @@ packages:
|
||||
'@kurkle/color@0.3.4':
|
||||
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
|
||||
|
||||
'@lichess-org/chessground@9.8.3':
|
||||
resolution: {integrity: sha512-W0dTDeuKLsVJqYRF34OBcRrVqX4EC6/vK3zH11iT1dTR2i3yh79VkTckix8BWrXX8K0PLqWsK7A+/7CoTr+arA==}
|
||||
'@lichess-org/chessground@9.8.4':
|
||||
resolution: {integrity: sha512-bVPXvR1EWXAAYsuvT7LBmAuwMgIW18RwfFCgwLFT6+g6Ou0mXIJNhq9eczQKTxKnGHTKDbj55AyzmVpIxogYXg==}
|
||||
|
||||
'@lichess-org/pgn-viewer@2.5.2':
|
||||
resolution: {integrity: sha512-RPbq5xOa80/p1B7DkZQe4HDJN18gf7SANn8nXfDOmCi9tmqbVAPEtGs7W+qw62B5EZpU98gXxfomZ3Cr/rOkpA==}
|
||||
@@ -1033,8 +1039,8 @@ packages:
|
||||
'@types/qrcode@1.5.5':
|
||||
resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==}
|
||||
|
||||
'@types/react@19.2.2':
|
||||
resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==}
|
||||
'@types/react@19.1.9':
|
||||
resolution: {integrity: sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==}
|
||||
|
||||
'@types/sortablejs@1.15.8':
|
||||
resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==}
|
||||
@@ -1681,8 +1687,8 @@ packages:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-fullwidth-code-point@5.1.0:
|
||||
resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
|
||||
is-fullwidth-code-point@5.0.0:
|
||||
resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-glob@4.0.3:
|
||||
@@ -1742,8 +1748,8 @@ packages:
|
||||
engines: {node: '>=20.17'}
|
||||
hasBin: true
|
||||
|
||||
listr2@9.0.5:
|
||||
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
|
||||
listr2@9.0.4:
|
||||
resolution: {integrity: sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
locate-path@5.0.0:
|
||||
@@ -2097,8 +2103,8 @@ packages:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
slice-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
|
||||
slice-ansi@7.1.0:
|
||||
resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
snabbdom@3.5.1:
|
||||
@@ -2153,8 +2159,8 @@ packages:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
strip-ansi@7.1.0:
|
||||
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-json-comments@3.1.1:
|
||||
@@ -2483,7 +2489,7 @@ snapshots:
|
||||
lru-cache: 10.4.3
|
||||
optional: true
|
||||
|
||||
'@babel/runtime@7.28.4': {}
|
||||
'@babel/runtime@7.28.2': {}
|
||||
|
||||
'@badrap/result@0.3.1': {}
|
||||
|
||||
@@ -2491,7 +2497,7 @@ snapshots:
|
||||
|
||||
'@blakeembrey/template@1.2.0': {}
|
||||
|
||||
'@csstools/color-helpers@5.1.0':
|
||||
'@csstools/color-helpers@5.0.2':
|
||||
optional: true
|
||||
|
||||
'@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
|
||||
@@ -2594,6 +2600,11 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.25.11':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.7.0(eslint@9.38.0)':
|
||||
dependencies:
|
||||
eslint: 9.38.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.0(eslint@9.38.0)':
|
||||
dependencies:
|
||||
eslint: 9.38.0
|
||||
@@ -2604,7 +2615,7 @@ snapshots:
|
||||
'@eslint/config-array@0.21.1':
|
||||
dependencies:
|
||||
'@eslint/object-schema': 2.1.7
|
||||
debug: 4.4.3
|
||||
debug: 4.4.1
|
||||
minimatch: 3.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2670,12 +2681,12 @@ snapshots:
|
||||
|
||||
'@kurkle/color@0.3.4': {}
|
||||
|
||||
'@lichess-org/chessground@9.8.3': {}
|
||||
'@lichess-org/chessground@9.8.4': {}
|
||||
|
||||
'@lichess-org/pgn-viewer@2.5.2':
|
||||
dependencies:
|
||||
'@lichess-org/chessground': 9.8.3
|
||||
'@types/node': 24.8.1
|
||||
'@lichess-org/chessground': 9.8.4
|
||||
'@types/node': 24.7.2
|
||||
chessops: 0.15.0
|
||||
snabbdom: 3.5.1
|
||||
|
||||
@@ -2884,7 +2895,7 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.46.1
|
||||
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.46.1
|
||||
debug: 4.4.3
|
||||
debug: 4.4.1
|
||||
eslint: 9.38.0
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
@@ -2894,7 +2905,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.46.1
|
||||
debug: 4.4.3
|
||||
debug: 4.4.1
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2913,7 +2924,7 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.46.1
|
||||
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
|
||||
debug: 4.4.3
|
||||
debug: 4.4.1
|
||||
eslint: 9.38.0
|
||||
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
@@ -2928,11 +2939,11 @@ snapshots:
|
||||
'@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.46.1
|
||||
'@typescript-eslint/visitor-keys': 8.46.1
|
||||
debug: 4.4.3
|
||||
debug: 4.4.1
|
||||
fast-glob: 3.3.3
|
||||
is-glob: 4.0.3
|
||||
minimatch: 9.0.5
|
||||
semver: 7.7.3
|
||||
semver: 7.7.2
|
||||
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
@@ -2940,7 +2951,7 @@ snapshots:
|
||||
|
||||
'@typescript-eslint/utils@8.46.1(eslint@9.38.0)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0)
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.38.0)
|
||||
'@typescript-eslint/scope-manager': 8.46.1
|
||||
'@typescript-eslint/types': 8.46.1
|
||||
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
|
||||
@@ -2962,13 +2973,13 @@ snapshots:
|
||||
chai: 5.3.3
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@7.1.11(@types/node@24.8.1)(yaml@2.8.1))':
|
||||
'@vitest/mocker@3.2.4(vite@7.0.6(@types/node@24.7.2)(yaml@2.8.1))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.19
|
||||
optionalDependencies:
|
||||
vite: 7.1.11(@types/node@24.8.1)(yaml@2.8.1)
|
||||
vite: 7.0.6(@types/node@24.7.2)(yaml@2.8.1)
|
||||
|
||||
'@vitest/pretty-format@3.2.4':
|
||||
dependencies:
|
||||
@@ -3183,7 +3194,7 @@ snapshots:
|
||||
|
||||
cli-truncate@5.1.0:
|
||||
dependencies:
|
||||
slice-ansi: 7.1.2
|
||||
slice-ansi: 7.1.0
|
||||
string-width: 8.1.0
|
||||
|
||||
cliui@6.0.0:
|
||||
@@ -3343,8 +3354,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@mdn/browser-compat-data': 5.7.6
|
||||
ast-metadata-inferer: 0.8.1
|
||||
browserslist: 4.26.3
|
||||
caniuse-lite: 1.0.30001751
|
||||
browserslist: 4.25.1
|
||||
caniuse-lite: 1.0.30001731
|
||||
eslint: 9.38.0
|
||||
find-up: 5.0.0
|
||||
globals: 15.15.0
|
||||
@@ -3370,7 +3381,7 @@ snapshots:
|
||||
'@eslint/eslintrc': 3.3.1
|
||||
'@eslint/js': 9.38.0
|
||||
'@eslint/plugin-kit': 0.4.0
|
||||
'@humanfs/node': 0.16.7
|
||||
'@humanfs/node': 0.16.6
|
||||
'@humanwhocodes/module-importer': 1.0.1
|
||||
'@humanwhocodes/retry': 0.4.3
|
||||
'@types/estree': 1.0.8
|
||||
@@ -3487,7 +3498,7 @@ snapshots:
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-east-asian-width@1.4.0: {}
|
||||
get-east-asian-width@1.3.0: {}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
@@ -3560,7 +3571,7 @@ snapshots:
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-fullwidth-code-point@5.1.0:
|
||||
is-fullwidth-code-point@5.0.0:
|
||||
dependencies:
|
||||
get-east-asian-width: 1.4.0
|
||||
|
||||
@@ -3631,14 +3642,14 @@ snapshots:
|
||||
lint-staged@16.2.4:
|
||||
dependencies:
|
||||
commander: 14.0.1
|
||||
listr2: 9.0.5
|
||||
listr2: 9.0.4
|
||||
micromatch: 4.0.8
|
||||
nano-spawn: 2.0.0
|
||||
pidtree: 0.6.0
|
||||
string-argv: 0.3.2
|
||||
yaml: 2.8.1
|
||||
|
||||
listr2@9.0.5:
|
||||
listr2@9.0.4:
|
||||
dependencies:
|
||||
cli-truncate: 5.1.0
|
||||
colorette: 2.0.20
|
||||
@@ -3682,8 +3693,6 @@ snapshots:
|
||||
|
||||
marked@16.4.1: {}
|
||||
|
||||
memory-pager@1.5.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
micromatch@4.0.8:
|
||||
@@ -3730,7 +3739,7 @@ snapshots:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
||||
nwsapi@2.2.22:
|
||||
nwsapi@2.2.21:
|
||||
optional: true
|
||||
|
||||
object-assign@4.1.1: {}
|
||||
@@ -3979,7 +3988,7 @@ snapshots:
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
slice-ansi@7.1.2:
|
||||
slice-ansi@7.1.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
is-fullwidth-code-point: 5.1.0
|
||||
@@ -4025,13 +4034,18 @@ snapshots:
|
||||
get-east-asian-width: 1.4.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
string-width@8.1.0:
|
||||
dependencies:
|
||||
get-east-asian-width: 1.3.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
ansi-regex: 6.1.0
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
|
||||
@@ -4155,13 +4169,13 @@ snapshots:
|
||||
|
||||
uuid@11.1.0: {}
|
||||
|
||||
vite-node@3.2.4(@types/node@24.8.1)(yaml@2.8.1):
|
||||
vite-node@3.2.4(@types/node@24.7.2)(yaml@2.8.1):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 7.1.11(@types/node@24.8.1)(yaml@2.8.1)
|
||||
vite: 7.0.6(@types/node@24.7.2)(yaml@2.8.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
@@ -4176,7 +4190,7 @@ snapshots:
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite@7.1.11(@types/node@24.8.1)(yaml@2.8.1):
|
||||
vite@7.0.6(@types/node@24.7.2)(yaml@2.8.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.11
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
@@ -4189,11 +4203,11 @@ snapshots:
|
||||
fsevents: 2.3.3
|
||||
yaml: 2.8.1
|
||||
|
||||
vitest@3.2.4(@types/node@24.8.1)(jsdom@26.1.0)(yaml@2.8.1):
|
||||
vitest@3.2.4(@types/node@24.7.2)(jsdom@26.1.0)(yaml@2.8.1):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.2
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@7.1.11(@types/node@24.8.1)(yaml@2.8.1))
|
||||
'@vitest/mocker': 3.2.4(vite@7.0.6(@types/node@24.7.2)(yaml@2.8.1))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
@@ -4211,8 +4225,8 @@ snapshots:
|
||||
tinyglobby: 0.2.15
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 7.1.11(@types/node@24.8.1)(yaml@2.8.1)
|
||||
vite-node: 3.2.4(@types/node@24.8.1)(yaml@2.8.1)
|
||||
vite: 7.0.6(@types/node@24.7.2)(yaml@2.8.1)
|
||||
vite-node: 3.2.4(@types/node@24.7.2)(yaml@2.8.1)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 24.8.1
|
||||
@@ -4314,4 +4328,4 @@ snapshots:
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zxcvbn@4.4.2: {}
|
||||
zxcvbn@4.4.2: {}
|
||||
@@ -28,7 +28,7 @@ object Dependencies {
|
||||
val lettuce = "io.lettuce" % "lettuce-core" % "6.8.1.RELEASE"
|
||||
val nettyTransport =
|
||||
("io.netty" % s"netty-transport-native-$notifier" % "4.2.7.Final").classifier(s"$os-$arch")
|
||||
val lilaSearch = "com.github.lichess-org.lila-search" %% "client" % "3.2.4"
|
||||
val lilaSearch = "com.github.lichess-org.lila-search" %% "client" % "3.3.0"
|
||||
val munit = "org.scalameta" %% "munit" % "1.2.1" % Test
|
||||
val uaparser = "org.uaparser" %% "uap-scala" % "0.20.0"
|
||||
val apacheText = "org.apache.commons" % "commons-text" % "1.14.0"
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
<plurals name="nbBroadcasts">
|
||||
<item quantity="other">%s 個直播</item>
|
||||
</plurals>
|
||||
<plurals name="nbViewers">
|
||||
<item quantity="other">%s 位觀眾</item>
|
||||
</plurals>
|
||||
<string name="liveBroadcasts">錦標賽直播</string>
|
||||
<string name="broadcastCalendar">直播時程表</string>
|
||||
<string name="newBroadcast">新的現場直播</string>
|
||||
@@ -75,4 +78,5 @@
|
||||
<string name="allBroadcastsByMonth">以月份顯示所有直播</string>
|
||||
<string name="backToLiveMove">返回及時走法</string>
|
||||
<string name="sinceHideResults">由於您選擇隱藏結果,所有預覽棋盤都是空的,以避免劇透。</string>
|
||||
<string name="liveboard">實時棋局</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,26 +18,26 @@
|
||||
<string name="removedStudents">Уклоњени</string>
|
||||
<string name="inviteTheStudentBack">Позови ученика назад</string>
|
||||
<string name="sendAMessage">Пошаљи поруку свим ученицима.</string>
|
||||
<string name="aLinkToTheClassWillBeAdded">Линк за час ће бити аутоматски додат на крају поруке, нема потребе да га сами укључите.</string>
|
||||
<string name="aLinkToTheClassWillBeAdded">Линк до часа ће бити аутоматски додат на крају поруке, тако да не мораш сам/а да га убациш.</string>
|
||||
<string name="className">Назив часа</string>
|
||||
<string name="classDescription">Опис часа</string>
|
||||
<string name="visibleByBothStudentsAndTeachers">Видљиво и учитељима и ученицима овога часа</string>
|
||||
<string name="teachersOfTheClass">Учитељи</string>
|
||||
<string name="addLichessUsernames">Додајте Lichess корисничка имена да бисте их позвали да буду учитељи. Свако име у новом реду.</string>
|
||||
<string name="resetPassword">Обнови лозинку</string>
|
||||
<string name="visibleByBothStudentsAndTeachers">Видљиво и учитељима и ученицима часа</string>
|
||||
<string name="teachersOfTheClass">Учитељи часа</string>
|
||||
<string name="addLichessUsernames">Додај Lichess корисничка имена да их позовеш као учитеље. Једно по линији.</string>
|
||||
<string name="resetPassword">Промени лозинку</string>
|
||||
<string name="makeSureToCopy">Копирајте или запиђите лозинку. Нећете моћи да је поново видите!</string>
|
||||
<string name="passwordX">Лозинка: %s</string>
|
||||
<string name="generateANewPassword">Направите нову лозинку за ученика</string>
|
||||
<string name="invitedToXByY">Позван на %1$s од стране %2$s</string>
|
||||
<string name="generateANewPassword">Генериши нову лозинку за ученика</string>
|
||||
<string name="invitedToXByY">Позван/а на %1$s од стране %2$s</string>
|
||||
<string name="realName">Право име</string>
|
||||
<string name="privateWillNeverBeShown">Приватно. Никада неће бити приказано изван учионице. Помаже да се присетите ко је ученик.</string>
|
||||
<string name="addStudent">Додајте ученика</string>
|
||||
<string name="lichessProfileXCreatedForY">Личес налог %1$s направљен за %2$s.</string>
|
||||
<string name="addStudent">Додај ученика</string>
|
||||
<string name="lichessProfileXCreatedForY">Lichess профил %1$s направљен за %2$s.</string>
|
||||
<string name="studentCredentials">Ученик: %1$s
|
||||
Корисничко име: %2$s
|
||||
Лозинка: %3$s</string>
|
||||
<string name="inviteALichessAccount">Позовите Личес налог</string>
|
||||
<string name="inviteDesc1">Ако ученик већ има Lichess налог, можете их позвати на час.</string>
|
||||
<string name="inviteALichessAccount">Позови Lichess налог</string>
|
||||
<string name="inviteDesc1">Ако ученик већ има Lichess налог, можеш га/је позвати у час.</string>
|
||||
<string name="inviteDesc2">Примиће поруку на Lichess са везом да приступе часу.</string>
|
||||
<string name="inviteDesc3">Важно: позовите само ученике које познајете и који активно желе да се придруже часу.</string>
|
||||
<string name="inviteDesc4">Никада не шаљите позивнице насумичним играчима.</string>
|
||||
|
||||
@@ -115,4 +115,5 @@
|
||||
<string name="xIsAKidAccountWarning">%1$s 是未成年帳戶,無法接收您的消息。您必須手動給他發送邀請鏈接: %2$s</string>
|
||||
<string name="moveToClass">移動到 %s</string>
|
||||
<string name="moveToAnotherClass">移動到另一個課程</string>
|
||||
<string name="allowMessagingBetweenStudents">允許學生之間的消息</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<string name="emailConfirm_subject">%s,请确认您的 lichess.org 账户。</string>
|
||||
<string name="emailConfirm_click" comment="emailConfirm_click Part of the confirmation email upon registering for a Lichess account. The unique reset link is presented just after this string.">单击下列链接以激活您的 Lichess 帐户:</string>
|
||||
<string name="emailConfirm_justIgnore" comment="This text is included in the registration email for new users.">如果您没有注册 Lichess,您可以安全地忽略此消息。 未确认的账户和您邮箱地址的所有信息将在 48 小时后从我们的系统中删除。</string>
|
||||
<string name="emailConfirm_justIgnore" comment="This text is included in the registration email for new users.">如果您并未在 Lichess 注册,可放心忽略此邮件。未确认的账号及所有相关邮箱记录将在 48 小时后从系统中删除。</string>
|
||||
<string name="passwordReset_subject">%s,请重置您的 lichess.org 密码。</string>
|
||||
<string name="passwordReset_intro">我们收到了重置您账户密码的请求。</string>
|
||||
<string name="passwordReset_clickOrIgnore">如果是您发出了这个请求,请点击下方的链接,否则请忽略本邮件。</string>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<string name="xHasNoChessInsights">%s nie ma jeszcze wygenerowanych statystyk!</string>
|
||||
<string name="insightsAreProtected">Statystyki użytkownika %s są ukryte</string>
|
||||
<string name="cantSeeInsights">Nie masz dostępu do statystyk użytkownika %s.</string>
|
||||
<string name="generateInsights">Wygeneruj statystyki szachowe dla użytkownika %s.</string>
|
||||
<string name="generateInsights" comment="%s is a player's username. Clicking this will scan data on Lichess to create insights for player %s. Example: Generate DrNykterstein's chess insights.">Wygeneruj statystyki szachowe dla użytkownika %s.</string>
|
||||
<string name="crunchingData">Teraz przetwarzamy dane tylko dla ciebie!</string>
|
||||
<string name="maybeAskThemToChangeTheir" comment="The parameter is the translation for 'insights settings'">Może poprosić ich o zmianę %s?</string>
|
||||
<string name="insightsSettings" comment="In the context of 'maybe ask them to change their insight settings'">ustawienia dostępności statystyk</string>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<string name="whitePawn">biały pion</string>
|
||||
<string name="blackPawn">czarny pion</string>
|
||||
<string name="sanSymbols" comment="Keep this order: king queen rook bishop knight takes">K Q R B N x</string>
|
||||
<string name="sanTakes" comment="Indicates a piece captured another piece as part of a longer sentence. Examples: "knight takes f 3" "e takes f 3" The exact format can vary depending on the user's preferences. See the screenshot for the options as of 2025-08-23. Used only in blind mode when the screen reader verbally announces a move. 'Takes' corresponds to "x" in Standard Algebraic Notation, for pieces being captured.">zbija</string>
|
||||
<string name="sanTakes" comment="Indicates a piece captured another piece as part of a longer sentence. Examples: "knight takes f 3" "e takes f 3" The exact format can vary depending on the user's preferences. Used only in blind mode when the screen reader verbally announces a move. "Takes" corresponds to "x" in Standard Algebraic Notation, for pieces being captured.">zbija</string>
|
||||
<string name="sanCheck" comment="+ in standard notation">szach</string>
|
||||
<string name="sanCheckmate" comment="# in standard notation">mat</string>
|
||||
<string name="sanPromotesTo" comment="Indicates a piece is promoted, as part of a longer sentence. Examples: "e promotes to queen" Used only in blind mode when the screen reader verbally announces a move. 'Takes' corresponds to "=" in Standard Algebraic Notation, for pieces being promoted.">promuje do</string>
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<string name="logInAsUsername">%s 已登录</string>
|
||||
<string name="welcome">欢迎!</string>
|
||||
<string name="welcomeToLichess">欢迎来到 Lichess!</string>
|
||||
<string name="thisIsYourProfilePage">这是你的个人资料页面。</string>
|
||||
<string name="enabledKidModeSuggestion">如果此账户是为儿童创建的,那你可能会想启用 %s。</string>
|
||||
<string name="whatNowSuggestions">接下来做什么?以下是一些建议:</string>
|
||||
<string name="learnChessRules">学习国际象棋的规则</string>
|
||||
<string name="improveWithChessTacticsPuzzles">练习谜题以提高战术技巧</string>
|
||||
<string name="playTheArtificialIntelligence">和 AI 对战</string>
|
||||
<string name="playOpponentsFromAroundTheWorld">和世界各地的棋手对战</string>
|
||||
<string name="followYourFriendsOnLichess">在 Lichess 上关注你的朋友们</string>
|
||||
<string name="playInTournaments">参与锦标赛</string>
|
||||
<string name="thisIsYourProfilePage">这是您的个人资料页。</string>
|
||||
<string name="enabledKidModeSuggestion">如果此账户是为儿童创建的,那您可能需要启用 %s。</string>
|
||||
<string name="whatNowSuggestions">现在做什么?这里有一些建议:</string>
|
||||
<string name="learnChessRules">学习国象规则</string>
|
||||
<string name="improveWithChessTacticsPuzzles">通过战术谜题提升棋艺</string>
|
||||
<string name="playTheArtificialIntelligence">与 AI 对弈</string>
|
||||
<string name="playOpponentsFromAroundTheWorld">与来自世界各地的棋手对弈</string>
|
||||
<string name="followYourFriendsOnLichess">在 Lichess 上关注您的朋友</string>
|
||||
<string name="playInTournaments">参加锦标赛</string>
|
||||
<string name="learnFromXAndY">从 %1$s 和 %2$s 中学习</string>
|
||||
<string name="configureLichess">根据您的偏好配置 Lichess</string>
|
||||
<string name="exploreTheSiteAndHaveFun">探索网站,愉快下棋 :)</string>
|
||||
<string name="configureLichess">根据您的喜好配置 Lichess</string>
|
||||
<string name="exploreTheSiteAndHaveFun">探索本站,祝您玩得开心 :)</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<string name="gameSetup">게임 설정</string>
|
||||
<string name="challengeAFriend" comment="be mindful how 'friend' translates in gendered languages. look for a more neutral term if there's an issue, or base your translation on a different phrase like 'invite to a game'. keep it short and convey the button's meaning without offense.">친구에게 도전</string>
|
||||
<string name="playAgainstComputer">컴퓨터와 대국하기</string>
|
||||
<string name="gameMode">게임 모드</string>
|
||||
<string name="createLobbyGame" comment="One of three buttons on the home page. Opens the modal to create a game that goes in the lobby.">로비 게임 만들기</string>
|
||||
<string name="youPlayAs">당신은 재생</string>
|
||||
@@ -837,6 +838,7 @@
|
||||
<string name="playVariationToCreateConditionalPremoves">기물을 움직여 조건적인 수를 만들기</string>
|
||||
<string name="noConditionalPremoves">조건적인 수가 없습니다</string>
|
||||
<string name="playX">%s 를 둠</string>
|
||||
<string name="challengeX">%s에게 도전하기</string>
|
||||
<plurals name="andSaveNbPremoveLines">
|
||||
<item quantity="other">%s 종류의 조건 수를 설정</item>
|
||||
</plurals>
|
||||
@@ -966,4 +968,7 @@ FEN 포지션을 생성하기 위해 %s를 사용할 수 있습니다.
|
||||
<string name="accessibility">접근성</string>
|
||||
<string name="enableBlindMode">시각장애 모드 활성화하기</string>
|
||||
<string name="disableBlindMode">시각장애 모드 비활성화하기</string>
|
||||
<string name="copyToClipboard">클립보드에 복사</string>
|
||||
<string name="online" comment="status of a user">온라인</string>
|
||||
<string name="offline" comment="status of a user">오프라인</string>
|
||||
</resources>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<string name="challengeAFriend" comment="be mindful how 'friend' translates in gendered languages. look for a more neutral term if there's an issue, or base your translation on a different phrase like 'invite to a game'. keep it short and convey the button's meaning without offense.">Daag een vriend uit</string>
|
||||
<string name="playAgainstComputer">Speel tegen de computer</string>
|
||||
<string name="gameMode">Spelmodus</string>
|
||||
<string name="createLobbyGame" comment="One of three buttons on the home page. Opens the modal to create a game that goes in the lobby.">Maak een lobby spel aan</string>
|
||||
<string name="youPlayAs">Je speelt als</string>
|
||||
<string name="toInviteSomeoneToPlayGiveThisUrl">Deel deze link als u iemand wil uitnodigen om met u te spelen</string>
|
||||
<string name="gameOver">Partij afgelopen</string>
|
||||
@@ -344,6 +345,7 @@
|
||||
<item quantity="other">%s bezig</item>
|
||||
</plurals>
|
||||
<string name="exportGames">Partijen exporteren</string>
|
||||
<string name="ratingFilter">Filter van rating</string>
|
||||
<plurals name="giveNbSeconds">
|
||||
<item quantity="one">Geef %s seconde</item>
|
||||
<item quantity="other">Geef %s seconden</item>
|
||||
@@ -828,6 +830,7 @@
|
||||
<string name="notifications">Meldingen</string>
|
||||
<string name="notificationsX">Meldingen: %1$s</string>
|
||||
<string name="perfRatingX">Rating: %s</string>
|
||||
<string name="yourRatingIsX">Uw rating is %s</string>
|
||||
<plurals name="nbSecondsToPlayTheFirstMove">
|
||||
<item quantity="one">%s seconde om de eerste zet te spelen</item>
|
||||
<item quantity="other">%s seconden om de eerste zet te spelen</item>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="gameSetup">棋局設置</string>
|
||||
<string name="challengeAFriend" comment="be mindful how 'friend' translates in gendered languages. look for a more neutral term if there's an issue, or base your translation on a different phrase like 'invite to a game'. keep it short and convey the button's meaning without offense.">挑戰一位朋友</string>
|
||||
<string name="playAgainstComputer">與電腦對局</string>
|
||||
<string name="gameMode">遊戲模式</string>
|
||||
<string name="toInviteSomeoneToPlayGiveThisUrl">請分享此網址以邀人下棋</string>
|
||||
<string name="gameOver">遊戲結束</string>
|
||||
<string name="waitingForOpponent">正在等待對手</string>
|
||||
@@ -20,6 +24,7 @@
|
||||
<string name="asBlack">作為黑方</string>
|
||||
<string name="randomColor">隨機選色</string>
|
||||
<string name="createAGame">開始對局</string>
|
||||
<string name="createTheGame">創建對局</string>
|
||||
<string name="whiteIsVictorious">白方勝</string>
|
||||
<string name="blackIsVictorious">黑方勝</string>
|
||||
<string name="youPlayTheWhitePieces">您執白棋</string>
|
||||
@@ -154,6 +159,7 @@
|
||||
<string name="drawByMutualAgreement">雙方同意和局</string>
|
||||
<string name="fiftyMovesWithoutProgress">50步規則和局</string>
|
||||
<string name="currentGames">當前對局</string>
|
||||
<string name="joinedX">於 %s 加入</string>
|
||||
<plurals name="nbGames">
|
||||
<item quantity="other">查看所有%s盤棋</item>
|
||||
</plurals>
|
||||
@@ -319,7 +325,15 @@
|
||||
<string name="openingExplorerAndTablebase">開局瀏覽器 & 總局資料庫</string>
|
||||
<string name="takeback">悔棋</string>
|
||||
<string name="proposeATakeback">請求悔棋</string>
|
||||
<string name="whiteProposesTakeback">白方提議悔棋</string>
|
||||
<string name="blackProposesTakeback">黑方提議悔棋</string>
|
||||
<string name="takebackPropositionSent">悔棋請求已發送</string>
|
||||
<string name="whiteDeclinesTakeback">白方拒絕悔棋</string>
|
||||
<string name="blackDeclinesTakeback">黑方拒絕悔棋</string>
|
||||
<string name="whiteAcceptsTakeback">白方同意悔棋</string>
|
||||
<string name="blackAcceptsTakeback">黑方同意悔棋</string>
|
||||
<string name="whiteCancelsTakeback">白方取消悔棋</string>
|
||||
<string name="blackCancelsTakeback">黑方取消悔棋</string>
|
||||
<string name="yourOpponentProposesATakeback">對手請求悔棋</string>
|
||||
<string name="bookmarkThisGame">收藏該棋局</string>
|
||||
<string name="tournament">錦標賽</string>
|
||||
@@ -698,6 +712,7 @@
|
||||
<string name="downloadAnnotated">下載含有棋子走動方向的棋局</string>
|
||||
<string name="downloadRaw">下載純文字</string>
|
||||
<string name="downloadImported">下載導入的棋局</string>
|
||||
<string name="downloadAllGames">下載所有棋局</string>
|
||||
<string name="crosstable">歷程表</string>
|
||||
<string name="youCanAlsoScrollOverTheBoardToMoveInTheGame">您也可以捲動棋盤以移動。</string>
|
||||
<string name="scrollOverComputerVariationsToPreviewThem">將鼠標移到電腦分析變種上進行預覽</string>
|
||||
@@ -733,6 +748,7 @@
|
||||
<string name="anonymous">匿名用户</string>
|
||||
<string name="yourScore">您的分數:%s</string>
|
||||
<string name="language">語言</string>
|
||||
<string name="allLanguages">所有語言</string>
|
||||
<string name="background">背景</string>
|
||||
<string name="light">亮</string>
|
||||
<string name="dark">暗</string>
|
||||
@@ -937,4 +953,10 @@
|
||||
一切營運成本、開發和內容皆來自用戶之捐贈。</string>
|
||||
<string name="nothingToSeeHere">目前這裡沒有什麼好看的。</string>
|
||||
<string name="stats">統計</string>
|
||||
<string name="copyToClipboard">複製到剪貼簿</string>
|
||||
<string name="online" comment="status of a user">在線</string>
|
||||
<string name="offline" comment="status of a user">離線</string>
|
||||
<string name="search">搜索</string>
|
||||
<string name="clearSearch">清除搜索</string>
|
||||
<string name="tags">標籤</string>
|
||||
</resources>
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<string name="studyPgn">研究 PGN</string>
|
||||
<string name="chapterPgn">章節PGN</string>
|
||||
<string name="copyChapterPgn">複製PGN</string>
|
||||
<string name="copyRawChapterPgn">複製純 PGN</string>
|
||||
<string name="downloadGame">下載棋局</string>
|
||||
<string name="studyUrl">研究連結</string>
|
||||
<string name="currentChapterUrl">目前章節連結</string>
|
||||
|
||||
@@ -42,10 +42,10 @@
|
||||
<item quantity="other">%s 年前</item>
|
||||
</plurals>
|
||||
<plurals name="nbMinutesRemaining">
|
||||
<item quantity="other">还剩 %s 分钟</item>
|
||||
<item quantity="other">剩余 %s 分钟</item>
|
||||
</plurals>
|
||||
<plurals name="nbHoursRemaining">
|
||||
<item quantity="other">还剩 %s 小时</item>
|
||||
<item quantity="other">剩余 %s 小时</item>
|
||||
</plurals>
|
||||
<string name="completed">已完成</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="community">社群</string>
|
||||
<string name="myFriends">我的朋友</string>
|
||||
<string name="myLikes" comment="A page which lists blog posts that you have pressed ❤️ Like on: https://lichess.org/blog/liked">我的點讚</string>
|
||||
<string name="myBlog">我的部落格</string>
|
||||
<string name="likedBlogs">已喜歡的部落格</string>
|
||||
<plurals name="blogPosts">
|
||||
|
||||
@@ -768,7 +768,8 @@
|
||||
<string name="crosstable">Crosstable</string>
|
||||
<string name="youCanAlsoScrollOverTheBoardToMoveInTheGame">Scroll over the board to move in the game.</string>
|
||||
<string name="scrollOverComputerVariationsToPreviewThem">Scroll over computer variations to preview them.</string>
|
||||
<string name="analysisShapesHowTo">Press shift+click or right-click to draw circles and arrows on the board.</string>
|
||||
<string name="analysisShapesHowTo">Press right-click (or shift+click) to draw circles and arrows on the board. For other colours, combine the following with right-click:</string>
|
||||
<string name="primaryColorArrowsHowTo">Ctrl or shift = red; command, alt, or meta = blue; a key from each = yellow.</string>
|
||||
<string name="letOtherPlayersMessageYou">Let other players message you</string>
|
||||
<string name="receiveForumNotifications">Receive notifications when mentioned in the forum</string>
|
||||
<string name="shareYourInsightsData">Share your chess insights data</string>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<string name="recentlyUpdated">Recently updated</string>
|
||||
<string name="mostPopular">Most popular</string>
|
||||
<string name="alphabetical">Alphabetical</string>
|
||||
<string name="relevant">Relevant</string>
|
||||
<string name="addNewChapter">Add a new chapter</string>
|
||||
<plurals name="nbChapters">
|
||||
<item quantity="one">%s Chapter</item>
|
||||
|
||||
@@ -120,7 +120,7 @@ async function splitConfig(cfgPath: string): Promise<SplitConfig[]> {
|
||||
co.noImplicitReturns = false;
|
||||
co.noUnusedParameters = false;
|
||||
}
|
||||
co.lib = co.lib?.map((lib: string) => /lib\.(.+)\.d\.ts/.exec(lib)?.[1] ?? lib);
|
||||
co.lib = co.lib?.map((lib: string) => lib.match(/lib\.(.+)\.d\.ts/)?.[1] ?? lib);
|
||||
co.pathsBasePath = undefined;
|
||||
co.incremental = true;
|
||||
config.compilerOptions = co;
|
||||
|
||||
Vendored
+5
-1
@@ -2895,7 +2895,7 @@ interface I18n {
|
||||
analysis: string;
|
||||
/** Analysis options */
|
||||
analysisOptions: string;
|
||||
/** Press shift+click or right-click to draw circles and arrows on the board. */
|
||||
/** Press right-click (or shift+click) to draw circles and arrows on the board. For other colours, combine the following with right-click: */
|
||||
analysisShapesHowTo: string;
|
||||
/** and save %s premove lines */
|
||||
andSaveNbPremoveLines: I18nPlural;
|
||||
@@ -3917,6 +3917,8 @@ interface I18n {
|
||||
practiceWithComputer: string;
|
||||
/** Previously on Lichess TV */
|
||||
previouslyOnLichessTV: string;
|
||||
/** Ctrl or shift = red; command, alt, or meta = blue; a key from each = yellow. */
|
||||
primaryColorArrowsHowTo: string;
|
||||
/** Privacy */
|
||||
privacy: string;
|
||||
/** Privacy policy */
|
||||
@@ -5059,6 +5061,8 @@ interface I18n {
|
||||
readMoreAboutEmbedding: string;
|
||||
/** Recently updated */
|
||||
recentlyUpdated: string;
|
||||
/** Relevant */
|
||||
relevant: string;
|
||||
/** Right under the board */
|
||||
rightUnderTheBoard: string;
|
||||
/** Save */
|
||||
|
||||
@@ -126,5 +126,14 @@ $col2-panel-height: 240px;
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.game-duration {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 1.5em;
|
||||
pointer-events: none;
|
||||
font-family: Roboto, sans-serif;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@
|
||||
content: $licon-X;
|
||||
}
|
||||
[data-mode='ceval']::after {
|
||||
content: $licon-Cpu;
|
||||
content: $licon-Cogs;
|
||||
color: $c-font-dimmer;
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
[data-mode='ceval']:has(eval)::after {
|
||||
|
||||
@@ -648,6 +648,10 @@ export default class AnalyseCtrl implements CevalHandler {
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
allowedEval(node: Tree.Node = this.node): Tree.ClientEval | Tree.ServerEval | false | undefined {
|
||||
return (this.cevalEnabled() && node.ceval) || (this.showFishnetAnalysis() && node.eval);
|
||||
}
|
||||
|
||||
outcome(node?: Tree.Node): Outcome | undefined {
|
||||
return this.position(node || this.node).unwrap(
|
||||
pos => pos.outcome(),
|
||||
|
||||
@@ -162,14 +162,14 @@ export class InlineView {
|
||||
?.map(g => this.glyphs[g.id - 1])
|
||||
.filter(Boolean)
|
||||
.forEach(cls => (classes[cls] = true));
|
||||
|
||||
return hl('move', { attrs: { p: path }, class: classes }, [
|
||||
parentDisclose && this.disclosureBtn(parentNode, parentPath),
|
||||
withIndex && renderIndex(node.ply, true),
|
||||
renderMoveNodes(
|
||||
node,
|
||||
ctrl.showFishnetAnalysis() && isMainline && !this.inline,
|
||||
isMainline && !this.inline,
|
||||
(!!ctrl.study && !ctrl.study.relay) || ctrl.showFishnetAnalysis(),
|
||||
ctrl.allowedEval(node) || false,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -298,9 +298,20 @@ export const renderIndexAndMove = (node: Tree.Node, withEval: boolean, withGlyph
|
||||
export const renderIndex = (ply: Ply, withDots: boolean): VNode =>
|
||||
hl(`index.sbhint${ply}`, plyToTurn(ply) + (withDots ? (ply % 2 === 1 ? '.' : '...') : ''));
|
||||
|
||||
export function renderMoveNodes(node: Tree.Node, withEval: boolean, withGlyphs: boolean): LooseVNodes {
|
||||
const ev = node.ceval ?? node.eval;
|
||||
const evalText = ev?.cp !== undefined ? normalizeEval(ev.cp) : ev?.mate !== undefined ? `#${ev.mate}` : '';
|
||||
export function renderMoveNodes(
|
||||
node: Tree.Node,
|
||||
withEval: boolean,
|
||||
withGlyphs: boolean,
|
||||
ev?: Tree.ClientEval | Tree.ServerEval | false,
|
||||
): LooseVNodes {
|
||||
ev ??= node.ceval ?? node.eval; // ev = false will override withEval
|
||||
const evalText = !ev
|
||||
? ''
|
||||
: ev?.cp !== undefined
|
||||
? normalizeEval(ev.cp)
|
||||
: ev?.mate !== undefined
|
||||
? `#${ev.mate}`
|
||||
: '';
|
||||
return [
|
||||
hl('san', fixCrazySan(node.san!)),
|
||||
withGlyphs && node.glyphs?.map(g => hl('glyph', { attrs: { title: g.name } }, g.symbol)),
|
||||
|
||||
@@ -99,7 +99,7 @@ function renderPracticeTab(ctrl: AnalyseCtrl): LooseVNode {
|
||||
|
||||
function renderMobileCevalTab(ctrl: AnalyseCtrl): LooseVNode {
|
||||
const engineMode = ctrl.activeControlMode() || 'ceval',
|
||||
ev = ctrl.node.ceval ?? (ctrl.showFishnetAnalysis() ? ctrl.node.eval : undefined),
|
||||
ev = ctrl.allowedEval() || undefined,
|
||||
evalstr = ev?.cp !== undefined ? renderEval(ev.cp) : ev?.mate ? '#' + ev.mate : '',
|
||||
active = ctrl.activeControlMode() && !ctrl.activeControlBarTool(),
|
||||
latent = ctrl.activeControlMode() && !!ctrl.activeControlBarTool();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"@types/zxcvbn": "^4.4.5",
|
||||
"@yaireo/tagify": "4.17.9",
|
||||
"canvas-confetti": "^1.9.3",
|
||||
"cropperjs": "^1.6.2",
|
||||
"cropperjs": "1.6.2",
|
||||
"debounce-promise": "^3.1.2",
|
||||
"emoji-mart": "^5.6.0",
|
||||
"flatpickr": "^4.6.13",
|
||||
|
||||
@@ -137,7 +137,11 @@ type Composition = { boards: number; squares: Map<number, Map<Color, Map<co.Role
|
||||
|
||||
async function makeCover(polyglotBook: OpeningBook, boardSize: number, numMoves?: number): Promise<Blob> {
|
||||
const squareSize = boardSize / 8;
|
||||
|
||||
if (typeof OffscreenCanvas !== 'function') throw 'no OffscreenCanvas support';
|
||||
// eslint-disable-next-line compat/compat
|
||||
const canvas = new OffscreenCanvas(boardSize, boardSize);
|
||||
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
const composition: Composition = { boards: 1, squares: new Map() };
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
"skipLibCheck": true,
|
||||
"noImplicitReturns": false
|
||||
},
|
||||
"references": [{ "path": "../lib/tsconfig.json" }, { "path": "../voice/tsconfig.json" }]
|
||||
"references": [{ "path": "../lib/tsconfig.json" }]
|
||||
}
|
||||
|
||||
@@ -206,6 +206,9 @@ export default async function (
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (moveCentis) addGameDuration(el, moveCentis);
|
||||
|
||||
const movetimeChart = new Chart(el, config) as PlyChart;
|
||||
movetimeChart.selectPly = selectPly.bind(movetimeChart);
|
||||
pubsub.on('ply', movetimeChart.selectPly);
|
||||
@@ -213,6 +216,14 @@ export default async function (
|
||||
return movetimeChart;
|
||||
}
|
||||
|
||||
const addGameDuration = (el: HTMLCanvasElement, moveCentis: number[]) => {
|
||||
const chart = $(el);
|
||||
let label = chart.next('.game-duration');
|
||||
if (!label.length) label = $('<div class="game-duration">').insertAfter(chart);
|
||||
const duration = moveCentis.reduce((s, v) => s + v, 0);
|
||||
label.text(i18n.site.duration + ' ' + formatClock(duration));
|
||||
};
|
||||
|
||||
const toBlurArray = (player: Player) =>
|
||||
player.blurs && player.blurs.bits ? player.blurs.bits.split('') : [];
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ export const highlightSearchTerm = (search: string, selector: string): void => {
|
||||
}
|
||||
if (ranges.length === 0) return;
|
||||
// create a CSS highlight that can be styled with the ::highlight(search) pseudo-element
|
||||
|
||||
if (typeof Highlight !== 'function') throw 'no Highlight support';
|
||||
// eslint-disable-next-line compat/compat
|
||||
const highlight = new Highlight(...ranges);
|
||||
CSS.highlights.set(highlightName, highlight);
|
||||
};
|
||||
|
||||
@@ -18,14 +18,15 @@ function primer() {
|
||||
}
|
||||
|
||||
function acquire() {
|
||||
navigator.wakeLock
|
||||
?.request('screen')
|
||||
.then(sentinel => {
|
||||
wakeLock = sentinel;
|
||||
primerEvents.forEach(e => window.removeEventListener(e, primer, { capture: true }));
|
||||
primerEvents = [];
|
||||
})
|
||||
.catch(() => (wakeLock = null));
|
||||
if ('wakeLock' in navigator)
|
||||
navigator.wakeLock
|
||||
?.request('screen')
|
||||
.then(sentinel => {
|
||||
wakeLock = sentinel;
|
||||
primerEvents.forEach(e => window.removeEventListener(e, primer, { capture: true }));
|
||||
primerEvents = [];
|
||||
})
|
||||
.catch(() => (wakeLock = null));
|
||||
}
|
||||
|
||||
// safari will only grant wakeLock on a user interaction, and without that initial grant
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
&::before {
|
||||
@extend %data-icon;
|
||||
font-size: 1.7em;
|
||||
font-size: 32px;
|
||||
color: $c-font-dimmer;
|
||||
}
|
||||
&--hook.button::before {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"target": "es2020",
|
||||
"lib": ["es2020", "webworker"],
|
||||
"lib": ["es2020", "WebWorker"],
|
||||
"types": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": { "noEmit": true, "isolatedDeclarations": false },
|
||||
"references": [{ "path": "../lib/tsconfig.json" }, { "path": "../bits/tsconfig.json" }]
|
||||
"references": [{ "path": "../lib/tsconfig.json" }]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
"libReplacement": false,
|
||||
"moduleResolution": "Node",
|
||||
"module": "ESNext",
|
||||
"target": "ES2020",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"target": "ES2021",
|
||||
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
||||
"types": ["lichess"],
|
||||
"paths": {
|
||||
"@/*": ["${configDir}/src/*"]
|
||||
|
||||
Reference in New Issue
Block a user