mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-02-16 09:21:45 +02:00
import scaffoldings
This commit is contained in:
parent
95f9d685dc
commit
f459dd8812
@ -21,6 +21,7 @@ func BindCollectionApi(app core.App, rg *echo.Group) {
|
||||
subGroup.GET("/:collection", api.view)
|
||||
subGroup.PATCH("/:collection", api.update)
|
||||
subGroup.DELETE("/:collection", api.delete)
|
||||
subGroup.POST("/import", api.bulkImport)
|
||||
}
|
||||
|
||||
type collectionApi struct {
|
||||
@ -167,3 +168,19 @@ func (api *collectionApi) delete(c echo.Context) error {
|
||||
|
||||
return handlerErr
|
||||
}
|
||||
|
||||
func (api *collectionApi) bulkImport(c echo.Context) error {
|
||||
form := forms.NewCollectionsImport(api.app)
|
||||
|
||||
// load request
|
||||
if err := c.Bind(form); err != nil {
|
||||
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||
}
|
||||
|
||||
submitErr := form.Submit()
|
||||
if submitErr != nil {
|
||||
return rest.NewBadRequestError("Failed to import the submitted collections.", submitErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
12
daos/base.go
12
daos/base.go
@ -128,7 +128,7 @@ func (dao *Dao) Delete(m models.Model) error {
|
||||
|
||||
// Save upserts (update or create if primary key is not set) the provided model.
|
||||
func (dao *Dao) Save(m models.Model) error {
|
||||
if m.HasId() {
|
||||
if !m.IsNew() {
|
||||
return dao.update(m)
|
||||
}
|
||||
|
||||
@ -140,6 +140,10 @@ func (dao *Dao) update(m models.Model) error {
|
||||
return errors.New("ID is not set")
|
||||
}
|
||||
|
||||
if m.GetCreated().IsZero() {
|
||||
m.RefreshCreated()
|
||||
}
|
||||
|
||||
m.RefreshUpdated()
|
||||
|
||||
if dao.BeforeUpdateFunc != nil {
|
||||
@ -195,6 +199,9 @@ func (dao *Dao) create(m models.Model) error {
|
||||
|
||||
if v, ok := any(m).(models.ColumnValueMapper); ok {
|
||||
dataMap := v.ColumnValueMap()
|
||||
if _, ok := dataMap["id"]; !ok {
|
||||
dataMap["id"] = m.GetId()
|
||||
}
|
||||
|
||||
_, err := dao.db.Insert(m.TableName(), dataMap).Execute()
|
||||
if err != nil {
|
||||
@ -206,6 +213,9 @@ func (dao *Dao) create(m models.Model) error {
|
||||
}
|
||||
}
|
||||
|
||||
// clears the internal isNewFlag
|
||||
m.UnmarkAsNew()
|
||||
|
||||
if dao.AfterCreateFunc != nil {
|
||||
dao.AfterCreateFunc(dao, m)
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ func (dao *Dao) DeleteCollection(collection *models.Collection) error {
|
||||
func (dao *Dao) SaveCollection(collection *models.Collection) error {
|
||||
var oldCollection *models.Collection
|
||||
|
||||
if collection.HasId() {
|
||||
if !collection.IsNew() {
|
||||
// get the existing collection state to compare with the new one
|
||||
// note: the select is outside of the transaction to prevent SQLITE_LOCKED error when mixing read&write in a single transaction
|
||||
var findErr error
|
||||
|
@ -147,6 +147,40 @@ func (dao *Dao) IsRecordValueUnique(
|
||||
return err == nil && !exists
|
||||
}
|
||||
|
||||
// IsRecordValueUnique checks if the provided key-value pair is a unique Record value.
|
||||
//
|
||||
// NB! Array values (eg. from multiple select fields) are matched
|
||||
// as a serialized json strings (eg. `["a","b"]`), so the value uniqueness
|
||||
// depends on the elements order. Or in other words the following values
|
||||
// are considered different: `[]string{"a","b"}` and `[]string{"b","a"}`
|
||||
func (dao *Dao) IsRecordUnique(
|
||||
collection *models.Collection,
|
||||
key string,
|
||||
value any,
|
||||
excludeId string,
|
||||
) bool {
|
||||
var exists bool
|
||||
|
||||
var normalizedVal any
|
||||
switch val := value.(type) {
|
||||
case []string:
|
||||
normalizedVal = append(types.JsonArray{}, list.ToInterfaceSlice(val)...)
|
||||
case []any:
|
||||
normalizedVal = append(types.JsonArray{}, val...)
|
||||
default:
|
||||
normalizedVal = val
|
||||
}
|
||||
|
||||
err := dao.RecordQuery(collection).
|
||||
Select("count(*)").
|
||||
AndWhere(dbx.Not(dbx.HashExp{"id": excludeId})).
|
||||
AndWhere(dbx.HashExp{key: normalizedVal}).
|
||||
Limit(1).
|
||||
Row(&exists)
|
||||
|
||||
return err == nil && !exists
|
||||
}
|
||||
|
||||
// FindUserRelatedRecords returns all records that has a reference
|
||||
// to the provided User model (via the user shema field).
|
||||
func (dao *Dao) FindUserRelatedRecords(user *models.User) ([]*models.Record, error) {
|
||||
|
@ -36,7 +36,7 @@ func NewCollectionUpsert(app core.App, collection *models.Collection) *Collectio
|
||||
form := &CollectionUpsert{
|
||||
app: app,
|
||||
collection: collection,
|
||||
isCreate: !collection.HasId(),
|
||||
isCreate: collection.IsNew(),
|
||||
}
|
||||
|
||||
// load defaults
|
||||
|
151
forms/collections_import.go
Normal file
151
forms/collections_import.go
Normal file
@ -0,0 +1,151 @@
|
||||
package forms
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
// CollectionsImport defines a bulk collections import form.
|
||||
type CollectionsImport struct {
|
||||
app core.App
|
||||
|
||||
Collections []*models.Collection `form:"collections" json:"collections"`
|
||||
DeleteOthers bool `form:"deleteOthers" json:"deleteOthers"`
|
||||
}
|
||||
|
||||
// NewCollectionsImport bulk imports (create, replace and delete)
|
||||
// a user provided list with collections data.
|
||||
func NewCollectionsImport(app core.App) *CollectionsImport {
|
||||
form := &CollectionsImport{
|
||||
app: app,
|
||||
}
|
||||
|
||||
return form
|
||||
}
|
||||
|
||||
// Validate makes the form validatable by implementing [validation.Validatable] interface.
|
||||
func (form *CollectionsImport) Validate() error {
|
||||
return validation.ValidateStruct(form,
|
||||
validation.Field(&form.Collections, validation.Required),
|
||||
)
|
||||
}
|
||||
|
||||
// Submit applies the import, aka.:
|
||||
// - imports the form collections (create or replace)
|
||||
// - sync the collection changes with their related records table
|
||||
// - ensures the integrity of the imported structure (aka. run validations for each collection)
|
||||
// - if [form.DeleteOthers] is set, deletes all local collections that are not found in the imports list
|
||||
//
|
||||
// All operations are wrapped in a single transaction that are
|
||||
// rollbacked on the first encountered error.
|
||||
func (form *CollectionsImport) Submit() error {
|
||||
if err := form.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// @todo validate id length in the form
|
||||
return form.app.Dao().RunInTransaction(func(txDao *daos.Dao) error {
|
||||
oldCollections := []*models.Collection{}
|
||||
if err := txDao.CollectionQuery().All(&oldCollections); err != nil {
|
||||
return err
|
||||
}
|
||||
mappedOldCollections := make(map[string]*models.Collection, len(oldCollections))
|
||||
for _, old := range oldCollections {
|
||||
mappedOldCollections[old.GetId()] = old
|
||||
}
|
||||
|
||||
// raw insert/replace (aka. without any validations)
|
||||
// (required to make sure that all linked collections exists before running the validations)
|
||||
mappedFormCollections := make(map[string]*models.Collection, len(form.Collections))
|
||||
for _, collection := range form.Collections {
|
||||
if mappedOldCollections[collection.GetId()] == nil {
|
||||
collection.MarkAsNew()
|
||||
}
|
||||
|
||||
if err := txDao.Save(collection); err != nil {
|
||||
if form.app.IsDebug() {
|
||||
log.Println("[CollectionsImport] Save failure", collection.Name, err)
|
||||
}
|
||||
return validation.Errors{"collections": validation.NewError(
|
||||
"collections_import_save_failure",
|
||||
fmt.Sprintf("Failed to save the imported collection %q (id: %s).", collection.Name, collection.Id),
|
||||
)}
|
||||
}
|
||||
|
||||
mappedFormCollections[collection.GetId()] = collection
|
||||
}
|
||||
|
||||
// delete all other collections not sent with the import
|
||||
if form.DeleteOthers {
|
||||
for _, old := range oldCollections {
|
||||
if mappedFormCollections[old.GetId()] == nil {
|
||||
// delete the collection
|
||||
if err := txDao.DeleteCollection(old); err != nil {
|
||||
if form.app.IsDebug() {
|
||||
log.Println("[CollectionsImport] DeleteOthers failure", old.Name, err)
|
||||
}
|
||||
return validation.Errors{"deleteOthers": validation.NewError(
|
||||
"collections_import_collection_delete_failure",
|
||||
fmt.Sprintf("Failed to delete collection %q. Make sure that the collection is not system or referenced by other collections.", old.Name),
|
||||
)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// refresh the actual persisted collections list
|
||||
refreshedCollections := []*models.Collection{}
|
||||
if err := txDao.CollectionQuery().All(&refreshedCollections); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// trigger the validator for each existing collection to
|
||||
// ensure that the app is not left in a broken state
|
||||
for _, collection := range refreshedCollections {
|
||||
upsertModel := mappedOldCollections[collection.GetId()]
|
||||
if upsertModel == nil {
|
||||
upsertModel = &models.Collection{}
|
||||
}
|
||||
upsertForm := NewCollectionUpsert(form.app, upsertModel)
|
||||
// load form fields with the refreshed collection state
|
||||
upsertForm.Name = collection.Name
|
||||
upsertForm.System = collection.System
|
||||
upsertForm.ListRule = collection.ListRule
|
||||
upsertForm.ViewRule = collection.ViewRule
|
||||
upsertForm.CreateRule = collection.CreateRule
|
||||
upsertForm.UpdateRule = collection.UpdateRule
|
||||
upsertForm.DeleteRule = collection.DeleteRule
|
||||
upsertForm.Schema = collection.Schema
|
||||
if err := upsertForm.Validate(); err != nil {
|
||||
if form.app.IsDebug() {
|
||||
log.Println("[CollectionsImport] Validate failure", collection.Name, err)
|
||||
}
|
||||
return validation.Errors{"collections": validation.NewError(
|
||||
"collections_import_validate_failure",
|
||||
fmt.Sprintf("Integrity check failed - collection %q has invalid data.", collection.Name),
|
||||
)}
|
||||
}
|
||||
}
|
||||
|
||||
// sync the records table for each updated collection
|
||||
for _, collection := range form.Collections {
|
||||
oldCollection := mappedOldCollections[collection.GetId()]
|
||||
if err := txDao.SyncRecordTableSchema(collection, oldCollection); err != nil {
|
||||
if form.app.IsDebug() {
|
||||
log.Println("[CollectionsImport] Records table sync failure", collection.Name, err)
|
||||
}
|
||||
return validation.Errors{"collections": validation.NewError(
|
||||
"collections_import_records_table_sync_failure",
|
||||
fmt.Sprintf("Failed to sync the records table changes for collection %q.", collection.Name),
|
||||
)}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
@ -24,6 +24,10 @@ type FilesManager interface {
|
||||
// Model defines an interface with common methods that all db models should have.
|
||||
type Model interface {
|
||||
TableName() string
|
||||
IsNew() bool
|
||||
MarkAsNew()
|
||||
UnmarkAsNew()
|
||||
SetId(id string)
|
||||
HasId() bool
|
||||
GetId() string
|
||||
GetCreated() types.DateTime
|
||||
@ -39,6 +43,9 @@ type Model interface {
|
||||
|
||||
// BaseModel defines common fields and methods used by all other models.
|
||||
type BaseModel struct {
|
||||
insertId string
|
||||
isNewFlag bool
|
||||
|
||||
Id string `db:"id" json:"id"`
|
||||
Created types.DateTime `db:"created" json:"created"`
|
||||
Updated types.DateTime `db:"updated" json:"updated"`
|
||||
@ -54,6 +61,27 @@ func (m *BaseModel) GetId() string {
|
||||
return m.Id
|
||||
}
|
||||
|
||||
// SetId sets the model's id to the provided one.
|
||||
func (m *BaseModel) SetId(id string) {
|
||||
m.Id = id
|
||||
}
|
||||
|
||||
// UnmarkAsNew sets the model's isNewFlag enforcing [m.IsNew()] to be true.
|
||||
func (m *BaseModel) MarkAsNew() {
|
||||
m.isNewFlag = true
|
||||
}
|
||||
|
||||
// UnmarkAsNew clears the enforced model's isNewFlag.
|
||||
func (m *BaseModel) UnmarkAsNew() {
|
||||
m.isNewFlag = false
|
||||
}
|
||||
|
||||
// IsNew indicates what type of db query (insert or update)
|
||||
// should be used with the model instance.
|
||||
func (m *BaseModel) IsNew() bool {
|
||||
return m.isNewFlag || !m.HasId()
|
||||
}
|
||||
|
||||
// GetCreated returns the model's Created datetime.
|
||||
func (m *BaseModel) GetCreated() types.DateTime {
|
||||
return m.Created
|
||||
|
@ -24,6 +24,7 @@
|
||||
window.Prism = window.Prism || {};
|
||||
window.Prism.manual = true;
|
||||
</script>
|
||||
<script src="./libs/diff/diff.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
455
ui/package-lock.json
generated
455
ui/package-lock.json
generated
@ -91,15 +91,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.0.tgz",
|
||||
"integrity": "sha512-qbUr94DZTe6/V1VS7LDLz11rM/1t/nJxR1El4I6UaxDEdc0aZZvq6JCLJWiRmUf95NRAnDH6fhXn+PWp9wGCIg==",
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.1.tgz",
|
||||
"integrity": "sha512-2s+aXsxmAwnR3Rd+JDHPG/1lw0YsA9PEwl7Re88gHJHGfxyfEzKBmsN4rr53RyPIR4lzbbhJX0DCq0WlqlBIRw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.1.2.tgz",
|
||||
"integrity": "sha512-puUydfKwfmOo+ixtuB+uN/ZpcteEYSnpjHmMaow1sOQhNICsKtGBup3i9ybVqyzDagARRYzSHTWjbdeHqmn31w==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.1.4.tgz",
|
||||
"integrity": "sha512-pekgUX+0hL4ri2JV7/bu7jhhwOgOhU1eRc1/ZyAQYCWcCI4TPB1qLrPE3cD/qW9yjBcYiN9MN0XI1tjK7Yw05Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -107,6 +107,22 @@
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz",
|
||||
"integrity": "sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz",
|
||||
@ -123,9 +139,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.0.tgz",
|
||||
"integrity": "sha512-TgEpfm9br2SX8JwtwKT8HsQZKuFkLRg6g+IRxObk9nVKQLKnkP3oMh+QGcTBL9GQsfQ2ADtKPbj2iGSMf3ytiA==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.1.tgz",
|
||||
"integrity": "sha512-RpHRs+Q+5tPsXtobSfSeRFRAnTRD0e4bApDvo74O+JiaWq9812x5S8WgftNX67owdaTQXCB5E8XZGALo4Wt77A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
@ -206,19 +222,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.2.tgz",
|
||||
"integrity": "sha512-7rqSlHWMUKFyBDOJvmFGW2lxULtcwaPLegDjX/Nu5j6QybY+GCiQkEY+6cqHw62S5tcwXMD8Y+H5OBGoR7d+ZQ==",
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
|
||||
"integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/chartjs-adapter-luxon": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-adapter-luxon/-/chartjs-adapter-luxon-1.1.0.tgz",
|
||||
"integrity": "sha512-CS+xBWEyXYVLBZ3dSY/MwlSXhz8er4JjkApazY84ft/++oOLsmkt6TaXBCsUFudum7QdoYmpxiL/gSp20+emkw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-adapter-luxon/-/chartjs-adapter-luxon-1.2.0.tgz",
|
||||
"integrity": "sha512-h1lEns7+8cUN/Dmk24dhrT9hpAimKImQxzHpILqXn2kocdzj9b/fDlBa8v8/OMq5rq0uZEx/NV1WpByH4l2/Rw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"chart.js": "^3.0.0",
|
||||
"luxon": "^1.0.0 || ^2.0.0"
|
||||
"luxon": ">=1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
@ -281,9 +297,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz",
|
||||
"integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.53.tgz",
|
||||
"integrity": "sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
@ -293,32 +309,33 @@
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"esbuild-android-64": "0.14.51",
|
||||
"esbuild-android-arm64": "0.14.51",
|
||||
"esbuild-darwin-64": "0.14.51",
|
||||
"esbuild-darwin-arm64": "0.14.51",
|
||||
"esbuild-freebsd-64": "0.14.51",
|
||||
"esbuild-freebsd-arm64": "0.14.51",
|
||||
"esbuild-linux-32": "0.14.51",
|
||||
"esbuild-linux-64": "0.14.51",
|
||||
"esbuild-linux-arm": "0.14.51",
|
||||
"esbuild-linux-arm64": "0.14.51",
|
||||
"esbuild-linux-mips64le": "0.14.51",
|
||||
"esbuild-linux-ppc64le": "0.14.51",
|
||||
"esbuild-linux-riscv64": "0.14.51",
|
||||
"esbuild-linux-s390x": "0.14.51",
|
||||
"esbuild-netbsd-64": "0.14.51",
|
||||
"esbuild-openbsd-64": "0.14.51",
|
||||
"esbuild-sunos-64": "0.14.51",
|
||||
"esbuild-windows-32": "0.14.51",
|
||||
"esbuild-windows-64": "0.14.51",
|
||||
"esbuild-windows-arm64": "0.14.51"
|
||||
"@esbuild/linux-loong64": "0.14.53",
|
||||
"esbuild-android-64": "0.14.53",
|
||||
"esbuild-android-arm64": "0.14.53",
|
||||
"esbuild-darwin-64": "0.14.53",
|
||||
"esbuild-darwin-arm64": "0.14.53",
|
||||
"esbuild-freebsd-64": "0.14.53",
|
||||
"esbuild-freebsd-arm64": "0.14.53",
|
||||
"esbuild-linux-32": "0.14.53",
|
||||
"esbuild-linux-64": "0.14.53",
|
||||
"esbuild-linux-arm": "0.14.53",
|
||||
"esbuild-linux-arm64": "0.14.53",
|
||||
"esbuild-linux-mips64le": "0.14.53",
|
||||
"esbuild-linux-ppc64le": "0.14.53",
|
||||
"esbuild-linux-riscv64": "0.14.53",
|
||||
"esbuild-linux-s390x": "0.14.53",
|
||||
"esbuild-netbsd-64": "0.14.53",
|
||||
"esbuild-openbsd-64": "0.14.53",
|
||||
"esbuild-sunos-64": "0.14.53",
|
||||
"esbuild-windows-32": "0.14.53",
|
||||
"esbuild-windows-64": "0.14.53",
|
||||
"esbuild-windows-arm64": "0.14.53"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz",
|
||||
"integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz",
|
||||
"integrity": "sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -332,9 +349,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -348,9 +365,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz",
|
||||
"integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz",
|
||||
"integrity": "sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -364,9 +381,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -380,9 +397,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -396,9 +413,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -412,9 +429,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-32": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz",
|
||||
"integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz",
|
||||
"integrity": "sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -428,9 +445,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz",
|
||||
"integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz",
|
||||
"integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -444,9 +461,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz",
|
||||
"integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz",
|
||||
"integrity": "sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -460,9 +477,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -476,9 +493,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-mips64le": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz",
|
||||
"integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz",
|
||||
"integrity": "sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
@ -492,9 +509,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-ppc64le": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz",
|
||||
"integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz",
|
||||
"integrity": "sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@ -508,9 +525,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-riscv64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz",
|
||||
"integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz",
|
||||
"integrity": "sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@ -524,9 +541,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-s390x": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz",
|
||||
"integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz",
|
||||
"integrity": "sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@ -540,9 +557,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-netbsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -556,9 +573,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-openbsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -572,9 +589,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-sunos-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz",
|
||||
"integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz",
|
||||
"integrity": "sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -588,9 +605,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-32": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz",
|
||||
"integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz",
|
||||
"integrity": "sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -604,9 +621,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz",
|
||||
"integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz",
|
||||
"integrity": "sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -620,9 +637,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -722,9 +739,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
|
||||
"integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
|
||||
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
@ -937,9 +954,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz",
|
||||
"integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==",
|
||||
"version": "1.54.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.2.tgz",
|
||||
"integrity": "sha512-wbVV26sejsCIbBScZZtNkvnrB/bVCQ8hSlZ01D9nzsVh9zLqCkWrlpvTb3YEb6xsuNi9cx75hncqwikHFSz7tw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
@ -1085,9 +1102,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.5.tgz",
|
||||
"integrity": "sha512-WJrK7i6w+ULuZsGscCezbCH4Aev5U3xY87vnSimzzEgPQhb0Sa0a1rE3c2jtEwrFtSfi61Jefw3jI5/DD/3jbQ==",
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
@ -1151,15 +1168,15 @@
|
||||
}
|
||||
},
|
||||
"@codemirror/state": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.0.tgz",
|
||||
"integrity": "sha512-qbUr94DZTe6/V1VS7LDLz11rM/1t/nJxR1El4I6UaxDEdc0aZZvq6JCLJWiRmUf95NRAnDH6fhXn+PWp9wGCIg==",
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.1.tgz",
|
||||
"integrity": "sha512-2s+aXsxmAwnR3Rd+JDHPG/1lw0YsA9PEwl7Re88gHJHGfxyfEzKBmsN4rr53RyPIR4lzbbhJX0DCq0WlqlBIRw==",
|
||||
"dev": true
|
||||
},
|
||||
"@codemirror/view": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.1.2.tgz",
|
||||
"integrity": "sha512-puUydfKwfmOo+ixtuB+uN/ZpcteEYSnpjHmMaow1sOQhNICsKtGBup3i9ybVqyzDagARRYzSHTWjbdeHqmn31w==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.1.4.tgz",
|
||||
"integrity": "sha512-pekgUX+0hL4ri2JV7/bu7jhhwOgOhU1eRc1/ZyAQYCWcCI4TPB1qLrPE3cD/qW9yjBcYiN9MN0XI1tjK7Yw05Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -1167,6 +1184,13 @@
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"@esbuild/linux-loong64": {
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz",
|
||||
"integrity": "sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@lezer/common": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz",
|
||||
@ -1183,9 +1207,9 @@
|
||||
}
|
||||
},
|
||||
"@lezer/lr": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.0.tgz",
|
||||
"integrity": "sha512-TgEpfm9br2SX8JwtwKT8HsQZKuFkLRg6g+IRxObk9nVKQLKnkP3oMh+QGcTBL9GQsfQ2ADtKPbj2iGSMf3ytiA==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.1.tgz",
|
||||
"integrity": "sha512-RpHRs+Q+5tPsXtobSfSeRFRAnTRD0e4bApDvo74O+JiaWq9812x5S8WgftNX67owdaTQXCB5E8XZGALo4Wt77A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
@ -1241,15 +1265,15 @@
|
||||
}
|
||||
},
|
||||
"chart.js": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.8.2.tgz",
|
||||
"integrity": "sha512-7rqSlHWMUKFyBDOJvmFGW2lxULtcwaPLegDjX/Nu5j6QybY+GCiQkEY+6cqHw62S5tcwXMD8Y+H5OBGoR7d+ZQ==",
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
|
||||
"integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==",
|
||||
"dev": true
|
||||
},
|
||||
"chartjs-adapter-luxon": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-adapter-luxon/-/chartjs-adapter-luxon-1.1.0.tgz",
|
||||
"integrity": "sha512-CS+xBWEyXYVLBZ3dSY/MwlSXhz8er4JjkApazY84ft/++oOLsmkt6TaXBCsUFudum7QdoYmpxiL/gSp20+emkw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-adapter-luxon/-/chartjs-adapter-luxon-1.2.0.tgz",
|
||||
"integrity": "sha512-h1lEns7+8cUN/Dmk24dhrT9hpAimKImQxzHpILqXn2kocdzj9b/fDlBa8v8/OMq5rq0uZEx/NV1WpByH4l2/Rw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
@ -1291,170 +1315,171 @@
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz",
|
||||
"integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.53.tgz",
|
||||
"integrity": "sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild-android-64": "0.14.51",
|
||||
"esbuild-android-arm64": "0.14.51",
|
||||
"esbuild-darwin-64": "0.14.51",
|
||||
"esbuild-darwin-arm64": "0.14.51",
|
||||
"esbuild-freebsd-64": "0.14.51",
|
||||
"esbuild-freebsd-arm64": "0.14.51",
|
||||
"esbuild-linux-32": "0.14.51",
|
||||
"esbuild-linux-64": "0.14.51",
|
||||
"esbuild-linux-arm": "0.14.51",
|
||||
"esbuild-linux-arm64": "0.14.51",
|
||||
"esbuild-linux-mips64le": "0.14.51",
|
||||
"esbuild-linux-ppc64le": "0.14.51",
|
||||
"esbuild-linux-riscv64": "0.14.51",
|
||||
"esbuild-linux-s390x": "0.14.51",
|
||||
"esbuild-netbsd-64": "0.14.51",
|
||||
"esbuild-openbsd-64": "0.14.51",
|
||||
"esbuild-sunos-64": "0.14.51",
|
||||
"esbuild-windows-32": "0.14.51",
|
||||
"esbuild-windows-64": "0.14.51",
|
||||
"esbuild-windows-arm64": "0.14.51"
|
||||
"@esbuild/linux-loong64": "0.14.53",
|
||||
"esbuild-android-64": "0.14.53",
|
||||
"esbuild-android-arm64": "0.14.53",
|
||||
"esbuild-darwin-64": "0.14.53",
|
||||
"esbuild-darwin-arm64": "0.14.53",
|
||||
"esbuild-freebsd-64": "0.14.53",
|
||||
"esbuild-freebsd-arm64": "0.14.53",
|
||||
"esbuild-linux-32": "0.14.53",
|
||||
"esbuild-linux-64": "0.14.53",
|
||||
"esbuild-linux-arm": "0.14.53",
|
||||
"esbuild-linux-arm64": "0.14.53",
|
||||
"esbuild-linux-mips64le": "0.14.53",
|
||||
"esbuild-linux-ppc64le": "0.14.53",
|
||||
"esbuild-linux-riscv64": "0.14.53",
|
||||
"esbuild-linux-s390x": "0.14.53",
|
||||
"esbuild-netbsd-64": "0.14.53",
|
||||
"esbuild-openbsd-64": "0.14.53",
|
||||
"esbuild-sunos-64": "0.14.53",
|
||||
"esbuild-windows-32": "0.14.53",
|
||||
"esbuild-windows-64": "0.14.53",
|
||||
"esbuild-windows-arm64": "0.14.53"
|
||||
}
|
||||
},
|
||||
"esbuild-android-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz",
|
||||
"integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz",
|
||||
"integrity": "sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-android-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz",
|
||||
"integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz",
|
||||
"integrity": "sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-32": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz",
|
||||
"integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz",
|
||||
"integrity": "sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz",
|
||||
"integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz",
|
||||
"integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz",
|
||||
"integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz",
|
||||
"integrity": "sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-mips64le": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz",
|
||||
"integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz",
|
||||
"integrity": "sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-ppc64le": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz",
|
||||
"integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz",
|
||||
"integrity": "sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-riscv64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz",
|
||||
"integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz",
|
||||
"integrity": "sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-s390x": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz",
|
||||
"integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz",
|
||||
"integrity": "sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-netbsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-openbsd-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz",
|
||||
"integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz",
|
||||
"integrity": "sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-sunos-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz",
|
||||
"integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz",
|
||||
"integrity": "sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-32": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz",
|
||||
"integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz",
|
||||
"integrity": "sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz",
|
||||
"integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz",
|
||||
"integrity": "sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-arm64": {
|
||||
"version": "0.14.51",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz",
|
||||
"integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==",
|
||||
"version": "0.14.53",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz",
|
||||
"integrity": "sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
@ -1526,9 +1551,9 @@
|
||||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
|
||||
"integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
|
||||
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
@ -1671,9 +1696,9 @@
|
||||
}
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.0.tgz",
|
||||
"integrity": "sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==",
|
||||
"version": "1.54.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.2.tgz",
|
||||
"integrity": "sha512-wbVV26sejsCIbBScZZtNkvnrB/bVCQ8hSlZ01D9nzsVh9zLqCkWrlpvTb3YEb6xsuNi9cx75hncqwikHFSz7tw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
@ -1759,9 +1784,9 @@
|
||||
}
|
||||
},
|
||||
"w3c-keyname": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.5.tgz",
|
||||
"integrity": "sha512-WJrK7i6w+ULuZsGscCezbCH4Aev5U3xY87vnSimzzEgPQhb0Sa0a1rE3c2jtEwrFtSfi61Jefw3jI5/DD/3jbQ==",
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
56
ui/public/libs/diff/diff.js
Normal file
56
ui/public/libs/diff/diff.js
Normal file
@ -0,0 +1,56 @@
|
||||
// https://github.com/google/diff-match-patch
|
||||
var diff_match_patch=function(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=.5;this.Patch_Margin=4;this.Match_MaxBits=32},DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;diff_match_patch.Diff=function(a,b){this[0]=a;this[1]=b};diff_match_patch.Diff.prototype.length=2;diff_match_patch.Diff.prototype.toString=function(){return this[0]+","+this[1]};
|
||||
diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[new diff_match_patch.Diff(DIFF_EQUAL,a)]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);f=this.diff_commonSuffix(a,b);var g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,
|
||||
b.length-f);a=this.diff_compute_(a,b,e,d);c&&a.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));g&&a.push(new diff_match_patch.Diff(DIFF_EQUAL,g));this.diff_cleanupMerge(a);return a};
|
||||
diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[new diff_match_patch.Diff(DIFF_INSERT,b)];if(!b)return[new diff_match_patch.Diff(DIFF_DELETE,a)];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[new diff_match_patch.Diff(DIFF_INSERT,e.substring(0,g)),new diff_match_patch.Diff(DIFF_EQUAL,f),new diff_match_patch.Diff(DIFF_INSERT,e.substring(g+f.length))],a.length>b.length&&(c[0][0]=c[2][0]=DIFF_DELETE),c):1==f.length?[new diff_match_patch.Diff(DIFF_DELETE,
|
||||
a),new diff_match_patch.Diff(DIFF_INSERT,b)]:(e=this.diff_halfMatch_(a,b))?(b=e[1],f=e[3],a=e[4],e=this.diff_main(e[0],e[2],c,d),c=this.diff_main(b,f,c,d),e.concat([new diff_match_patch.Diff(DIFF_EQUAL,a)],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,d):this.diff_bisect_(a,b,d)};
|
||||
diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case DIFF_INSERT:e++;g+=a[b][1];break;case DIFF_DELETE:d++;f+=a[b][1];break;case DIFF_EQUAL:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,
|
||||
0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
|
||||
diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=2*f,h=Array(g),l=Array(g),k=0;k<g;k++)h[k]=-1,l[k]=-1;h[f+1]=0;l[f+1]=0;k=d-e;for(var m=0!=k%2,p=0,x=0,w=0,q=0,t=0;t<f&&!((new Date).getTime()>c);t++){for(var v=-t+p;v<=t-x;v+=2){var n=f+v;var r=v==-t||v!=t&&h[n-1]<h[n+1]?h[n+1]:h[n-1]+1;for(var y=r-v;r<d&&y<e&&a.charAt(r)==b.charAt(y);)r++,y++;h[n]=r;if(r>d)x+=2;else if(y>e)p+=2;else if(m&&(n=f+k-v,0<=n&&n<g&&-1!=l[n])){var u=d-l[n];if(r>=
|
||||
u)return this.diff_bisectSplit_(a,b,r,y,c)}}for(v=-t+w;v<=t-q;v+=2){n=f+v;u=v==-t||v!=t&&l[n-1]<l[n+1]?l[n+1]:l[n-1]+1;for(r=u-v;u<d&&r<e&&a.charAt(d-u-1)==b.charAt(e-r-1);)u++,r++;l[n]=u;if(u>d)q+=2;else if(r>e)w+=2;else if(!m&&(n=f+k-v,0<=n&&n<g&&-1!=h[n]&&(r=h[n],y=f+r-n,u=d-u,r>=u)))return this.diff_bisectSplit_(a,b,r,y,c)}}return[new diff_match_patch.Diff(DIFF_DELETE,a),new diff_match_patch.Diff(DIFF_INSERT,b)]};
|
||||
diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
|
||||
diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,g=-1,h=d.length;g<a.length-1;){g=a.indexOf("\n",c);-1==g&&(g=a.length-1);var l=a.substring(c,g+1);(e.hasOwnProperty?e.hasOwnProperty(l):void 0!==e[l])?b+=String.fromCharCode(e[l]):(h==f&&(l=a.substring(c),g=a.length),b+=String.fromCharCode(h),e[l]=h,d[h++]=l);c=g+1}return b}var d=[],e={};d[0]="";var f=4E4,g=c(a);f=65535;var h=c(b);return{chars1:g,chars2:h,lineArray:d}};
|
||||
diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
|
||||
diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
|
||||
diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;d=0;for(var e=1;;){var f=a.substring(c-e);f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
|
||||
diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,k,l,m;-1!=(e=b.indexOf(d,e+1));){var p=f.diff_commonPrefix(a.substring(c),b.substring(e)),u=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<u+p&&(g=b.substring(e-u,e)+b.substring(e,e+p),h=a.substring(0,c-u),k=a.substring(c+p),l=b.substring(0,e-u),m=b.substring(e+p))}return 2*g.length>=a.length?[h,k,l,m,g]:null}if(0>=this.Diff_Timeout)return null;
|
||||
var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4));d=c(d,e,Math.ceil(d.length/2));if(g||d)g=d?g?g[4].length>d[4].length?g:d:d:g;else return null;if(a.length>b.length){d=g[0];e=g[1];var h=g[2];var l=g[3]}else h=g[0],l=g[1],d=g[2],e=g[3];return[d,e,h,l,g[4]]};
|
||||
diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,l=0,k=0;f<a.length;)a[f][0]==DIFF_EQUAL?(c[d++]=f,g=l,h=k,k=l=0,e=a[f][1]):(a[f][0]==DIFF_INSERT?l+=a[f][1].length:k+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(l,k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,d--,f=0<d?c[d-1]:-1,k=l=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<
|
||||
a.length;){if(a[f-1][0]==DIFF_DELETE&&a[f][0]==DIFF_INSERT){b=a[f-1][1];c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,c.substring(0,d))),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,b.substring(0,e))),a[f-1][0]=DIFF_INSERT,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=DIFF_DELETE,
|
||||
a[f+1][1]=b.substring(e),f++;f++}f++}};
|
||||
diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_);c=g&&c.match(diff_match_patch.linebreakRegex_);d=h&&d.match(diff_match_patch.linebreakRegex_);var k=c&&a.match(diff_match_patch.blanklineEndRegex_),l=d&&b.match(diff_match_patch.blanklineStartRegex_);
|
||||
return k||l?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(a[c-1][0]==DIFF_EQUAL&&a[c+1][0]==DIFF_EQUAL){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g){var h=e.substring(e.length-g);d=d.substring(0,d.length-g);e=h+e.substring(0,e.length-g);f=h+f}g=d;h=e;for(var l=f,k=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);e=e.substring(1)+f.charAt(0);f=f.substring(1);var m=b(d,e)+b(e,f);m>=k&&(k=m,g=d,h=e,l=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-
|
||||
1,1),c--),a[c][1]=h,l?a[c+1][1]=l:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
|
||||
diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,l=!1,k=!1;f<a.length;)a[f][0]==DIFF_EQUAL?(a[f][1].length<this.Diff_EditCost&&(l||k)?(c[d++]=f,g=l,h=k,e=a[f][1]):(d=0,e=null),l=k=!1):(a[f][0]==DIFF_DELETE?k=!0:l=!0,e&&(g&&h&&l&&k||e.length<this.Diff_EditCost/2&&3==g+h+l+k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,e=null,g&&h?(l=k=!0,d=0):(d--,f=0<d?c[d-1]:-1,l=k=!1),b=!0)),f++;b&&this.diff_cleanupMerge(a)};
|
||||
diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case DIFF_INSERT:d++;f+=a[b][1];b++;break;case DIFF_DELETE:c++;e+=a[b][1];b++;break;case DIFF_EQUAL:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&a[b-c-d-1][0]==DIFF_EQUAL?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,new diff_match_patch.Diff(DIFF_EQUAL,f.substring(0,g))),b++),f=f.substring(g),e=e.substring(g)),
|
||||
g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-g),e=e.substring(0,e.length-g))),b-=c+d,a.splice(b,c+d),e.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_DELETE,e)),b++),f.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_INSERT,f)),b++),b++):0!==b&&a[b-1][0]==DIFF_EQUAL?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)a[b-1][0]==DIFF_EQUAL&&a[b+1][0]==DIFF_EQUAL&&(a[b][1].substring(a[b][1].length-
|
||||
a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};
|
||||
diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==DIFF_INSERT&&(c+=a[g][1].length);a[g][0]!==DIFF_DELETE&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===DIFF_DELETE?f:f+(b-e)};
|
||||
diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],l=a[g][1].replace(c,"&").replace(d,"<").replace(e,">").replace(f,"¶<br>");switch(h){case DIFF_INSERT:b[g]='<ins style="background:#e6ffe6;">'+l+"</ins>";break;case DIFF_DELETE:b[g]='<del style="background:#ffe6e6;">'+l+"</del>";break;case DIFF_EQUAL:b[g]="<span>"+l+"</span>"}}return b.join("")};
|
||||
diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_INSERT&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_DELETE&&(b[c]=a[c][1]);return b.join("")};
|
||||
diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][1];switch(a[e][0]){case DIFF_INSERT:c+=f.length;break;case DIFF_DELETE:d+=f.length;break;case DIFF_EQUAL:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
|
||||
diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case DIFF_INSERT:b[c]="+"+encodeURI(a[c][1]);break;case DIFF_DELETE:b[c]="-"+a[c][1].length;break;case DIFF_EQUAL:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
|
||||
diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=new diff_match_patch.Diff(DIFF_INSERT,decodeURI(h))}catch(k){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var l=parseInt(h,10);if(isNaN(l)||0>l)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=l);"="==f[g].charAt(0)?c[d++]=new diff_match_patch.Diff(DIFF_EQUAL,h):c[d++]=
|
||||
new diff_match_patch.Diff(DIFF_DELETE,h);break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
|
||||
diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return f.Match_Distance?e+g/f.Match_Distance:g?1:e}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));var l=1<<b.length-1;h=-1;for(var k,m,p=b.length+a.length,x,w=0;w<b.length;w++){k=0;for(m=p;k<m;)d(w,
|
||||
c+m)<=g?k=m:p=m,m=Math.floor((p-k)/2+k);p=m;k=Math.max(1,c-m+1);var q=Math.min(c+m,a.length)+b.length;m=Array(q+2);for(m[q+1]=(1<<w)-1;q>=k;q--){var t=e[a.charAt(q-1)];m[q]=0===w?(m[q+1]<<1|1)&t:(m[q+1]<<1|1)&t|(x[q+1]|x[q])<<1|1|x[q+1];if(m[q]&l&&(t=d(w,q-1),t<=g))if(g=t,h=q-1,h>c)k=Math.max(1,2*c-h);else break}if(d(w+1,c)>g)break;x=m}return h};
|
||||
diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
|
||||
diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){if(null===a.start2)throw Error("patch not initialized");for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));(d=b.substring(a.start2+a.length1,
|
||||
a.start2+a.length1+d))&&a.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,d));a.start1-=c.length;a.start2-=c.length;a.length1+=c.length+d.length;a.length2+=c.length+d.length}};
|
||||
diff_match_patch.prototype.patch_make=function(a,b,c){if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c){var d=a;b=this.diff_main(d,b,!0);2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b))}else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
|
||||
if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,l=0;l<b.length;l++){var k=b[l][0],m=b[l][1];e||k===DIFF_EQUAL||(a.start1=f,a.start2=g);switch(k){case DIFF_INSERT:a.diffs[e++]=b[l];a.length2+=m.length;d=d.substring(0,g)+m+d.substring(g);break;case DIFF_DELETE:a.length1+=m.length;a.diffs[e++]=b[l];d=d.substring(0,g)+d.substring(g+m.length);break;case DIFF_EQUAL:m.length<=2*this.Patch_Margin&&e&&b.length!=l+1?(a.diffs[e++]=b[l],a.length1+=m.length,a.length2+=m.length):
|
||||
m.length>=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}k!==DIFF_INSERT&&(f+=m.length);k!==DIFF_DELETE&&(g+=m.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};
|
||||
diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=new diff_match_patch.Diff(d.diffs[f][0],d.diffs[f][1]);e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
|
||||
diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),l=-1;if(h.length>this.Match_MaxBits){var k=this.match_main(b,h.substring(0,this.Match_MaxBits),g);-1!=k&&(l=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==l||k>=l)&&(k=-1)}else k=this.match_main(b,h,
|
||||
g);if(-1==k)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=k-g,g=-1==l?b.substring(k,k+h.length):b.substring(k,l+this.Match_MaxBits),h==g)b=b.substring(0,k)+this.diff_text2(a[f].diffs)+b.substring(k+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);h=0;var m;for(l=0;l<a[f].diffs.length;l++){var p=a[f].diffs[l];p[0]!==DIFF_EQUAL&&(m=this.diff_xIndex(g,h));p[0]===
|
||||
DIFF_INSERT?b=b.substring(0,k+m)+p[1]+b.substring(k+m):p[0]===DIFF_DELETE&&(b=b.substring(0,k+m)+b.substring(k+this.diff_xIndex(g,h+p[1].length)));p[0]!==DIFF_DELETE&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
|
||||
diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;d=a[0];var e=d.diffs;if(0==e.length||e[0][0]!=DIFF_EQUAL)e.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;
|
||||
0==e.length||e[e.length-1][0]!=DIFF_EQUAL?(e.push(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
|
||||
diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,l=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g)));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){g=d.diffs[0][0];var k=d.diffs[0][1];g===DIFF_INSERT?(h.length2+=
|
||||
k.length,f+=k.length,h.diffs.push(d.diffs.shift()),l=!1):g===DIFF_DELETE&&1==h.diffs.length&&h.diffs[0][0]==DIFF_EQUAL&&k.length>2*b?(h.length1+=k.length,e+=k.length,l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),d.diffs.shift()):(k=k.substring(0,b-h.length1-this.Patch_Margin),h.length1+=k.length,e+=k.length,g===DIFF_EQUAL?(h.length2+=k.length,f+=k.length):l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),k==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(k.length))}g=this.diff_text2(h.diffs);
|
||||
g=g.substring(g.length-this.Patch_Margin);k=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==k&&(h.length1+=k.length,h.length2+=k.length,0!==h.diffs.length&&h.diffs[h.diffs.length-1][0]===DIFF_EQUAL?h.diffs[h.diffs.length-1][1]+=k:h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,k)));l||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
|
||||
diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
|
||||
parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_DELETE,g));else if("+"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_INSERT,g));else if(" "==e)f.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g));else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};
|
||||
diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
|
||||
diff_match_patch.patch_obj.prototype.toString=function(){for(var a=["@@ -"+(0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1)+" +"+(0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2)+" @@\n"],b,c=0;c<this.diffs.length;c++){switch(this.diffs[c][0]){case DIFF_INSERT:b="+";break;case DIFF_DELETE:b="-";break;case DIFF_EQUAL:b=" "}a[c+1]=b+encodeURI(this.diffs[c][1])+"\n"}return a.join("").replace(/%20/g," ")};
|
||||
this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=DIFF_DELETE;this.DIFF_INSERT=DIFF_INSERT;this.DIFF_EQUAL=DIFF_EQUAL;
|
@ -143,9 +143,9 @@
|
||||
|
||||
<div class="app-body">
|
||||
<Router {routes} on:routeLoading={handleRouteLoading} on:conditionsFailed={handleRouteFailure} />
|
||||
|
||||
<Toasts />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Toasts />
|
||||
|
||||
<Confirmation />
|
||||
|
@ -4,6 +4,9 @@
|
||||
import "prismjs/components/prism-dart.js";
|
||||
import "@/scss/prism_light.scss";
|
||||
|
||||
let classes = "";
|
||||
export { classes as class }; // export reserved keyword
|
||||
|
||||
export let content = "";
|
||||
export let language = "javascript"; // javascript, html
|
||||
|
||||
@ -28,7 +31,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="code-wrapper prism-light">
|
||||
<div class="code-wrapper prism-light {classes}">
|
||||
<code>{@html formattedContent}</code>
|
||||
</div>
|
||||
|
||||
@ -43,6 +46,9 @@
|
||||
.code-wrapper {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
overflow: auto; /* fallback */
|
||||
overflow: overlay;
|
||||
}
|
||||
.prism-light code {
|
||||
color: var(--txtPrimaryColor);
|
||||
|
352
ui/src/components/collections/CollectionsExportForm.svelte
Normal file
352
ui/src/components/collections/CollectionsExportForm.svelte
Normal file
@ -0,0 +1,352 @@
|
||||
<script>
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import Field from "@/components/base/Field.svelte";
|
||||
import CodeBlock from "@/components/base/CodeBlock.svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const uniqueId = "exports_" + CommonHelper.randomString(5);
|
||||
|
||||
let collections = [];
|
||||
let isLoadingCollections = false;
|
||||
|
||||
loadCollections();
|
||||
|
||||
async function loadCollections() {
|
||||
isLoadingCollections = true;
|
||||
|
||||
try {
|
||||
collections = await ApiClient.collections.getFullList(100, {
|
||||
$cancelKey: uniqueId,
|
||||
});
|
||||
} catch (err) {
|
||||
ApiClient.errorResponseHandler(err);
|
||||
}
|
||||
|
||||
isLoadingCollections = false;
|
||||
}
|
||||
|
||||
let oldSchema = "";
|
||||
let newSchema = "";
|
||||
|
||||
function diff_prettyHtml(diffs, showInsert) {
|
||||
const html = [];
|
||||
const pattern_amp = /&/g;
|
||||
const pattern_lt = /</g;
|
||||
const pattern_gt = />/g;
|
||||
const pattern_para = /\n/g;
|
||||
for (let x = 0; x < diffs.length; x++) {
|
||||
let op = diffs[x][0]; // Operation (insert, delete, equal)
|
||||
let data = diffs[x][1]; // Text of change.
|
||||
let text = data
|
||||
.replace(pattern_amp, "&")
|
||||
.replace(pattern_lt, "<")
|
||||
.replace(pattern_gt, ">")
|
||||
.replace(pattern_para, "<br>");
|
||||
// text = CommonHelper.stripTags(text);
|
||||
switch (op) {
|
||||
case DIFF_INSERT:
|
||||
if (showInsert) {
|
||||
html[x] = '<ins class="block">' + text + "</ins>";
|
||||
}
|
||||
break;
|
||||
case DIFF_DELETE:
|
||||
if (!showInsert) {
|
||||
html[x] = '<del class="block">' + text + "</del>";
|
||||
}
|
||||
break;
|
||||
case DIFF_EQUAL:
|
||||
html[x] = "<span>" + text + "</span>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return html.join("");
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
var dmp = new diff_match_patch();
|
||||
const text1 = [
|
||||
{
|
||||
id: "zwWlxR46txtoAwx",
|
||||
created: "2022-08-01 17:32:24.329",
|
||||
updated: "2022-08-04 10:19:57.248",
|
||||
name: "profia sdles",
|
||||
system: true,
|
||||
listRule: "userId = @request.user.id",
|
||||
viewRule: "userId = @request.user.id",
|
||||
createRule: "userId = @request.user.id",
|
||||
updateRule: "userId = @request.user.id",
|
||||
deleteRule: null,
|
||||
schema: [
|
||||
{
|
||||
id: "nsght7oy",
|
||||
name: "userId",
|
||||
type: "user",
|
||||
system: true,
|
||||
required: true,
|
||||
unique: true,
|
||||
options: {
|
||||
maxSelect: 1,
|
||||
cascadeDelete: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "atpc4yjm",
|
||||
name: "name",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "akb4s9de",
|
||||
name: "avatar",
|
||||
type: "file",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
maxSelect: 1,
|
||||
maxSize: 5242880,
|
||||
mimeTypes: ["image/jpg", "image/jpeg", "image/png", "image/svg+xml", "image/gif"],
|
||||
thumbs: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "IV8FbE78jmXF56d",
|
||||
created: "",
|
||||
updated: "2022-08-04 10:21:54.100",
|
||||
name: "abc",
|
||||
system: false,
|
||||
listRule: null,
|
||||
viewRule: null,
|
||||
createRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: null,
|
||||
schema: [
|
||||
{
|
||||
id: "t2pukeas",
|
||||
name: "demo",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "dddddd",
|
||||
name: "aaaa",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "squmamtm",
|
||||
name: "test",
|
||||
type: "date",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: "",
|
||||
max: "",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const text2 = [
|
||||
{
|
||||
id: "zwWlxR46txtoAwx",
|
||||
created: "2022-08-01 17:32:24.329",
|
||||
updated: "2022-08-04 10:19:57.248",
|
||||
name: "Demo",
|
||||
system: true,
|
||||
listRule: "userId = @request.user.id",
|
||||
viewRule: "userId = @request.user.id",
|
||||
createRule: "userId = @request.user.id",
|
||||
updateRule: "userId = @request.user.id",
|
||||
deleteRule: null,
|
||||
schema: [
|
||||
{
|
||||
id: "nsght7oy",
|
||||
name: "userId",
|
||||
type: "user",
|
||||
system: true,
|
||||
required: true,
|
||||
unique: true,
|
||||
options: {
|
||||
maxSelect: 1,
|
||||
cascadeDelete: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "atpc4yjm",
|
||||
name: "name",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "akb4s9de",
|
||||
name: "avatar",
|
||||
type: "file",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: true,
|
||||
options: {
|
||||
maxSelect: 1,
|
||||
maxSize: 5242880,
|
||||
mimeTypes: ["image/jpg", "image/jpeg", "image/png", "image/svg+xml", "image/gif"],
|
||||
thumbs: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "IV8FbE78jmXF56d",
|
||||
created: "",
|
||||
updated: "2022-08-04 10:21:54.100",
|
||||
name: "abc",
|
||||
system: false,
|
||||
listRule: null,
|
||||
viewRule: null,
|
||||
createRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: null,
|
||||
schema: [
|
||||
{
|
||||
id: "t2pukeas",
|
||||
name: "demo",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "dddddd",
|
||||
name: "aaaa",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "squmamtm",
|
||||
name: "test",
|
||||
type: "date",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: "",
|
||||
max: "",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "GGACt8sa1tcJp7T",
|
||||
created: "2022-08-04 10:22:15.871",
|
||||
updated: "2022-08-04 10:22:15.871",
|
||||
name: "asdasd",
|
||||
system: true,
|
||||
listRule: null,
|
||||
viewRule: null,
|
||||
createRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: null,
|
||||
schema: [
|
||||
{
|
||||
id: "0eklwfvl",
|
||||
name: "field",
|
||||
type: "text",
|
||||
system: false,
|
||||
required: false,
|
||||
unique: false,
|
||||
options: {
|
||||
min: null,
|
||||
max: null,
|
||||
pattern: "",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// var diffs = dmp.diff_main(JSON.stringify(text1, null, 2), JSON.stringify(text2, null, 2));
|
||||
|
||||
var a = dmp.diff_linesToChars_(JSON.stringify(text1, null, 2), JSON.stringify(text2, null, 2));
|
||||
var lineText1 = a.chars1;
|
||||
var lineText2 = a.chars2;
|
||||
var lineArray = a.lineArray;
|
||||
var diffs = dmp.diff_main(lineText1, lineText2, false);
|
||||
dmp.diff_charsToLines_(diffs, lineArray);
|
||||
|
||||
oldSchema = diff_prettyHtml(diffs, false);
|
||||
newSchema = diff_prettyHtml(diffs, true);
|
||||
});
|
||||
</script>
|
||||
|
||||
<br />
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<code>
|
||||
{@html oldSchema}
|
||||
</code>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<code>
|
||||
{@html newSchema}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.collections-list {
|
||||
column-count: 2;
|
||||
column-gap: var(--baseSpacing);
|
||||
}
|
||||
code {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding: var(--xsSpacing);
|
||||
white-space: pre;
|
||||
background: var(--baseAlt1Color);
|
||||
}
|
||||
</style>
|
29
ui/src/components/collections/CollectionsExportPanel.svelte
Normal file
29
ui/src/components/collections/CollectionsExportPanel.svelte
Normal file
@ -0,0 +1,29 @@
|
||||
<script>
|
||||
import OverlayPanel from "@/components/base/OverlayPanel.svelte";
|
||||
import CollectionsExportForm from "@/components/collections/CollectionsExportForm.svelte";
|
||||
|
||||
let overlayPanel;
|
||||
|
||||
export function show() {
|
||||
return overlayPanel?.show();
|
||||
}
|
||||
|
||||
export function hide() {
|
||||
return overlayPanel?.hide();
|
||||
}
|
||||
</script>
|
||||
|
||||
<OverlayPanel
|
||||
bind:this={overlayPanel}
|
||||
class="overlay-panel-xl collections-export-panel"
|
||||
on:hide
|
||||
on:show
|
||||
popup
|
||||
active
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<h4>Export collections schema</h4>
|
||||
</svelte:fragment>
|
||||
|
||||
<CollectionsExportForm />
|
||||
</OverlayPanel>
|
@ -13,6 +13,7 @@
|
||||
import CollectionsSidebar from "@/components/collections/CollectionsSidebar.svelte";
|
||||
import CollectionUpsertPanel from "@/components/collections/CollectionUpsertPanel.svelte";
|
||||
import CollectionDocsPanel from "@/components/collections/docs/CollectionDocsPanel.svelte";
|
||||
import CollectionsExportPanel from "@/components/collections/CollectionsExportPanel.svelte";
|
||||
import RecordUpsertPanel from "@/components/records/RecordUpsertPanel.svelte";
|
||||
import RecordsList from "@/components/records/RecordsList.svelte";
|
||||
|
||||
@ -20,6 +21,7 @@
|
||||
|
||||
const queryParams = new URLSearchParams($querystring);
|
||||
|
||||
let collectionsExportPanel;
|
||||
let collectionUpsertPanel;
|
||||
let collectionDocsPanel;
|
||||
let recordPanel;
|
||||
@ -84,16 +86,18 @@
|
||||
<div class="breadcrumb-item">{$activeCollection.name}</div>
|
||||
</nav>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-circle"
|
||||
use:tooltip={{ text: "Edit collection", position: "right" }}
|
||||
on:click={() => collectionUpsertPanel?.show($activeCollection)}
|
||||
>
|
||||
<i class="ri-settings-4-line" />
|
||||
</button>
|
||||
<div class="inline-flex gap-5">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-circle"
|
||||
use:tooltip={{ text: "Edit collection", position: "right" }}
|
||||
on:click={() => collectionUpsertPanel?.show($activeCollection)}
|
||||
>
|
||||
<i class="ri-settings-4-line" />
|
||||
</button>
|
||||
|
||||
<RefreshButton on:refresh={() => recordsList?.load()} />
|
||||
<RefreshButton on:refresh={() => recordsList?.load()} />
|
||||
</div>
|
||||
|
||||
<div class="btns-group">
|
||||
<button
|
||||
@ -128,6 +132,8 @@
|
||||
</main>
|
||||
{/if}
|
||||
|
||||
<CollectionsExportPanel bind:this={collectionsExportPanel} />
|
||||
|
||||
<CollectionUpsertPanel bind:this={collectionUpsertPanel} />
|
||||
|
||||
<CollectionDocsPanel bind:this={collectionDocsPanel} />
|
||||
|
105
ui/src/components/settings/PageExportCollections.svelte
Normal file
105
ui/src/components/settings/PageExportCollections.svelte
Normal file
@ -0,0 +1,105 @@
|
||||
<script>
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import { pageTitle } from "@/stores/app";
|
||||
import { addInfoToast } from "@/stores/toasts";
|
||||
import CodeBlock from "@/components/base/CodeBlock.svelte";
|
||||
import SettingsSidebar from "@/components/settings/SettingsSidebar.svelte";
|
||||
|
||||
$pageTitle = "Export collections";
|
||||
|
||||
const uniqueId = "export_" + CommonHelper.randomString(5);
|
||||
|
||||
let collections = [];
|
||||
let isLoadingCollections = false;
|
||||
|
||||
$: schema = JSON.stringify(collections, null, 2);
|
||||
|
||||
loadCollections();
|
||||
|
||||
async function loadCollections() {
|
||||
isLoadingCollections = true;
|
||||
|
||||
try {
|
||||
collections = await ApiClient.collections.getFullList(100, {
|
||||
$cancelKey: uniqueId,
|
||||
});
|
||||
// delete timestamps
|
||||
for (let collection of collections) {
|
||||
delete collection.created;
|
||||
delete collection.updated;
|
||||
}
|
||||
} catch (err) {
|
||||
ApiClient.errorResponseHandler(err);
|
||||
}
|
||||
|
||||
isLoadingCollections = false;
|
||||
}
|
||||
|
||||
function download() {
|
||||
CommonHelper.downloadJson(collections, "pb_schema");
|
||||
}
|
||||
|
||||
function copy() {
|
||||
CommonHelper.copyToClipboard(schema);
|
||||
addInfoToast("The schema was copied to your clipboard!", 3000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<SettingsSidebar />
|
||||
|
||||
<main class="page-wrapper">
|
||||
<header class="page-header">
|
||||
<nav class="breadcrumbs">
|
||||
<div class="breadcrumb-item">Settings</div>
|
||||
<div class="breadcrumb-item">{$pageTitle}</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="panel">
|
||||
{#if isLoadingCollections}
|
||||
<div class="loader" />
|
||||
{:else}
|
||||
<div class="content txt-xl m-b-base">
|
||||
<p>
|
||||
Below you'll find your current collections schema that you could import later in
|
||||
another PocketBase environment.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="export-preview">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-secondary fade copy-schema"
|
||||
on:click={() => copy()}
|
||||
>
|
||||
<span class="txt">Copy</span>
|
||||
</button>
|
||||
|
||||
<CodeBlock content={schema} />
|
||||
</div>
|
||||
|
||||
<div class="flex m-t-base">
|
||||
<div class="flex-fill" />
|
||||
<button type="button" class="btn btn-expanded" on:click={() => download()}>
|
||||
<i class="ri-download-line" />
|
||||
<span class="txt">Download as JSON</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.export-preview {
|
||||
position: relative;
|
||||
height: 500px;
|
||||
}
|
||||
.export-preview .copy-schema {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
}
|
||||
</style>
|
221
ui/src/components/settings/PageImportCollections.svelte
Normal file
221
ui/src/components/settings/PageImportCollections.svelte
Normal file
@ -0,0 +1,221 @@
|
||||
<script>
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import CommonHelper from "@/utils/CommonHelper";
|
||||
import { pageTitle } from "@/stores/app";
|
||||
import { addInfoToast, addErrorToast } from "@/stores/toasts";
|
||||
import Field from "@/components/base/Field.svelte";
|
||||
import CodeBlock from "@/components/base/CodeBlock.svelte";
|
||||
import SettingsSidebar from "@/components/settings/SettingsSidebar.svelte";
|
||||
|
||||
$pageTitle = "Import collections";
|
||||
|
||||
let uniquePageId = "import_" + CommonHelper.randomString(5);
|
||||
|
||||
let fileInput;
|
||||
|
||||
let schema = "";
|
||||
let isImporting = false;
|
||||
let isLoadingFile = false;
|
||||
let newCollections = [];
|
||||
let oldCollections = [];
|
||||
let isLoadingOldCollections = false;
|
||||
|
||||
$: if (typeof schema !== "undefined") {
|
||||
loadNewCollections(schema);
|
||||
}
|
||||
|
||||
$: isValid =
|
||||
!!schema &&
|
||||
newCollections.length &&
|
||||
newCollections.length === newCollections.filter((item) => !!item.id && !!item.name).length;
|
||||
|
||||
$: canImport = isValid && !isLoadingOldCollections;
|
||||
|
||||
$: collectionsToDelete = oldCollections.filter((collection) => {
|
||||
return !CommonHelper.findByKey(newCollections, "id", collection.id);
|
||||
});
|
||||
|
||||
$: collectionsToAdd = newCollections.filter((collection) => {
|
||||
return !CommonHelper.findByKey(oldCollections, "id", collection.id);
|
||||
});
|
||||
|
||||
$: collectionsToModify = newCollections.filter((newCollection) => {
|
||||
const oldCollection = CommonHelper.findByKey(oldCollections, "id", newCollection.id);
|
||||
if (!oldCollection?.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return JSON.stringify(oldCollection) !== JSON.stringify(newCollection);
|
||||
});
|
||||
|
||||
loadOldCollections();
|
||||
|
||||
async function loadOldCollections() {
|
||||
isLoadingOldCollections = true;
|
||||
|
||||
try {
|
||||
oldCollections = await ApiClient.collections.getFullList(100, {
|
||||
$cancelKey: uniquePageId,
|
||||
});
|
||||
// delete timestamps
|
||||
for (let collection of oldCollections) {
|
||||
delete collection.created;
|
||||
delete collection.updated;
|
||||
}
|
||||
} catch (err) {
|
||||
ApiClient.errorResponseHandler(err);
|
||||
}
|
||||
|
||||
isLoadingOldCollections = false;
|
||||
}
|
||||
|
||||
function loadNewCollections() {
|
||||
newCollections = [];
|
||||
|
||||
try {
|
||||
newCollections = JSON.parse(schema);
|
||||
} catch (_) {}
|
||||
|
||||
if (!Array.isArray(newCollections)) {
|
||||
newCollections = [];
|
||||
}
|
||||
|
||||
// delete timestamps
|
||||
for (let collection of newCollections) {
|
||||
delete collection.created;
|
||||
delete collection.updated;
|
||||
}
|
||||
}
|
||||
|
||||
function loadFile(file) {
|
||||
isLoadingFile = true;
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (event) => {
|
||||
schema = event.target.result;
|
||||
|
||||
isLoadingFile = false;
|
||||
fileInput.value = ""; // reset
|
||||
};
|
||||
|
||||
reader.onerror = (err) => {
|
||||
console.log(err);
|
||||
addErrorToast("Failed to load the imported JSON.");
|
||||
|
||||
isLoadingFile = false;
|
||||
fileInput.value = ""; // reset
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
function submitImport() {
|
||||
isImporting = true;
|
||||
|
||||
try {
|
||||
const newCollections = JSON.parse(schema);
|
||||
ApiClient.collections.import(newCollections);
|
||||
} catch (err) {
|
||||
ApiClient.errorResponseHandler(err);
|
||||
}
|
||||
|
||||
isImporting = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<SettingsSidebar />
|
||||
|
||||
<main class="page-wrapper">
|
||||
<header class="page-header">
|
||||
<nav class="breadcrumbs">
|
||||
<div class="breadcrumb-item">Settings</div>
|
||||
<div class="breadcrumb-item">{$pageTitle}</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="panel">
|
||||
<div class="content txt-xl m-b-base">
|
||||
<input
|
||||
bind:this={fileInput}
|
||||
type="file"
|
||||
class="hidden"
|
||||
accept=".json"
|
||||
on:change={() => {
|
||||
if (fileInput.files.length) {
|
||||
loadFile(fileInput.files[0]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<p>
|
||||
Paste below the collections schema you want to import or
|
||||
<button
|
||||
class="btn btn-outline btn-sm"
|
||||
class:btn-loading={isLoadingFile}
|
||||
on:click={() => {
|
||||
fileInput.click();
|
||||
}}
|
||||
>
|
||||
<span class="txt">Import from JSON file</span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Field class="form-field {!isValid ? 'field-error' : ''}" name="collections" let:uniqueId>
|
||||
<label for={uniqueId}>Collections schema</label>
|
||||
<textarea
|
||||
id={uniqueId}
|
||||
class="json-editor"
|
||||
spellcheck="false"
|
||||
rows="20"
|
||||
required
|
||||
bind:value={schema}
|
||||
/>
|
||||
{#if !!schema && !isValid}
|
||||
<div class="help-block help-block-error">Invalid collections schema.</div>
|
||||
{/if}
|
||||
</Field>
|
||||
|
||||
<div class="section-title">Detected changes</div>
|
||||
<p>No changes to your current collections schema were found.</p>
|
||||
|
||||
{#each collectionsToDelete as collection (collection.id)}
|
||||
Delete {collection.name}
|
||||
<br />
|
||||
{/each}
|
||||
|
||||
{#each collectionsToModify as collection (collection.id)}
|
||||
Modify {collection.name}
|
||||
<br />
|
||||
{/each}
|
||||
|
||||
{#each collectionsToAdd as collection (collection.id)}
|
||||
Add {collection.name}
|
||||
<br />
|
||||
{/each}
|
||||
|
||||
<div class="flex m-t-base">
|
||||
<div class="flex-fill" />
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-expanded"
|
||||
class:btn-loading={isImporting}
|
||||
disabled={!canImport}
|
||||
on:click={() => submitImport()}
|
||||
>
|
||||
<span class="txt">Import</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.json-editor {
|
||||
font-size: 15px;
|
||||
line-height: 1.379rem;
|
||||
font-family: var(--monospaceFontFamily);
|
||||
}
|
||||
</style>
|
@ -29,6 +29,26 @@
|
||||
<span class="txt">Files storage</span>
|
||||
</a>
|
||||
|
||||
<div class="sidebar-title">Sync</div>
|
||||
<a
|
||||
href="/settings/export-collections"
|
||||
class="sidebar-list-item"
|
||||
use:active={{ path: "/settings/export-collections/?.*" }}
|
||||
use:link
|
||||
>
|
||||
<i class="ri-uninstall-line" />
|
||||
<span class="txt">Export collections</span>
|
||||
</a>
|
||||
<a
|
||||
href="/settings/import-collections"
|
||||
class="sidebar-list-item"
|
||||
use:active={{ path: "/settings/import-collections/?.*" }}
|
||||
use:link
|
||||
>
|
||||
<i class="ri-install-line" />
|
||||
<span class="txt">Import collections</span>
|
||||
</a>
|
||||
|
||||
<div class="sidebar-title">Authentication</div>
|
||||
<a
|
||||
href="/settings/auth-providers"
|
||||
|
@ -55,10 +55,11 @@
|
||||
clearList();
|
||||
}
|
||||
|
||||
return ApiClient.users.getList(page, 50, {
|
||||
sort: sort || "-created",
|
||||
filter: filter,
|
||||
})
|
||||
return ApiClient.users
|
||||
.getList(page, 50, {
|
||||
sort: sort || "-created",
|
||||
filter: filter,
|
||||
})
|
||||
.then((result) => {
|
||||
isLoadingUsers = false;
|
||||
users = users.concat(result.items);
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { replace } from "svelte-spa-router";
|
||||
import { wrap } from "svelte-spa-router/wrap";
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import PageIndex from "@/components/PageIndex.svelte";
|
||||
import PageLogs from "@/components/logs/PageLogs.svelte";
|
||||
import PageRecords from "@/components/records/PageRecords.svelte";
|
||||
import PageUsers from "@/components/users/PageUsers.svelte";
|
||||
import PageAdmins from "@/components/admins/PageAdmins.svelte";
|
||||
import PageAdminLogin from "@/components/admins/PageAdminLogin.svelte";
|
||||
import PageApplication from "@/components/settings/PageApplication.svelte";
|
||||
import PageMail from "@/components/settings/PageMail.svelte";
|
||||
import PageStorage from "@/components/settings/PageStorage.svelte";
|
||||
import PageAuthProviders from "@/components/settings/PageAuthProviders.svelte";
|
||||
import PageTokenOptions from "@/components/settings/PageTokenOptions.svelte";
|
||||
import { replace } from "svelte-spa-router";
|
||||
import { wrap } from "svelte-spa-router/wrap";
|
||||
import ApiClient from "@/utils/ApiClient";
|
||||
import PageIndex from "@/components/PageIndex.svelte";
|
||||
import PageLogs from "@/components/logs/PageLogs.svelte";
|
||||
import PageRecords from "@/components/records/PageRecords.svelte";
|
||||
import PageUsers from "@/components/users/PageUsers.svelte";
|
||||
import PageAdmins from "@/components/admins/PageAdmins.svelte";
|
||||
import PageAdminLogin from "@/components/admins/PageAdminLogin.svelte";
|
||||
import PageApplication from "@/components/settings/PageApplication.svelte";
|
||||
import PageMail from "@/components/settings/PageMail.svelte";
|
||||
import PageStorage from "@/components/settings/PageStorage.svelte";
|
||||
import PageAuthProviders from "@/components/settings/PageAuthProviders.svelte";
|
||||
import PageTokenOptions from "@/components/settings/PageTokenOptions.svelte";
|
||||
import PageExportCollections from "@/components/settings/PageExportCollections.svelte";
|
||||
import PageImportCollections from "@/components/settings/PageImportCollections.svelte";
|
||||
|
||||
const baseConditions = [
|
||||
async (details) => {
|
||||
@ -134,6 +136,18 @@ const routes = {
|
||||
userData: { showAppSidebar: true },
|
||||
}),
|
||||
|
||||
"/settings/export-collections": wrap({
|
||||
component: PageExportCollections,
|
||||
conditions: baseConditions.concat([(_) => ApiClient.authStore.isValid]),
|
||||
userData: { showAppSidebar: true },
|
||||
}),
|
||||
|
||||
"/settings/import-collections": wrap({
|
||||
component: PageImportCollections,
|
||||
conditions: baseConditions.concat([(_) => ApiClient.authStore.isValid]),
|
||||
userData: { showAppSidebar: true },
|
||||
}),
|
||||
|
||||
// fallback
|
||||
"*": wrap({
|
||||
component: PageIndex,
|
||||
|
@ -94,14 +94,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
// toast alerts
|
||||
.toasts-wrapper {
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0 var(--smSpacing);
|
||||
width: 100%;
|
||||
width: auto;
|
||||
display: block;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
@ -112,4 +112,10 @@
|
||||
margin: var(--baseSpacing) auto;
|
||||
@include shadowize();
|
||||
}
|
||||
.app-sidebar ~ .app-body & {
|
||||
left: var(--appSidebarWidth);
|
||||
}
|
||||
.app-sidebar ~ .app-body .page-sidebar ~ & {
|
||||
left: calc(var(--appSidebarWidth) + var(--pageSidebarWidth));
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,16 @@ em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
ins {
|
||||
background: var(--successAltColor);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
del {
|
||||
background: var(--dangerAltColor);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ button {
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
backface-visibility: hidden;
|
||||
background: var(--primaryColor);
|
||||
transition: filter var(--baseAnimationSpeed),
|
||||
opacity var(--baseAnimationSpeed),
|
||||
@ -483,13 +484,13 @@ select {
|
||||
line-height: var(--smLineHeight);
|
||||
color: var(--txtHintColor);
|
||||
}
|
||||
.help-block-error {
|
||||
color: var(--dangerColor);
|
||||
}
|
||||
|
||||
// states
|
||||
&.error,
|
||||
&.invalid {
|
||||
.help-block-error {
|
||||
color: var(--dangerColor);
|
||||
}
|
||||
> label {
|
||||
color: var(--dangerColor);
|
||||
}
|
||||
|
@ -600,6 +600,22 @@ export default class CommonHelper {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a json file created from the provide object.
|
||||
*
|
||||
* @param {mixed} obj The JS object to download.
|
||||
* @param {String} name The result file name.
|
||||
*/
|
||||
static downloadJson(obj, name) {
|
||||
const encodedObj = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj, null, 2));
|
||||
|
||||
const tempLink = document.createElement('a');
|
||||
tempLink.setAttribute("href", encodedObj);
|
||||
tempLink.setAttribute("download", name + ".json");
|
||||
tempLink.click();
|
||||
tempLink.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and returns the decoded jwt payload data.
|
||||
*
|
||||
|
@ -24,12 +24,4 @@ export default defineConfig({
|
||||
'@': __dirname + '/src',
|
||||
}
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
includePaths: [__dirname + '/src/scss'],
|
||||
prependData: `@import "${__dirname}/src/scss/mixins"; @import "${__dirname}/src/scss/vars";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user