mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-22 16:36:15 -04:00
resolve conflict with async test
This commit is contained in:
commit
a908bbee8e
14 changed files with 229 additions and 1139 deletions
|
@ -220,12 +220,12 @@ fs.readdir(pluginPath, (err, rootFiles) => {
|
|||
}
|
||||
|
||||
updateDeps(parsedPackageJSON, 'devDependencies', {
|
||||
'eslint': '^7.17.0',
|
||||
'eslint-config-etherpad': '^1.0.22',
|
||||
'eslint': '^7.18.0',
|
||||
'eslint-config-etherpad': '^1.0.24',
|
||||
'eslint-plugin-eslint-comments': '^3.2.0',
|
||||
'eslint-plugin-mocha': '^8.0.0',
|
||||
'eslint-plugin-node': '^11.1.0',
|
||||
'eslint-plugin-prefer-arrow': '^1.2.2',
|
||||
'eslint-plugin-prefer-arrow': '^1.2.3',
|
||||
'eslint-plugin-promise': '^4.2.1',
|
||||
'eslint-plugin-you-dont-need-lodash-underscore': '^6.10.0',
|
||||
});
|
||||
|
|
174
package-lock.json
generated
174
package-lock.json
generated
|
@ -74,9 +74,9 @@
|
|||
}
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz",
|
||||
"integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==",
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz",
|
||||
"integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
|
@ -86,7 +86,7 @@
|
|||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"lodash": "^4.17.19",
|
||||
"lodash": "^4.17.20",
|
||||
"minimatch": "^3.0.4",
|
||||
"strip-json-comments": "^3.1.1"
|
||||
}
|
||||
|
@ -321,9 +321,9 @@
|
|||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"astral-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
|
@ -743,9 +743,9 @@
|
|||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"engine.io": {
|
||||
|
@ -2450,6 +2450,11 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8410,13 +8415,13 @@
|
|||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.15.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.15.0.tgz",
|
||||
"integrity": "sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz",
|
||||
"integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@eslint/eslintrc": "^0.2.2",
|
||||
"@eslint/eslintrc": "^0.3.0",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.2",
|
||||
|
@ -8440,7 +8445,7 @@
|
|||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
"lodash": "^4.17.19",
|
||||
"lodash": "^4.17.20",
|
||||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
|
@ -8449,15 +8454,15 @@
|
|||
"semver": "^7.2.1",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"table": "^5.2.3",
|
||||
"table": "^6.0.4",
|
||||
"text-table": "^0.2.0",
|
||||
"v8-compile-cache": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"eslint-config-etherpad": {
|
||||
"version": "1.0.20",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-etherpad/-/eslint-config-etherpad-1.0.20.tgz",
|
||||
"integrity": "sha512-dDEmWphxOmYe7XC0Uevzb0lK7o1jDBGwYMMCdNeZlgo2EfJljnijPgodlimM4R+4OsnfegEMY6rdWoXjzdd5Rw==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-etherpad/-/eslint-config-etherpad-1.0.24.tgz",
|
||||
"integrity": "sha512-zM92/lricP0ALURQWhSFKk8gwDUVkgNiup/Gv5lly6bHj9OIMpK86SlLv/NPkQZYM609pyQjKIeiObsiCSdQsw==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-es": {
|
||||
|
@ -8527,9 +8532,9 @@
|
|||
}
|
||||
},
|
||||
"eslint-plugin-prefer-arrow": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.2.tgz",
|
||||
"integrity": "sha512-C8YMhL+r8RMeMdYAw/rQtE6xNdMulj+zGWud/qIGnlmomiPRaLDGLMeskZ3alN6uMBojmooRimtdrXebLN4svQ==",
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz",
|
||||
"integrity": "sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-promise": {
|
||||
|
@ -8702,9 +8707,9 @@
|
|||
}
|
||||
},
|
||||
"flatted": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz",
|
||||
"integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
|
||||
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"forever-agent": {
|
||||
|
@ -8977,9 +8982,9 @@
|
|||
}
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz",
|
||||
"integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
|
@ -9869,6 +9874,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dev": true
|
||||
},
|
||||
"require_optional": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
|
||||
|
@ -9992,14 +10003,46 @@
|
|||
}
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
|
||||
"integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
||||
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.0",
|
||||
"astral-regex": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^2.0.0"
|
||||
"ansi-styles": "^4.0.0",
|
||||
"astral-regex": "^2.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"socket.io": {
|
||||
|
@ -10176,30 +10219,21 @@
|
|||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^5.1.0"
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -10243,15 +10277,35 @@
|
|||
}
|
||||
},
|
||||
"table": {
|
||||
"version": "5.4.6",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
|
||||
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
|
||||
"version": "6.0.7",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
|
||||
"integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.10.2",
|
||||
"lodash": "^4.17.14",
|
||||
"slice-ansi": "^2.1.0",
|
||||
"string-width": "^3.0.0"
|
||||
"ajv": "^7.0.2",
|
||||
"lodash": "^4.17.20",
|
||||
"slice-ansi": "^4.0.0",
|
||||
"string-width": "^4.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
|
||||
"integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
"ep_etherpad-lite": "file:src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-etherpad": "^1.0.20",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-config-etherpad": "^1.0.24",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-mocha": "^8.0.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.2",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0"
|
||||
},
|
||||
|
|
|
@ -11,24 +11,42 @@
|
|||
"Sebastian Wallroth",
|
||||
"Thargon",
|
||||
"Tim.krieger",
|
||||
"Wikinaut"
|
||||
"Wikinaut",
|
||||
"Zunkelty"
|
||||
]
|
||||
},
|
||||
"admin.page-title": "Admin Dashboard - Etherpad",
|
||||
"admin_plugins": "Plugins verwalten",
|
||||
"admin_plugins.available": "Verfügbare Plugins",
|
||||
"admin_plugins.available_not-found": "Keine Plugins gefunden.",
|
||||
"admin_plugins.available_fetching": "Wird abgerufen...",
|
||||
"admin_plugins.available_install.value": "Installieren",
|
||||
"admin_plugins.available_search.placeholder": "Suche nach Plugins zum Installieren",
|
||||
"admin_plugins.description": "Beschreibung",
|
||||
"admin_plugins.installed": "Installierte Plugins",
|
||||
"admin_plugins.installed_fetching": "Rufe installierte Plugins ab...",
|
||||
"admin_plugins.installed_nothing": "Du hast bisher noch keine Plugins installiert.",
|
||||
"admin_plugins.installed_uninstall.value": "Deinstallieren",
|
||||
"admin_plugins.last-update": "Letze Aktualisierung",
|
||||
"admin_plugins.name": "Name",
|
||||
"admin_plugins.page-title": "Plugin Manager - Etherpad",
|
||||
"admin_plugins.version": "Version",
|
||||
"admin_plugins_info": "Hilfestellung",
|
||||
"admin_plugins_info.hooks": "Installierte Hooks",
|
||||
"admin_plugins_info.hooks_client": "Client-seitige Hooks",
|
||||
"admin_plugins_info.hooks_server": "Server-seitige Hooks",
|
||||
"admin_plugins_info.parts": "Installierte Teile",
|
||||
"admin_plugins_info.plugins": "Installierte Plugins",
|
||||
"admin_plugins_info.page-title": "Plugin Informationen - Etherpad",
|
||||
"admin_plugins_info.version": "Etherpad Version",
|
||||
"admin_plugins_info.version_latest": "Neueste Version",
|
||||
"admin_plugins_info.version_number": "Versionsnummer",
|
||||
"admin_settings": "Einstellungen",
|
||||
"admin_settings.current": "Derzeitige Konfiguration",
|
||||
"admin_settings.current_example-devel": "Beispielhafte Entwicklungseinstellungs-Templates",
|
||||
"admin_settings.current_restart.value": "Etherpad neustarten",
|
||||
"admin_settings.current_save.value": "Einstellungen speichern",
|
||||
"admin_settings.page-title": "Einstellungen - Etherpad",
|
||||
"index.newPad": "Neues Pad",
|
||||
"index.createOpenPad": "oder ein Pad mit folgendem Namen erstellen/öffnen:",
|
||||
"index.openPad": "Öffne ein vorhandenes Pad mit folgendem Namen:",
|
||||
|
@ -78,7 +96,7 @@
|
|||
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
||||
"pad.importExport.abiword.innerHTML": "Du kannst nur aus reinen Text- oder HTML-Formaten importieren. Für umfangreichere Importfunktionen <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">muss AbiWord oder LibreOffice auf dem Server installiert werden</a>.",
|
||||
"pad.modals.connected": "Verbunden.",
|
||||
"pad.modals.reconnecting": "Wiederherstellen der Verbindung …",
|
||||
"pad.modals.reconnecting": "Dein Pad wird neu verbunden...",
|
||||
"pad.modals.forcereconnect": "Erneutes Verbinden erzwingen",
|
||||
"pad.modals.reconnecttimer": "Versuche Neuverbindung in",
|
||||
"pad.modals.cancel": "Abbrechen",
|
||||
|
@ -102,6 +120,7 @@
|
|||
"pad.modals.deleted.explanation": "Dieses Pad wurde entfernt.",
|
||||
"pad.modals.rateLimited": "Begrenzte Rate.",
|
||||
"pad.modals.rateLimited.explanation": "Sie haben zu viele Nachrichten an dieses Pad gesendet, so dass die Verbindung unterbrochen wurde.",
|
||||
"pad.modals.rejected.explanation": "Der Server hat eine Nachricht abgelehnt, die von deinem Browser gesendet wurde.",
|
||||
"pad.modals.disconnected": "Ihre Verbindung wurde getrennt.",
|
||||
"pad.modals.disconnected.explanation": "Die Verbindung zum Server wurde unterbrochen.",
|
||||
"pad.modals.disconnected.cause": "Möglicherweise ist der Server nicht erreichbar. Bitte benachrichtige den Dienstadministrator, falls dies weiterhin passiert.",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"VezonThunder"
|
||||
]
|
||||
},
|
||||
"admin_plugins.available": "Saatavilla olevat liitännäiset",
|
||||
"admin_plugins.available_install.value": "Lataa",
|
||||
"admin_plugins.available_search.placeholder": "Etsi asennettavia laajennuksia",
|
||||
"admin_plugins.description": "Kuvaus",
|
||||
|
@ -92,7 +93,7 @@
|
|||
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
||||
"pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Monipuoliset tuontiominaisuudet ovat käytettävissä <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">asentamalla AbiWordin tai LibreOfficen</a>.",
|
||||
"pad.modals.connected": "Yhdistetty.",
|
||||
"pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...",
|
||||
"pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen…",
|
||||
"pad.modals.forcereconnect": "Pakota yhdistämään uudelleen",
|
||||
"pad.modals.reconnecttimer": "Yritetään yhdistää uudelleen",
|
||||
"pad.modals.cancel": "Peruuta",
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
"Upwinxp"
|
||||
]
|
||||
},
|
||||
"admin_plugins.last-update": "Zadnja posodobitev",
|
||||
"admin_plugins.name": "Ime",
|
||||
"admin_plugins.version": "Različica",
|
||||
"admin_settings": "Nastavitve",
|
||||
"index.newPad": "Nov dokument",
|
||||
"index.createOpenPad": "ali pa ustvari/odpri dokument z imenom:",
|
||||
"pad.toolbar.bold.title": "Krepko (Ctrl-B)",
|
||||
|
@ -54,7 +58,7 @@
|
|||
"pad.importExport.exportword": "DOC (zapis Microsoft Word)",
|
||||
"pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)",
|
||||
"pad.importExport.exportopen": "ODF (zapis Open Document)",
|
||||
"pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">program AbiWord</a>.",
|
||||
"pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le neoblikovano besedilo in zapise HTML. Za naprednejše možnosti uvoza namestite program <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">AbiWord</a>.",
|
||||
"pad.modals.connected": "Povezano.",
|
||||
"pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...",
|
||||
"pad.modals.forcereconnect": "Vsili ponovno povezavo",
|
||||
|
@ -64,7 +68,7 @@
|
|||
"pad.modals.userdup.explanation": "Videti je, da je ta dokument odprt v več kot enem oknu brskalnika na tem računalniku.",
|
||||
"pad.modals.userdup.advice": "Ponovno vzpostavite povezavo in uporabljajte to okno.",
|
||||
"pad.modals.unauth": "Nepooblaščen dostop",
|
||||
"pad.modals.unauth.explanation": "Med pregledovanjem te strani so se dovoljenja za ogled spremenila. Poskusite se ponovno povezati.",
|
||||
"pad.modals.unauth.explanation": "Med ogledovanjem strani so se dovoljenja za ogled spremenila. Poskusite se znova povezati.",
|
||||
"pad.modals.looping.explanation": "Zaznane so težave pri komunikaciji s strežnikom za usklajevanje.",
|
||||
"pad.modals.looping.cause": "Morda ste se povezali preko neustrezno nastavljenega požarnega zidu ali posredniškega strežnika.",
|
||||
"pad.modals.initsocketfail": "Strežnik je nedosegljiv.",
|
||||
|
|
|
@ -1217,7 +1217,7 @@ const handleChangesetRequest = async (socket, message) => {
|
|||
socket.json.send({type: 'CHANGESET_REQ', data});
|
||||
} catch (err) {
|
||||
console.error(`Error while handling a changeset request for ${padIds.padId}`,
|
||||
err.toString(), message.data);
|
||||
err.toString(), message.data);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
990
src/package-lock.json
generated
990
src/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -78,18 +78,17 @@
|
|||
"etherpad-lite": "node/server.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-etherpad": "^1.0.20",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-config-etherpad": "^1.0.24",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-mocha": "^8.0.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.2",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
|
||||
"etherpad-cli-client": "0.0.9",
|
||||
"mocha": "7.1.2",
|
||||
"mocha-froth": "^0.2.10",
|
||||
"nyc": "15.0.1",
|
||||
"set-cookie-parser": "^2.4.6",
|
||||
"sinon": "^9.2.0",
|
||||
"superagent": "^3.8.3",
|
||||
|
@ -148,8 +147,8 @@
|
|||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "nyc mocha --timeout 120000 --recursive ../tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs",
|
||||
"test-container": "nyc mocha --timeout 5000 ../tests/container/specs/api"
|
||||
"test": "mocha --timeout 120000 --recursive ../tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs",
|
||||
"test-container": "mocha --timeout 5000 ../tests/container/specs/api"
|
||||
},
|
||||
"version": "1.8.7",
|
||||
"license": "Apache-2.0"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
const Changeset = require('./Changeset');
|
||||
const ChangesetUtils = require('./ChangesetUtils');
|
||||
const _ = require('./underscore');
|
||||
|
@ -72,10 +74,12 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
|
||||
const rowChangeset = this._setAttributesOnRangeByLine(row, startCol, endCol, attribs);
|
||||
|
||||
// compose changesets of all rows into a single changeset, as the range might not be continuous
|
||||
// compose changesets of all rows into a single changeset
|
||||
// as the range might not be continuous
|
||||
// due to the presence of line markers on the rows
|
||||
if (allChangesets) {
|
||||
allChangesets = Changeset.compose(allChangesets.toString(), rowChangeset.toString(), this.rep.apool);
|
||||
allChangesets = Changeset.compose(
|
||||
allChangesets.toString(), rowChangeset.toString(), this.rep.apool);
|
||||
} else {
|
||||
allChangesets = rowChangeset;
|
||||
}
|
||||
|
@ -118,7 +122,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
_setAttributesOnRangeByLine(row, startCol, endCol, attribs) {
|
||||
const builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||
ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [row, startCol]);
|
||||
ChangesetUtils.buildKeepRange(this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
||||
ChangesetUtils.buildKeepRange(
|
||||
this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
||||
return builder;
|
||||
},
|
||||
|
||||
|
@ -127,9 +132,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
@param lineNum: the number of the line
|
||||
*/
|
||||
lineHasMarker(lineNum) {
|
||||
const that = this;
|
||||
|
||||
return _.find(lineAttributes, (attribute) => that.getAttributeOnLine(lineNum, attribute) != '') !== undefined;
|
||||
return lineAttributes.find(
|
||||
(attribute) => this.getAttributeOnLine(lineNum, attribute) !== '') !== undefined;
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -184,7 +188,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
if (!(rep.selStart && rep.selEnd)) return;
|
||||
// If we're looking for the caret attribute not the selection
|
||||
// has the user already got a selection or is this purely a caret location?
|
||||
const isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
|
||||
const isNotSelection = (rep.selStart[0] === rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
|
||||
if (isNotSelection) {
|
||||
if (prevChar) {
|
||||
// If it's not the start of the line
|
||||
|
@ -198,21 +202,18 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
[attributeName, 'true'],
|
||||
], rep.apool);
|
||||
const withItRegex = new RegExp(`${withIt.replace(/\*/g, '\\*')}(\\*|$)`);
|
||||
function hasIt(attribs) {
|
||||
return withItRegex.test(attribs);
|
||||
}
|
||||
const hasIt = (attribs) => withItRegex.test(attribs);
|
||||
|
||||
return rangeHasAttrib(rep.selStart, rep.selEnd);
|
||||
|
||||
function rangeHasAttrib(selStart, selEnd) {
|
||||
const rangeHasAttrib = (selStart, selEnd) => {
|
||||
// if range is collapsed -> no attribs in range
|
||||
if (selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false;
|
||||
if (selStart[1] === selEnd[1] && selStart[0] === selEnd[0]) return false;
|
||||
|
||||
if (selStart[0] != selEnd[0]) { // -> More than one line selected
|
||||
var hasAttrib = true;
|
||||
if (selStart[0] !== selEnd[0]) { // -> More than one line selected
|
||||
let hasAttrib = true;
|
||||
|
||||
// from selStart to the end of the first line
|
||||
hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]);
|
||||
hasAttrib = hasAttrib && rangeHasAttrib(
|
||||
selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]);
|
||||
|
||||
// for all lines in between
|
||||
for (let n = selStart[0] + 1; n < selEnd[0]; n++) {
|
||||
|
@ -230,7 +231,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
const lineNum = selStart[0];
|
||||
const start = selStart[1];
|
||||
const end = selEnd[1];
|
||||
var hasAttrib = true;
|
||||
let hasAttrib = true;
|
||||
|
||||
// Iterate over attribs on this line
|
||||
|
||||
|
@ -244,7 +245,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
if (!hasIt(op.attribs)) {
|
||||
// does op overlap selection?
|
||||
if (!(opEndInLine <= start || opStartInLine >= end)) {
|
||||
hasAttrib = false; // since it's overlapping but hasn't got the attrib -> range hasn't got it
|
||||
// since it's overlapping but hasn't got the attrib -> range hasn't got it
|
||||
hasAttrib = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +254,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
}
|
||||
|
||||
return hasAttrib;
|
||||
}
|
||||
};
|
||||
return rangeHasAttrib(rep.selStart, rep.selEnd);
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -349,13 +352,13 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
const hasMarker = this.lineHasMarker(lineNum);
|
||||
let found = false;
|
||||
|
||||
const attribs = _(this.getAttributesOnLine(lineNum)).map(function (attrib) {
|
||||
const attribs = this.getAttributesOnLine(lineNum).map((attrib) => {
|
||||
if (attrib[0] === attributeName && (!attributeValue || attrib[0] === attributeValue)) {
|
||||
found = true;
|
||||
return [attributeName, ''];
|
||||
return [attrib[0], ''];
|
||||
} else if (attrib[0] === 'author') {
|
||||
// update last author to make changes to line attributes on this line
|
||||
return [attributeName, this.author];
|
||||
return [attrib[0], this.author];
|
||||
}
|
||||
return attrib;
|
||||
});
|
||||
|
@ -373,7 +376,8 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
if (hasMarker && !countAttribsWithMarker) {
|
||||
ChangesetUtils.buildRemoveRange(this.rep, builder, [lineNum, 0], [lineNum, 1]);
|
||||
} else {
|
||||
ChangesetUtils.buildKeepRange(this.rep, builder, [lineNum, 0], [lineNum, 1], attribs, this.rep.apool);
|
||||
ChangesetUtils.buildKeepRange(
|
||||
this.rep, builder, [lineNum, 0], [lineNum, 1], attribs, this.rep.apool);
|
||||
}
|
||||
|
||||
return this.applyChangeset(builder);
|
||||
|
@ -394,7 +398,9 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
},
|
||||
|
||||
hasAttributeOnSelectionOrCaretPosition(attributeName) {
|
||||
const hasSelection = ((this.rep.selStart[0] !== this.rep.selEnd[0]) || (this.rep.selEnd[1] !== this.rep.selStart[1]));
|
||||
const hasSelection = (
|
||||
(this.rep.selStart[0] !== this.rep.selEnd[0]) || (this.rep.selEnd[1] !== this.rep.selStart[1])
|
||||
);
|
||||
let hasAttrib;
|
||||
if (hasSelection) {
|
||||
hasAttrib = this.getAttributeOnSelection(attributeName);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
|
@ -22,33 +24,23 @@
|
|||
|
||||
const Security = require('./security');
|
||||
|
||||
function isNodeText(node) {
|
||||
return (node.nodeType == 3);
|
||||
}
|
||||
const isNodeText = (node) => (node.nodeType === 3);
|
||||
|
||||
function object(o) {
|
||||
const f = function () {};
|
||||
f.prototype = o;
|
||||
return new f();
|
||||
}
|
||||
const getAssoc = (obj, name) => obj[`_magicdom_${name}`];
|
||||
|
||||
function getAssoc(obj, name) {
|
||||
return obj[`_magicdom_${name}`];
|
||||
}
|
||||
|
||||
function setAssoc(obj, name, value) {
|
||||
const setAssoc = (obj, name, value) => {
|
||||
// note that in IE designMode, properties of a node can get
|
||||
// copied to new nodes that are spawned during editing; also,
|
||||
// properties representable in HTML text can survive copy-and-paste
|
||||
obj[`_magicdom_${name}`] = value;
|
||||
}
|
||||
};
|
||||
|
||||
// "func" is a function over 0..(numItems-1) that is monotonically
|
||||
// "increasing" with index (false, then true). Finds the boundary
|
||||
// between false and true, a number between 0 and numItems inclusive.
|
||||
|
||||
|
||||
function binarySearch(numItems, func) {
|
||||
const binarySearch = (numItems, func) => {
|
||||
if (numItems < 1) return 0;
|
||||
if (func(0)) return 0;
|
||||
if (!func(numItems - 1)) return numItems;
|
||||
|
@ -60,22 +52,19 @@ function binarySearch(numItems, func) {
|
|||
else low = x;
|
||||
}
|
||||
return high;
|
||||
}
|
||||
};
|
||||
|
||||
function binarySearchInfinite(expectedLength, func) {
|
||||
const binarySearchInfinite = (expectedLength, func) => {
|
||||
let i = 0;
|
||||
while (!func(i)) i += expectedLength;
|
||||
return binarySearch(i, func);
|
||||
}
|
||||
};
|
||||
|
||||
function htmlPrettyEscape(str) {
|
||||
return Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
|
||||
}
|
||||
const htmlPrettyEscape = (str) => Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
|
||||
|
||||
const noop = function () {};
|
||||
const noop = () => {};
|
||||
|
||||
exports.isNodeText = isNodeText;
|
||||
exports.object = object;
|
||||
exports.getAssoc = getAssoc;
|
||||
exports.setAssoc = setAssoc;
|
||||
exports.binarySearch = binarySearch;
|
||||
|
|
|
@ -113,7 +113,7 @@ const reconnectionTries = {
|
|||
|
||||
nextTry() {
|
||||
// double the time to try to reconnect on every time reconnection fails
|
||||
const nextCounterFactor = Math.pow(2, this.counter);
|
||||
const nextCounterFactor = 2 ** this.counter;
|
||||
this.counter++;
|
||||
|
||||
return nextCounterFactor;
|
||||
|
|
|
@ -55,7 +55,7 @@ const tsort = (edges) => {
|
|||
Object.keys(nodes).forEach(visit);
|
||||
|
||||
return sorted;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* TEST
|
||||
|
|
|
@ -136,42 +136,40 @@ describe('indentation button', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("issue #2772 shows '*' when multiple indented lines receive a style and are outdented", function (done) {
|
||||
it("issue #2772 shows '*' when multiple indented lines receive a style and are outdented", async function () {
|
||||
this.timeout(1200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// make sure pad has more than one line
|
||||
inner$('div').first().sendkeys('First{enter}Second{enter}');
|
||||
helper.waitFor(() => inner$('div').first().text().trim() === 'First').done(() => {
|
||||
// indent first 2 lines
|
||||
const $lines = inner$('div');
|
||||
const $firstLine = $lines.first();
|
||||
const $secondLine = $lines.slice(1, 2);
|
||||
helper.selectLines($firstLine, $secondLine);
|
||||
await helper.waitForPromise(() => inner$('div').first().text().trim() === 'First');
|
||||
|
||||
const $indentButton = chrome$('.buttonicon-indent');
|
||||
$indentButton.click();
|
||||
// indent first 2 lines
|
||||
const $lines = inner$('div');
|
||||
const $firstLine = $lines.first();
|
||||
let $secondLine = $lines.slice(1, 2);
|
||||
helper.selectLines($firstLine, $secondLine);
|
||||
|
||||
helper.waitFor(() => inner$('div').first().find('ul li').length === 1).done(() => {
|
||||
// apply bold
|
||||
const $boldButton = chrome$('.buttonicon-bold');
|
||||
$boldButton.click();
|
||||
const $indentButton = chrome$('.buttonicon-indent');
|
||||
$indentButton.click();
|
||||
|
||||
helper.waitFor(() => inner$('div').first().find('b').length === 1).done(() => {
|
||||
// outdent first 2 lines
|
||||
const $outdentButton = chrome$('.buttonicon-outdent');
|
||||
$outdentButton.click();
|
||||
helper.waitFor(() => inner$('div').first().find('ul li').length === 0).done(() => {
|
||||
// check if '*' is displayed
|
||||
const $secondLine = inner$('div').slice(1, 2);
|
||||
expect($secondLine.text().trim()).to.be('Second');
|
||||
await helper.waitForPromise(() => inner$('div').first().find('ul li').length === 1);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
// apply bold
|
||||
const $boldButton = chrome$('.buttonicon-bold');
|
||||
$boldButton.click();
|
||||
|
||||
await helper.waitForPromise(() => inner$('div').first().find('b').length === 1);
|
||||
|
||||
// outdent first 2 lines
|
||||
const $outdentButton = chrome$('.buttonicon-outdent');
|
||||
$outdentButton.click();
|
||||
await helper.waitForPromise(() => inner$('div').first().find('ul li').length === 0);
|
||||
|
||||
// check if '*' is displayed
|
||||
$secondLine = inner$('div').slice(1, 2);
|
||||
expect($secondLine.text().trim()).to.be('Second');
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue