sv 0.6.14 → 0.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +38 -21
- package/dist/index.js +2 -2
- package/dist/{install-DJcXCdFP.js → install-k7_ajcbZ.js} +91 -25
- package/dist/templates/demo/files.types=checkjs.json +1 -1
- package/dist/templates/demo/files.types=none.json +1 -1
- package/dist/templates/demo/files.types=typescript.json +1 -1
- package/dist/templates/demo/package.json +2 -1
- package/dist/templates/library/package.json +1 -0
- package/dist/templates/minimal/package.json +2 -1
- package/dist/testing.js +1 -1
- package/package.json +3 -3
- package/dist/{main-UNazaUHM.js → main-CCykm_Ik.js} +3 -3
package/dist/bin.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { g as getDefaultExportFromCjs$2, a as commonjsGlobal, t as templates, c as create$1 } from './main-
|
|
2
|
+
import { g as getDefaultExportFromCjs$2, a as commonjsGlobal, t as templates, c as create$1 } from './main-CCykm_Ik.js';
|
|
3
3
|
import require$$0 from 'node:events';
|
|
4
4
|
import require$$1, { exec, execSync } from 'node:child_process';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import process$1 from 'node:process';
|
|
8
|
-
import { u as up$1, d as dedent, p as parseJson, a as parseScript, b as imports, c as common, e as exports$1, o as object$1, v as variables, _ as _function, f as parseSvelte, g as array$1, w as walk$1, k as kit, h as addFromString, E as Element, j as index, l as parseHtml, m as parseHtml$1, A as AtRule, n as parseCss, q as pc, r as intro, s as outro, t as log$1, x as cancel, y as box, z as multiselect, B as isCancel, C as confirm, D as createWorkspace, F as setupAddons, G as note, H as select, I as text, J as packageManagerPrompt, K as applyAddons, L as installDependencies, M as formatFiles, N as spinner, O as getHighlighter, P as detectSync, Q as getUserAgent, R as resolveCommand, S as group, T as from } from './install-
|
|
8
|
+
import { u as up$1, d as dedent, p as parseJson, a as parseScript, b as imports, c as common, e as exports$1, o as object$1, v as variables, _ as _function, f as parseSvelte, g as array$1, w as walk$1, k as kit, h as addFromString, E as Element, j as index, l as parseHtml, m as parseHtml$1, A as AtRule, n as parseCss, q as pc, r as intro, s as outro, t as log$1, x as cancel, y as box, z as multiselect, B as isCancel, C as confirm, D as createWorkspace, F as setupAddons, G as note, H as select, I as text, J as packageManagerPrompt, K as applyAddons, L as installDependencies, M as formatFiles, N as spinner, O as getHighlighter, P as detectSync, Q as getUserAgent, R as resolveCommand, S as group, T as from } from './install-k7_ajcbZ.js';
|
|
9
9
|
import 'node:readline';
|
|
10
10
|
import 'node:tty';
|
|
11
11
|
import { createGunzip } from 'node:zlib';
|
|
@@ -25,7 +25,7 @@ import 'url';
|
|
|
25
25
|
import 'node:fs/promises';
|
|
26
26
|
|
|
27
27
|
var name = "sv";
|
|
28
|
-
var version = "0.6.
|
|
28
|
+
var version = "0.6.16";
|
|
29
29
|
var type = "module";
|
|
30
30
|
var description = "A CLI for creating and updating SvelteKit projects";
|
|
31
31
|
var license = "MIT";
|
|
@@ -6016,7 +6016,7 @@ class Chunk {
|
|
|
6016
6016
|
// ' test'.trim()
|
|
6017
6017
|
// split -> ' ' + 'test'
|
|
6018
6018
|
// ✔️ edit -> '' + 'test'
|
|
6019
|
-
// ✖️ edit -> 'test' + ''
|
|
6019
|
+
// ✖️ edit -> 'test' + ''
|
|
6020
6020
|
// TODO is this block necessary?...
|
|
6021
6021
|
newChunk.edit('', false);
|
|
6022
6022
|
this.content = '';
|
|
@@ -6263,6 +6263,7 @@ class Mappings {
|
|
|
6263
6263
|
this.raw[this.generatedCodeLine] = this.rawSegments = [];
|
|
6264
6264
|
this.generatedCodeColumn = 0;
|
|
6265
6265
|
first = true;
|
|
6266
|
+
charInHiresBoundary = false;
|
|
6266
6267
|
} else {
|
|
6267
6268
|
if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
|
|
6268
6269
|
const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
|
|
@@ -6340,6 +6341,7 @@ class MagicString {
|
|
|
6340
6341
|
storedNames: { writable: true, value: {} },
|
|
6341
6342
|
indentStr: { writable: true, value: undefined },
|
|
6342
6343
|
ignoreList: { writable: true, value: options.ignoreList },
|
|
6344
|
+
offset: { writable: true, value: options.offset || 0 },
|
|
6343
6345
|
});
|
|
6344
6346
|
|
|
6345
6347
|
this.byStart[0] = chunk;
|
|
@@ -6358,6 +6360,8 @@ class MagicString {
|
|
|
6358
6360
|
}
|
|
6359
6361
|
|
|
6360
6362
|
appendLeft(index, content) {
|
|
6363
|
+
index = index + this.offset;
|
|
6364
|
+
|
|
6361
6365
|
if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
|
|
6362
6366
|
|
|
6363
6367
|
this._split(index);
|
|
@@ -6373,6 +6377,8 @@ class MagicString {
|
|
|
6373
6377
|
}
|
|
6374
6378
|
|
|
6375
6379
|
appendRight(index, content) {
|
|
6380
|
+
index = index + this.offset;
|
|
6381
|
+
|
|
6376
6382
|
if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
|
|
6377
6383
|
|
|
6378
6384
|
this._split(index);
|
|
@@ -6388,7 +6394,7 @@ class MagicString {
|
|
|
6388
6394
|
}
|
|
6389
6395
|
|
|
6390
6396
|
clone() {
|
|
6391
|
-
const cloned = new MagicString(this.original, { filename: this.filename });
|
|
6397
|
+
const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });
|
|
6392
6398
|
|
|
6393
6399
|
let originalChunk = this.firstChunk;
|
|
6394
6400
|
let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
|
|
@@ -6586,7 +6592,7 @@ class MagicString {
|
|
|
6586
6592
|
if (!warned.insertLeft) {
|
|
6587
6593
|
console.warn(
|
|
6588
6594
|
'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',
|
|
6589
|
-
);
|
|
6595
|
+
);
|
|
6590
6596
|
warned.insertLeft = true;
|
|
6591
6597
|
}
|
|
6592
6598
|
|
|
@@ -6597,7 +6603,7 @@ class MagicString {
|
|
|
6597
6603
|
if (!warned.insertRight) {
|
|
6598
6604
|
console.warn(
|
|
6599
6605
|
'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',
|
|
6600
|
-
);
|
|
6606
|
+
);
|
|
6601
6607
|
warned.insertRight = true;
|
|
6602
6608
|
}
|
|
6603
6609
|
|
|
@@ -6605,6 +6611,10 @@ class MagicString {
|
|
|
6605
6611
|
}
|
|
6606
6612
|
|
|
6607
6613
|
move(start, end, index) {
|
|
6614
|
+
start = start + this.offset;
|
|
6615
|
+
end = end + this.offset;
|
|
6616
|
+
index = index + this.offset;
|
|
6617
|
+
|
|
6608
6618
|
if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');
|
|
6609
6619
|
|
|
6610
6620
|
this._split(start);
|
|
@@ -6647,6 +6657,9 @@ class MagicString {
|
|
|
6647
6657
|
}
|
|
6648
6658
|
|
|
6649
6659
|
update(start, end, content, options) {
|
|
6660
|
+
start = start + this.offset;
|
|
6661
|
+
end = end + this.offset;
|
|
6662
|
+
|
|
6650
6663
|
if (typeof content !== 'string') throw new TypeError('replacement content must be a string');
|
|
6651
6664
|
|
|
6652
6665
|
if (this.original.length !== 0) {
|
|
@@ -6667,7 +6680,7 @@ class MagicString {
|
|
|
6667
6680
|
if (!warned.storeName) {
|
|
6668
6681
|
console.warn(
|
|
6669
6682
|
'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',
|
|
6670
|
-
);
|
|
6683
|
+
);
|
|
6671
6684
|
warned.storeName = true;
|
|
6672
6685
|
}
|
|
6673
6686
|
|
|
@@ -6718,6 +6731,8 @@ class MagicString {
|
|
|
6718
6731
|
}
|
|
6719
6732
|
|
|
6720
6733
|
prependLeft(index, content) {
|
|
6734
|
+
index = index + this.offset;
|
|
6735
|
+
|
|
6721
6736
|
if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
|
|
6722
6737
|
|
|
6723
6738
|
this._split(index);
|
|
@@ -6733,6 +6748,8 @@ class MagicString {
|
|
|
6733
6748
|
}
|
|
6734
6749
|
|
|
6735
6750
|
prependRight(index, content) {
|
|
6751
|
+
index = index + this.offset;
|
|
6752
|
+
|
|
6736
6753
|
if (typeof content !== 'string') throw new TypeError('inserted content must be a string');
|
|
6737
6754
|
|
|
6738
6755
|
this._split(index);
|
|
@@ -6748,6 +6765,9 @@ class MagicString {
|
|
|
6748
6765
|
}
|
|
6749
6766
|
|
|
6750
6767
|
remove(start, end) {
|
|
6768
|
+
start = start + this.offset;
|
|
6769
|
+
end = end + this.offset;
|
|
6770
|
+
|
|
6751
6771
|
if (this.original.length !== 0) {
|
|
6752
6772
|
while (start < 0) start += this.original.length;
|
|
6753
6773
|
while (end < 0) end += this.original.length;
|
|
@@ -6774,6 +6794,9 @@ class MagicString {
|
|
|
6774
6794
|
}
|
|
6775
6795
|
|
|
6776
6796
|
reset(start, end) {
|
|
6797
|
+
start = start + this.offset;
|
|
6798
|
+
end = end + this.offset;
|
|
6799
|
+
|
|
6777
6800
|
if (this.original.length !== 0) {
|
|
6778
6801
|
while (start < 0) start += this.original.length;
|
|
6779
6802
|
while (end < 0) end += this.original.length;
|
|
@@ -6838,7 +6861,10 @@ class MagicString {
|
|
|
6838
6861
|
return this.intro + lineStr;
|
|
6839
6862
|
}
|
|
6840
6863
|
|
|
6841
|
-
slice(start = 0, end = this.original.length) {
|
|
6864
|
+
slice(start = 0, end = this.original.length - this.offset) {
|
|
6865
|
+
start = start + this.offset;
|
|
6866
|
+
end = end + this.offset;
|
|
6867
|
+
|
|
6842
6868
|
if (this.original.length !== 0) {
|
|
6843
6869
|
while (start < 0) start += this.original.length;
|
|
6844
6870
|
while (end < 0) end += this.original.length;
|
|
@@ -7074,11 +7100,7 @@ class MagicString {
|
|
|
7074
7100
|
if (match.index != null) {
|
|
7075
7101
|
const replacement = getReplacement(match, this.original);
|
|
7076
7102
|
if (replacement !== match[0]) {
|
|
7077
|
-
this.overwrite(
|
|
7078
|
-
match.index,
|
|
7079
|
-
match.index + match[0].length,
|
|
7080
|
-
replacement
|
|
7081
|
-
);
|
|
7103
|
+
this.overwrite(match.index, match.index + match[0].length, replacement);
|
|
7082
7104
|
}
|
|
7083
7105
|
}
|
|
7084
7106
|
});
|
|
@@ -7087,11 +7109,7 @@ class MagicString {
|
|
|
7087
7109
|
if (match && match.index != null) {
|
|
7088
7110
|
const replacement = getReplacement(match, this.original);
|
|
7089
7111
|
if (replacement !== match[0]) {
|
|
7090
|
-
this.overwrite(
|
|
7091
|
-
match.index,
|
|
7092
|
-
match.index + match[0].length,
|
|
7093
|
-
replacement
|
|
7094
|
-
);
|
|
7112
|
+
this.overwrite(match.index, match.index + match[0].length, replacement);
|
|
7095
7113
|
}
|
|
7096
7114
|
}
|
|
7097
7115
|
}
|
|
@@ -7126,8 +7144,7 @@ class MagicString {
|
|
|
7126
7144
|
index = original.indexOf(string, index + stringLength)
|
|
7127
7145
|
) {
|
|
7128
7146
|
const previous = original.slice(index, index + stringLength);
|
|
7129
|
-
if (previous !== replacement)
|
|
7130
|
-
this.overwrite(index, index + stringLength, replacement);
|
|
7147
|
+
if (previous !== replacement) this.overwrite(index, index + stringLength, replacement);
|
|
7131
7148
|
}
|
|
7132
7149
|
|
|
7133
7150
|
return this;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { c as create } from './main-
|
|
2
|
-
export { i as installAddon } from './install-
|
|
1
|
+
export { c as create } from './main-CCykm_Ik.js';
|
|
2
|
+
export { i as installAddon } from './install-k7_ajcbZ.js';
|
|
3
3
|
import 'node:fs';
|
|
4
4
|
import 'node:path';
|
|
5
5
|
import 'node:url';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as getDefaultExportFromCjs$3, b as be } from './main-
|
|
1
|
+
import { g as getDefaultExportFromCjs$3, b as be } from './main-CCykm_Ik.js';
|
|
2
2
|
import process$1, { stdin, stdout } from 'node:process';
|
|
3
3
|
import * as readline from 'node:readline';
|
|
4
4
|
import readline__default from 'node:readline';
|
|
@@ -3183,6 +3183,7 @@ function requireTypes() {
|
|
|
3183
3183
|
switch (len) {
|
|
3184
3184
|
case 0:
|
|
3185
3185
|
return "";
|
|
3186
|
+
// If there's only one initial capital letter, just lower-case it.
|
|
3186
3187
|
case 1:
|
|
3187
3188
|
return upperCasePrefix.toLowerCase();
|
|
3188
3189
|
default:
|
|
@@ -29206,11 +29207,15 @@ function requireLines() {
|
|
|
29206
29207
|
break;
|
|
29207
29208
|
}
|
|
29208
29209
|
case 11:
|
|
29210
|
+
// '\v'
|
|
29209
29211
|
case 12:
|
|
29212
|
+
// '\f'
|
|
29210
29213
|
case 13:
|
|
29214
|
+
// '\r'
|
|
29211
29215
|
case 65279:
|
|
29212
29216
|
break;
|
|
29213
29217
|
case 32:
|
|
29218
|
+
// ' '
|
|
29214
29219
|
default:
|
|
29215
29220
|
count += 1;
|
|
29216
29221
|
break;
|
|
@@ -30027,6 +30032,7 @@ function requireFastPath() {
|
|
|
30027
30032
|
return parent.type === "NullableTypeAnnotation";
|
|
30028
30033
|
case "Literal":
|
|
30029
30034
|
return parent.type === "MemberExpression" && isNumber2.check(node2.value) && name === "object" && parent.object === node2;
|
|
30035
|
+
// Babel 6 Literal split
|
|
30030
30036
|
case "NumericLiteral":
|
|
30031
30037
|
return parent.type === "MemberExpression" && name === "object" && parent.object === node2;
|
|
30032
30038
|
case "YieldExpression":
|
|
@@ -30654,6 +30660,7 @@ function requirePrinter() {
|
|
|
30654
30660
|
}, "body"));
|
|
30655
30661
|
return (0, lines_1.concat)(parts);
|
|
30656
30662
|
case "Noop":
|
|
30663
|
+
// Babel extension.
|
|
30657
30664
|
case "EmptyStatement":
|
|
30658
30665
|
return (0, lines_1.fromString)("");
|
|
30659
30666
|
case "ExpressionStatement":
|
|
@@ -30711,6 +30718,7 @@ function requirePrinter() {
|
|
|
30711
30718
|
case "SpreadElement":
|
|
30712
30719
|
case "SpreadElementPattern":
|
|
30713
30720
|
case "RestProperty":
|
|
30721
|
+
// Babel 6 for ObjectPattern
|
|
30714
30722
|
case "SpreadProperty":
|
|
30715
30723
|
case "SpreadPropertyPattern":
|
|
30716
30724
|
case "ObjectTypeSpreadProperty":
|
|
@@ -30858,6 +30866,10 @@ function requirePrinter() {
|
|
|
30858
30866
|
return path2.call(print, "exported");
|
|
30859
30867
|
case "Import":
|
|
30860
30868
|
return (0, lines_1.fromString)("import", options2);
|
|
30869
|
+
// Recast and ast-types currently support dynamic import(...) using
|
|
30870
|
+
// either this dedicated ImportExpression type or a CallExpression
|
|
30871
|
+
// whose callee has type Import.
|
|
30872
|
+
// https://github.com/benjamn/ast-types/pull/365#issuecomment-605214486
|
|
30861
30873
|
case "ImportExpression":
|
|
30862
30874
|
return (0, lines_1.concat)(["import(", path2.call(print, "source"), ")"]);
|
|
30863
30875
|
case "ImportDeclaration": {
|
|
@@ -30910,6 +30922,7 @@ function requirePrinter() {
|
|
|
30910
30922
|
return (0, lines_1.concat)([path2.call(print, "key"), ": ", path2.call(print, "value")]);
|
|
30911
30923
|
case "StaticBlock":
|
|
30912
30924
|
parts.push("static ");
|
|
30925
|
+
// Intentionally fall through to BlockStatement below.
|
|
30913
30926
|
case "BlockStatement": {
|
|
30914
30927
|
var naked_1 = path2.call(function(bodyPath) {
|
|
30915
30928
|
return printStatementSequence(bodyPath, options2, print);
|
|
@@ -30959,6 +30972,7 @@ function requirePrinter() {
|
|
|
30959
30972
|
return (0, lines_1.concat)(parts);
|
|
30960
30973
|
case "RecordExpression":
|
|
30961
30974
|
parts.push("#");
|
|
30975
|
+
// Intentionally fall through to printing the object literal...
|
|
30962
30976
|
case "ObjectExpression":
|
|
30963
30977
|
case "ObjectPattern":
|
|
30964
30978
|
case "ObjectTypeAnnotation": {
|
|
@@ -31033,6 +31047,7 @@ function requirePrinter() {
|
|
|
31033
31047
|
path2.call(print, "pattern")
|
|
31034
31048
|
]);
|
|
31035
31049
|
case "ObjectProperty":
|
|
31050
|
+
// Babel 6
|
|
31036
31051
|
case "Property": {
|
|
31037
31052
|
if (n.method || n.kind === "get" || n.kind === "set") {
|
|
31038
31053
|
return printMethod(path2, options2, print);
|
|
@@ -31052,7 +31067,9 @@ function requirePrinter() {
|
|
|
31052
31067
|
return (0, lines_1.concat)(parts);
|
|
31053
31068
|
}
|
|
31054
31069
|
case "ClassMethod":
|
|
31070
|
+
// Babel 6
|
|
31055
31071
|
case "ObjectMethod":
|
|
31072
|
+
// Babel 6
|
|
31056
31073
|
case "ClassPrivateMethod":
|
|
31057
31074
|
case "TSDeclareMethod":
|
|
31058
31075
|
return printMethod(path2, options2, print);
|
|
@@ -31062,6 +31079,7 @@ function requirePrinter() {
|
|
|
31062
31079
|
return (0, lines_1.concat)(["@", path2.call(print, "expression")]);
|
|
31063
31080
|
case "TupleExpression":
|
|
31064
31081
|
parts.push("#");
|
|
31082
|
+
// Intentionally fall through to printing the tuple elements...
|
|
31065
31083
|
case "ArrayExpression":
|
|
31066
31084
|
case "ArrayPattern": {
|
|
31067
31085
|
var elems = n.elements;
|
|
@@ -31127,6 +31145,7 @@ function requirePrinter() {
|
|
|
31127
31145
|
case "StringLiteral":
|
|
31128
31146
|
return (0, lines_1.fromString)(nodeStr(n.value, options2));
|
|
31129
31147
|
case "BooleanLiteral":
|
|
31148
|
+
// Babel 6 Literal split
|
|
31130
31149
|
case "Literal":
|
|
31131
31150
|
return (0, lines_1.fromString)(getPossibleRaw(n) || (typeof n.value === "string" ? nodeStr(n.value, options2) : n.value), options2);
|
|
31132
31151
|
case "Directive":
|
|
@@ -31328,6 +31347,7 @@ function requirePrinter() {
|
|
|
31328
31347
|
(0, lines_1.fromString)("\n").join(path2.map(print, "cases")),
|
|
31329
31348
|
"\n}"
|
|
31330
31349
|
]);
|
|
31350
|
+
// Note: ignoring n.lexical because it has no printing consequences.
|
|
31331
31351
|
case "SwitchCase":
|
|
31332
31352
|
if (n.test)
|
|
31333
31353
|
parts.push("case ", path2.call(print, "test"), ":");
|
|
@@ -31341,6 +31361,7 @@ function requirePrinter() {
|
|
|
31341
31361
|
return (0, lines_1.concat)(parts);
|
|
31342
31362
|
case "DebuggerStatement":
|
|
31343
31363
|
return (0, lines_1.fromString)("debugger;");
|
|
31364
|
+
// JSX extensions below.
|
|
31344
31365
|
case "JSXAttribute":
|
|
31345
31366
|
parts.push(path2.call(print, "name"));
|
|
31346
31367
|
if (n.value)
|
|
@@ -31565,6 +31586,8 @@ function requirePrinter() {
|
|
|
31565
31586
|
}
|
|
31566
31587
|
case "TaggedTemplateExpression":
|
|
31567
31588
|
return (0, lines_1.concat)([path2.call(print, "tag"), path2.call(print, "quasi")]);
|
|
31589
|
+
// These types are unprintable because they serve as abstract
|
|
31590
|
+
// supertypes for other (printable) types.
|
|
31568
31591
|
case "Node":
|
|
31569
31592
|
case "Printable":
|
|
31570
31593
|
case "SourceLocation":
|
|
@@ -31577,22 +31600,32 @@ function requirePrinter() {
|
|
|
31577
31600
|
case "Specifier":
|
|
31578
31601
|
case "NamedSpecifier":
|
|
31579
31602
|
case "Comment":
|
|
31603
|
+
// Supertype of Block and Line
|
|
31580
31604
|
case "Flow":
|
|
31605
|
+
// Supertype of all Flow AST node types
|
|
31581
31606
|
case "FlowType":
|
|
31607
|
+
// Supertype of all Flow types
|
|
31582
31608
|
case "FlowPredicate":
|
|
31609
|
+
// Supertype of InferredPredicate and DeclaredPredicate
|
|
31583
31610
|
case "MemberTypeAnnotation":
|
|
31611
|
+
// Flow
|
|
31584
31612
|
case "Type":
|
|
31613
|
+
// Flow
|
|
31585
31614
|
case "TSHasOptionalTypeParameterInstantiation":
|
|
31586
31615
|
case "TSHasOptionalTypeParameters":
|
|
31587
31616
|
case "TSHasOptionalTypeAnnotation":
|
|
31588
31617
|
case "ChainElement":
|
|
31589
31618
|
throw new Error("unprintable type: " + JSON.stringify(n.type));
|
|
31590
31619
|
case "CommentBlock":
|
|
31620
|
+
// Babel block comment.
|
|
31591
31621
|
case "Block":
|
|
31592
31622
|
return (0, lines_1.concat)(["/*", (0, lines_1.fromString)(n.value, options2), "*/"]);
|
|
31593
31623
|
case "CommentLine":
|
|
31624
|
+
// Babel line comment.
|
|
31594
31625
|
case "Line":
|
|
31595
31626
|
return (0, lines_1.concat)(["//", (0, lines_1.fromString)(n.value, options2)]);
|
|
31627
|
+
// Type Annotations for Facebook Flow, typically stripped out or
|
|
31628
|
+
// transformed away before printing.
|
|
31596
31629
|
case "TypeAnnotation":
|
|
31597
31630
|
if (n.typeAnnotation) {
|
|
31598
31631
|
if (n.typeAnnotation.type !== "FunctionTypeAnnotation") {
|
|
@@ -31757,6 +31790,7 @@ function requirePrinter() {
|
|
|
31757
31790
|
]);
|
|
31758
31791
|
case "DeclareInterface":
|
|
31759
31792
|
parts.push("declare ");
|
|
31793
|
+
// Fall through to InterfaceDeclaration...
|
|
31760
31794
|
case "InterfaceDeclaration":
|
|
31761
31795
|
case "TSInterfaceDeclaration":
|
|
31762
31796
|
if (n.declare) {
|
|
@@ -31834,6 +31868,7 @@ function requirePrinter() {
|
|
|
31834
31868
|
return (0, lines_1.fromString)("string", options2);
|
|
31835
31869
|
case "DeclareTypeAlias":
|
|
31836
31870
|
parts.push("declare ");
|
|
31871
|
+
// Fall through to TypeAlias...
|
|
31837
31872
|
case "TypeAlias":
|
|
31838
31873
|
return (0, lines_1.concat)([
|
|
31839
31874
|
"type ",
|
|
@@ -31845,6 +31880,7 @@ function requirePrinter() {
|
|
|
31845
31880
|
]);
|
|
31846
31881
|
case "DeclareOpaqueType":
|
|
31847
31882
|
parts.push("declare ");
|
|
31883
|
+
// Fall through to OpaqueType...
|
|
31848
31884
|
case "OpaqueType":
|
|
31849
31885
|
parts.push("opaque type ", path2.call(print, "id"), path2.call(print, "typeParameters"));
|
|
31850
31886
|
if (n["supertype"]) {
|
|
@@ -31913,6 +31949,7 @@ function requirePrinter() {
|
|
|
31913
31949
|
return (0, lines_1.fromString)("symbol", options2);
|
|
31914
31950
|
case "BigIntTypeAnnotation":
|
|
31915
31951
|
return (0, lines_1.fromString)("bigint", options2);
|
|
31952
|
+
// Type Annotations for TypeScript (when using Babylon as parser)
|
|
31916
31953
|
case "TSType":
|
|
31917
31954
|
throw new Error("unprintable type: " + JSON.stringify(n.type));
|
|
31918
31955
|
case "TSNumberKeyword":
|
|
@@ -32252,19 +32289,33 @@ function requirePrinter() {
|
|
|
32252
32289
|
parts.push(path2.call(print, "expression"), path2.call(print, "typeParameters"));
|
|
32253
32290
|
return (0, lines_1.concat)(parts);
|
|
32254
32291
|
}
|
|
32292
|
+
// https://github.com/babel/babel/pull/10148
|
|
32255
32293
|
case "V8IntrinsicIdentifier":
|
|
32256
32294
|
return (0, lines_1.concat)(["%", path2.call(print, "name")]);
|
|
32295
|
+
// https://github.com/babel/babel/pull/13191
|
|
32257
32296
|
case "TopicReference":
|
|
32258
32297
|
return (0, lines_1.fromString)("#");
|
|
32298
|
+
// Unhandled types below. If encountered, nodes of these types should
|
|
32299
|
+
// be either left alone or desugared into AST types that are fully
|
|
32300
|
+
// supported by the pretty-printer.
|
|
32259
32301
|
case "ClassHeritage":
|
|
32302
|
+
// TODO
|
|
32260
32303
|
case "ComprehensionBlock":
|
|
32304
|
+
// TODO
|
|
32261
32305
|
case "ComprehensionExpression":
|
|
32306
|
+
// TODO
|
|
32262
32307
|
case "Glob":
|
|
32308
|
+
// TODO
|
|
32263
32309
|
case "GeneratorExpression":
|
|
32310
|
+
// TODO
|
|
32264
32311
|
case "LetStatement":
|
|
32312
|
+
// TODO
|
|
32265
32313
|
case "LetExpression":
|
|
32314
|
+
// TODO
|
|
32266
32315
|
case "GraphExpression":
|
|
32316
|
+
// TODO
|
|
32267
32317
|
case "GraphIndexExpression":
|
|
32318
|
+
// TODO
|
|
32268
32319
|
case "XMLDefaultDeclaration":
|
|
32269
32320
|
case "XMLAnyName":
|
|
32270
32321
|
case "XMLQualifiedIdentifier":
|
|
@@ -33518,6 +33569,7 @@ class EntityDecoder {
|
|
|
33518
33569
|
case EntityDecoderState.NamedEntity: {
|
|
33519
33570
|
return this.result !== 0 && (this.decodeMode !== DecodingMode.Attribute || this.result === this.treeIndex) ? this.emitNotTerminatedNamedEntity() : 0;
|
|
33520
33571
|
}
|
|
33572
|
+
// Otherwise, emit a numeric entity if we have one.
|
|
33521
33573
|
case EntityDecoderState.NumericDecimal: {
|
|
33522
33574
|
return this.emitNumericEntity(0, 2);
|
|
33523
33575
|
}
|
|
@@ -34940,6 +34992,7 @@ function renderNode(node2, options2) {
|
|
|
34940
34992
|
switch (node2.type) {
|
|
34941
34993
|
case Root$1:
|
|
34942
34994
|
return render(node2.children, options2);
|
|
34995
|
+
// @ts-expect-error We don't use `Doctype` yet
|
|
34943
34996
|
case Doctype:
|
|
34944
34997
|
case Directive:
|
|
34945
34998
|
return renderDirective(node2);
|
|
@@ -35974,9 +36027,10 @@ function requireNode() {
|
|
|
35974
36027
|
if (opts.index) {
|
|
35975
36028
|
pos = this.positionInside(opts.index);
|
|
35976
36029
|
} else if (opts.word) {
|
|
35977
|
-
let
|
|
35978
|
-
|
|
35979
|
-
sourceOffset(
|
|
36030
|
+
let inputString = "document" in this.source.input ? this.source.input.document : this.source.input.css;
|
|
36031
|
+
let stringRepresentation = inputString.slice(
|
|
36032
|
+
sourceOffset(inputString, this.source.start),
|
|
36033
|
+
sourceOffset(inputString, this.source.end)
|
|
35980
36034
|
);
|
|
35981
36035
|
let index2 = stringRepresentation.indexOf(opts.word);
|
|
35982
36036
|
if (index2 !== -1) pos = this.positionInside(index2);
|
|
@@ -35986,10 +36040,11 @@ function requireNode() {
|
|
|
35986
36040
|
positionInside(index2) {
|
|
35987
36041
|
let column = this.source.start.column;
|
|
35988
36042
|
let line = this.source.start.line;
|
|
35989
|
-
let
|
|
36043
|
+
let inputString = "document" in this.source.input ? this.source.input.document : this.source.input.css;
|
|
36044
|
+
let offset = sourceOffset(inputString, this.source.start);
|
|
35990
36045
|
let end = offset + index2;
|
|
35991
36046
|
for (let i = offset; i < end; i++) {
|
|
35992
|
-
if (
|
|
36047
|
+
if (inputString[i] === "\n") {
|
|
35993
36048
|
column = 1;
|
|
35994
36049
|
line += 1;
|
|
35995
36050
|
} else {
|
|
@@ -36016,9 +36071,10 @@ function requireNode() {
|
|
|
36016
36071
|
line: start.line
|
|
36017
36072
|
};
|
|
36018
36073
|
if (opts.word) {
|
|
36019
|
-
let
|
|
36020
|
-
|
|
36021
|
-
sourceOffset(
|
|
36074
|
+
let inputString = "document" in this.source.input ? this.source.input.document : this.source.input.css;
|
|
36075
|
+
let stringRepresentation = inputString.slice(
|
|
36076
|
+
sourceOffset(inputString, this.source.start),
|
|
36077
|
+
sourceOffset(inputString, this.source.end)
|
|
36022
36078
|
);
|
|
36023
36079
|
let index2 = stringRepresentation.indexOf(opts.word);
|
|
36024
36080
|
if (index2 !== -1) {
|
|
@@ -38724,6 +38780,8 @@ function requireInput() {
|
|
|
38724
38780
|
} else {
|
|
38725
38781
|
this.hasBOM = false;
|
|
38726
38782
|
}
|
|
38783
|
+
this.document = this.css;
|
|
38784
|
+
if (opts.document) this.document = opts.document.toString();
|
|
38727
38785
|
if (opts.from) {
|
|
38728
38786
|
if (!pathAvailable || /^\w+:\/\//.test(opts.from) || isAbsolute(opts.from)) {
|
|
38729
38787
|
this.file = opts.from;
|
|
@@ -40671,7 +40729,7 @@ function requireProcessor() {
|
|
|
40671
40729
|
let Root2 = requireRoot();
|
|
40672
40730
|
class Processor {
|
|
40673
40731
|
constructor(plugins = []) {
|
|
40674
|
-
this.version = "8.
|
|
40732
|
+
this.version = "8.5.1";
|
|
40675
40733
|
this.plugins = this.normalize(plugins);
|
|
40676
40734
|
}
|
|
40677
40735
|
normalize(plugins) {
|
|
@@ -42577,6 +42635,7 @@ class Mappings {
|
|
|
42577
42635
|
this.raw[this.generatedCodeLine] = this.rawSegments = [];
|
|
42578
42636
|
this.generatedCodeColumn = 0;
|
|
42579
42637
|
first = true;
|
|
42638
|
+
charInHiresBoundary = false;
|
|
42580
42639
|
} else {
|
|
42581
42640
|
if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
|
|
42582
42641
|
const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
|
|
@@ -42638,7 +42697,8 @@ class MagicString {
|
|
|
42638
42697
|
sourcemapLocations: { writable: true, value: new BitSet() },
|
|
42639
42698
|
storedNames: { writable: true, value: {} },
|
|
42640
42699
|
indentStr: { writable: true, value: void 0 },
|
|
42641
|
-
ignoreList: { writable: true, value: options.ignoreList }
|
|
42700
|
+
ignoreList: { writable: true, value: options.ignoreList },
|
|
42701
|
+
offset: { writable: true, value: options.offset || 0 }
|
|
42642
42702
|
});
|
|
42643
42703
|
this.byStart[0] = chunk;
|
|
42644
42704
|
this.byEnd[string.length] = chunk;
|
|
@@ -42652,6 +42712,7 @@ class MagicString {
|
|
|
42652
42712
|
return this;
|
|
42653
42713
|
}
|
|
42654
42714
|
appendLeft(index, content) {
|
|
42715
|
+
index = index + this.offset;
|
|
42655
42716
|
if (typeof content !== "string") throw new TypeError("inserted content must be a string");
|
|
42656
42717
|
this._split(index);
|
|
42657
42718
|
const chunk = this.byEnd[index];
|
|
@@ -42663,6 +42724,7 @@ class MagicString {
|
|
|
42663
42724
|
return this;
|
|
42664
42725
|
}
|
|
42665
42726
|
appendRight(index, content) {
|
|
42727
|
+
index = index + this.offset;
|
|
42666
42728
|
if (typeof content !== "string") throw new TypeError("inserted content must be a string");
|
|
42667
42729
|
this._split(index);
|
|
42668
42730
|
const chunk = this.byStart[index];
|
|
@@ -42674,7 +42736,7 @@ class MagicString {
|
|
|
42674
42736
|
return this;
|
|
42675
42737
|
}
|
|
42676
42738
|
clone() {
|
|
42677
|
-
const cloned = new MagicString(this.original, { filename: this.filename });
|
|
42739
|
+
const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });
|
|
42678
42740
|
let originalChunk = this.firstChunk;
|
|
42679
42741
|
let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
|
|
42680
42742
|
while (originalChunk) {
|
|
@@ -42839,6 +42901,9 @@ class MagicString {
|
|
|
42839
42901
|
return this.prependRight(index, content);
|
|
42840
42902
|
}
|
|
42841
42903
|
move(start, end, index) {
|
|
42904
|
+
start = start + this.offset;
|
|
42905
|
+
end = end + this.offset;
|
|
42906
|
+
index = index + this.offset;
|
|
42842
42907
|
if (index >= start && index <= end) throw new Error("Cannot move a selection inside itself");
|
|
42843
42908
|
this._split(start);
|
|
42844
42909
|
this._split(end);
|
|
@@ -42870,6 +42935,8 @@ class MagicString {
|
|
|
42870
42935
|
return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
|
|
42871
42936
|
}
|
|
42872
42937
|
update(start, end, content, options) {
|
|
42938
|
+
start = start + this.offset;
|
|
42939
|
+
end = end + this.offset;
|
|
42873
42940
|
if (typeof content !== "string") throw new TypeError("replacement content must be a string");
|
|
42874
42941
|
if (this.original.length !== 0) {
|
|
42875
42942
|
while (start < 0) start += this.original.length;
|
|
@@ -42926,6 +42993,7 @@ class MagicString {
|
|
|
42926
42993
|
return this;
|
|
42927
42994
|
}
|
|
42928
42995
|
prependLeft(index, content) {
|
|
42996
|
+
index = index + this.offset;
|
|
42929
42997
|
if (typeof content !== "string") throw new TypeError("inserted content must be a string");
|
|
42930
42998
|
this._split(index);
|
|
42931
42999
|
const chunk = this.byEnd[index];
|
|
@@ -42937,6 +43005,7 @@ class MagicString {
|
|
|
42937
43005
|
return this;
|
|
42938
43006
|
}
|
|
42939
43007
|
prependRight(index, content) {
|
|
43008
|
+
index = index + this.offset;
|
|
42940
43009
|
if (typeof content !== "string") throw new TypeError("inserted content must be a string");
|
|
42941
43010
|
this._split(index);
|
|
42942
43011
|
const chunk = this.byStart[index];
|
|
@@ -42948,6 +43017,8 @@ class MagicString {
|
|
|
42948
43017
|
return this;
|
|
42949
43018
|
}
|
|
42950
43019
|
remove(start, end) {
|
|
43020
|
+
start = start + this.offset;
|
|
43021
|
+
end = end + this.offset;
|
|
42951
43022
|
if (this.original.length !== 0) {
|
|
42952
43023
|
while (start < 0) start += this.original.length;
|
|
42953
43024
|
while (end < 0) end += this.original.length;
|
|
@@ -42967,6 +43038,8 @@ class MagicString {
|
|
|
42967
43038
|
return this;
|
|
42968
43039
|
}
|
|
42969
43040
|
reset(start, end) {
|
|
43041
|
+
start = start + this.offset;
|
|
43042
|
+
end = end + this.offset;
|
|
42970
43043
|
if (this.original.length !== 0) {
|
|
42971
43044
|
while (start < 0) start += this.original.length;
|
|
42972
43045
|
while (end < 0) end += this.original.length;
|
|
@@ -43020,7 +43093,9 @@ class MagicString {
|
|
|
43020
43093
|
if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
|
|
43021
43094
|
return this.intro + lineStr;
|
|
43022
43095
|
}
|
|
43023
|
-
slice(start = 0, end = this.original.length) {
|
|
43096
|
+
slice(start = 0, end = this.original.length - this.offset) {
|
|
43097
|
+
start = start + this.offset;
|
|
43098
|
+
end = end + this.offset;
|
|
43024
43099
|
if (this.original.length !== 0) {
|
|
43025
43100
|
while (start < 0) start += this.original.length;
|
|
43026
43101
|
while (end < 0) end += this.original.length;
|
|
@@ -43197,11 +43272,7 @@ class MagicString {
|
|
|
43197
43272
|
if (match.index != null) {
|
|
43198
43273
|
const replacement2 = getReplacement(match, this.original);
|
|
43199
43274
|
if (replacement2 !== match[0]) {
|
|
43200
|
-
this.overwrite(
|
|
43201
|
-
match.index,
|
|
43202
|
-
match.index + match[0].length,
|
|
43203
|
-
replacement2
|
|
43204
|
-
);
|
|
43275
|
+
this.overwrite(match.index, match.index + match[0].length, replacement2);
|
|
43205
43276
|
}
|
|
43206
43277
|
}
|
|
43207
43278
|
});
|
|
@@ -43210,11 +43281,7 @@ class MagicString {
|
|
|
43210
43281
|
if (match && match.index != null) {
|
|
43211
43282
|
const replacement2 = getReplacement(match, this.original);
|
|
43212
43283
|
if (replacement2 !== match[0]) {
|
|
43213
|
-
this.overwrite(
|
|
43214
|
-
match.index,
|
|
43215
|
-
match.index + match[0].length,
|
|
43216
|
-
replacement2
|
|
43217
|
-
);
|
|
43284
|
+
this.overwrite(match.index, match.index + match[0].length, replacement2);
|
|
43218
43285
|
}
|
|
43219
43286
|
}
|
|
43220
43287
|
}
|
|
@@ -43239,8 +43306,7 @@ class MagicString {
|
|
|
43239
43306
|
const stringLength = string.length;
|
|
43240
43307
|
for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {
|
|
43241
43308
|
const previous = original.slice(index, index + stringLength);
|
|
43242
|
-
if (previous !== replacement)
|
|
43243
|
-
this.overwrite(index, index + stringLength, replacement);
|
|
43309
|
+
if (previous !== replacement) this.overwrite(index, index + stringLength, replacement);
|
|
43244
43310
|
}
|
|
43245
43311
|
return this;
|
|
43246
43312
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "src/routes/sverdle/+page.svelte",
|
|
40
|
-
"contents": "<script>\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\t/**\n\t * @typedef {Object} Props\n\t * @property {import('./$types').PageData} data\n\t * @property {import('./$types').ActionData} form\n\t */\n\n\t/**\n\t * @type {Props}\n\t */\n\tlet { data, form = $bindable() } = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t * @type {Record<string, 'exact' | 'close' | 'missing'>}\n\t\t */\n\t\tlet classnames = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t * @type {Record<string, string>}\n\t\t */\n\t\tlet description = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t * @param {MouseEvent} event\n\t */\n\tfunction update(event) {\n\t\tevent.preventDefault();\n\t\tconst key = /** @type {HTMLButtonElement} */ (event.target).getAttribute('data-key');\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t * @param {KeyboardEvent} event\n\t */\n\tfunction keydown(event) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
40
|
+
"contents": "<script>\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\t/**\n\t * @typedef {Object} Props\n\t * @property {import('./$types').PageData} data\n\t * @property {import('./$types').ActionData} form\n\t */\n\n\t/**\n\t * @type {Props}\n\t */\n\tlet { data, form = $bindable() } = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t * @type {Record<string, 'exact' | 'close' | 'missing'>}\n\t\t */\n\t\tlet classnames = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t * @type {Record<string, string>}\n\t\t */\n\t\tlet description = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t * @param {MouseEvent} event\n\t */\n\tfunction update(event) {\n\t\tevent.preventDefault();\n\t\tconst key = /** @type {HTMLButtonElement} */ (event.target).getAttribute('data-key');\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t * @param {KeyboardEvent} event\n\t */\n\tfunction keydown(event) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true, bubbles: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"name": "src/routes/sverdle/game.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"name": "src/routes/sverdle/+page.svelte",
|
|
36
|
-
"contents": "<script>\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\tlet { data, form = $bindable() } = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t */\n\t\tlet classnames = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t */\n\t\tlet description = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t */\n\tfunction update(event) {\n\t\tevent.preventDefault();\n\t\tconst key = (event.target).getAttribute('data-key');\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t */\n\tfunction keydown(event) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
36
|
+
"contents": "<script>\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\tlet { data, form = $bindable() } = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t */\n\t\tlet classnames = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t */\n\t\tlet description = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t */\n\tfunction update(event) {\n\t\tevent.preventDefault();\n\t\tconst key = (event.target).getAttribute('data-key');\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t */\n\tfunction keydown(event) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true, bubbles: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "src/routes/sverdle/game.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "src/routes/sverdle/+page.svelte",
|
|
40
|
-
"contents": "<script lang=\"ts\">\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\timport type { ActionData, PageData } from './$types';\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\tinterface Props {\n\t\tdata: PageData;\n\t\tform: ActionData;\n\t}\n\tlet { data, form = $bindable() }: Props = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t */\n\t\tlet classnames: Record<string, 'exact' | 'close' | 'missing'> = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t */\n\t\tlet description: Record<string, string> = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t */\n\tfunction update(event: MouseEvent) {\n\t\tevent.preventDefault();\n\t\tconst key = (event.target as HTMLButtonElement).getAttribute(\n\t\t\t'data-key'\n\t\t);\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t */\n\tfunction keydown(event: KeyboardEvent) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
40
|
+
"contents": "<script lang=\"ts\">\n\timport { enhance } from '$app/forms';\n\timport { confetti } from '@neoconfetti/svelte';\n\timport type { ActionData, PageData } from './$types';\n\timport { MediaQuery } from 'svelte/reactivity';\n\n\tinterface Props {\n\t\tdata: PageData;\n\t\tform: ActionData;\n\t}\n\tlet { data, form = $bindable() }: Props = $props();\n\n\t/** Whether the user prefers reduced motion */\n\tconst reducedMotion = new MediaQuery('(prefers-reduced-motion: reduce)');\n\n\t/** Whether or not the user has won */\n\tlet won = $derived(data.answers.at(-1) === 'xxxxx');\n\n\t/** The index of the current guess */\n\tlet i = $derived(won ? -1 : data.answers.length);\n\n\t/** The current guess */\n\t// svelte-ignore state_referenced_locally\n\tlet currentGuess = $state(data.guesses[i] || '');\n\n\t$effect(() => {\n\t\tcurrentGuess = data.guesses[i] || '';\n\t});\n\n\t/** Whether the current guess can be submitted */\n\tlet submittable = $derived(currentGuess.length === 5);\n\n\tconst { classnames, description } = $derived.by(() => {\n\t\t/**\n\t\t * A map of classnames for all letters that have been guessed,\n\t\t * used for styling the keyboard\n\t\t */\n\t\tlet classnames: Record<string, 'exact' | 'close' | 'missing'> = {};\n\t\t/**\n\t\t * A map of descriptions for all letters that have been guessed,\n\t\t * used for adding text for assistive technology (e.g. screen readers)\n\t\t */\n\t\tlet description: Record<string, string> = {};\n\t\tdata.answers.forEach((answer, i) => {\n\t\t\tconst guess = data.guesses[i];\n\t\t\tfor (let i = 0; i < 5; i += 1) {\n\t\t\t\tconst letter = guess[i];\n\t\t\t\tif (answer[i] === 'x') {\n\t\t\t\t\tclassnames[letter] = 'exact';\n\t\t\t\t\tdescription[letter] = 'correct';\n\t\t\t\t} else if (!classnames[letter]) {\n\t\t\t\t\tclassnames[letter] = answer[i] === 'c' ? 'close' : 'missing';\n\t\t\t\t\tdescription[letter] = answer[i] === 'c' ? 'present' : 'absent';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { classnames, description };\n\t});\n\n\t/**\n\t * Modify the game state without making a trip to the server,\n\t * if client-side JavaScript is enabled\n\t */\n\tfunction update(event: MouseEvent) {\n\t\tevent.preventDefault();\n\t\tconst key = (event.target as HTMLButtonElement).getAttribute(\n\t\t\t'data-key'\n\t\t);\n\n\t\tif (key === 'backspace') {\n\t\t\tcurrentGuess = currentGuess.slice(0, -1);\n\t\t\tif (form?.badGuess) form.badGuess = false;\n\t\t} else if (currentGuess.length < 5) {\n\t\t\tcurrentGuess += key;\n\t\t}\n\t}\n\n\t/**\n\t * Trigger form logic in response to a keydown event, so that\n\t * desktop users can use the keyboard to play the game\n\t */\n\tfunction keydown(event: KeyboardEvent) {\n\t\tif (event.metaKey) return;\n\n\t\tif (event.key === 'Enter' && !submittable) return;\n\n\t\tdocument\n\t\t\t.querySelector(`[data-key=\"${event.key}\" i]`)\n\t\t\t?.dispatchEvent(new MouseEvent('click', { cancelable: true, bubbles: true }));\n\t}\n</script>\n\n<svelte:window onkeydown={keydown} />\n\n<svelte:head>\n\t<title>Sverdle</title>\n\t<meta name=\"description\" content=\"A Wordle clone written in SvelteKit\" />\n</svelte:head>\n\n<h1 class=\"visually-hidden\">Sverdle</h1>\n\n<form\n\tmethod=\"post\"\n\taction=\"?/enter\"\n\tuse:enhance={() => {\n\t\t// prevent default callback from resetting the form\n\t\treturn ({ update }) => {\n\t\t\tupdate({ reset: false });\n\t\t};\n\t}}\n>\n\t<a class=\"how-to-play\" href=\"/sverdle/how-to-play\">How to play</a>\n\n\t<div class=\"grid\" class:playing={!won} class:bad-guess={form?.badGuess}>\n\t\t{#each Array.from(Array(6).keys()) as row (row)}\n\t\t\t{@const current = row === i}\n\t\t\t<h2 class=\"visually-hidden\">Row {row + 1}</h2>\n\t\t\t<div class=\"row\" class:current>\n\t\t\t\t{#each Array.from(Array(5).keys()) as column (column)}\n\t\t\t\t\t{@const guess = current ? currentGuess : data.guesses[row]}\n\t\t\t\t\t{@const answer = data.answers[row]?.[column]}\n\t\t\t\t\t{@const value = guess?.[column] ?? ''}\n\t\t\t\t\t{@const selected = current && column === guess.length}\n\t\t\t\t\t{@const exact = answer === 'x'}\n\t\t\t\t\t{@const close = answer === 'c'}\n\t\t\t\t\t{@const missing = answer === '_'}\n\t\t\t\t\t<div class=\"letter\" class:exact class:close class:missing class:selected>\n\t\t\t\t\t\t{value}\n\t\t\t\t\t\t<span class=\"visually-hidden\">\n\t\t\t\t\t\t\t{#if exact}\n\t\t\t\t\t\t\t\t(correct)\n\t\t\t\t\t\t\t{:else if close}\n\t\t\t\t\t\t\t\t(present)\n\t\t\t\t\t\t\t{:else if missing}\n\t\t\t\t\t\t\t\t(absent)\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\tempty\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<input name=\"guess\" disabled={!current} type=\"hidden\" {value} />\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/each}\n\t</div>\n\n\t<div class=\"controls\">\n\t\t{#if won || data.answers.length >= 6}\n\t\t\t{#if !won && data.answer}\n\t\t\t\t<p>the answer was \"{data.answer}\"</p>\n\t\t\t{/if}\n\t\t\t<button data-key=\"enter\" class=\"restart selected\" formaction=\"?/restart\">\n\t\t\t\t{won ? 'you won :)' : `game over :(`} play again?\n\t\t\t</button>\n\t\t{:else}\n\t\t\t<div class=\"keyboard\">\n\t\t\t\t<button data-key=\"enter\" class:selected={submittable} disabled={!submittable}>enter</button>\n\n\t\t\t\t<button\n\t\t\t\t\tonclick={update}\n\t\t\t\t\tdata-key=\"backspace\"\n\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\tname=\"key\"\n\t\t\t\t\tvalue=\"backspace\"\n\t\t\t\t>\n\t\t\t\t\tback\n\t\t\t\t</button>\n\n\t\t\t\t{#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row}\n\t\t\t\t\t<div class=\"row\">\n\t\t\t\t\t\t{#each row as letter}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonclick={update}\n\t\t\t\t\t\t\t\tdata-key={letter}\n\t\t\t\t\t\t\t\tclass={classnames[letter]}\n\t\t\t\t\t\t\t\tdisabled={submittable}\n\t\t\t\t\t\t\t\tformaction=\"?/update\"\n\t\t\t\t\t\t\t\tname=\"key\"\n\t\t\t\t\t\t\t\tvalue={letter}\n\t\t\t\t\t\t\t\taria-label=\"{letter} {description[letter] || ''}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t</div>\n\t\t\t\t{/each}\n\t\t\t</div>\n\t\t{/if}\n\t</div>\n</form>\n\n{#if won}\n\t<div\n\t\tstyle=\"position: absolute; left: 50%; top: 30%\"\n\t\tuse:confetti={{\n\t\t\tparticleCount: reducedMotion.current ? 0 : undefined,\n\t\t\tforce: 0.7,\n\t\t\tstageWidth: window.innerWidth,\n\t\t\tstageHeight: window.innerHeight,\n\t\t\tcolors: ['#ff3e00', '#40b3ff', '#676778']\n\t\t}}\n\t></div>\n{/if}\n\n<style>\n\tform {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tgap: 1rem;\n\t\tflex: 1;\n\t}\n\n\t.how-to-play {\n\t\tcolor: var(--color-text);\n\t}\n\n\t.how-to-play::before {\n\t\tcontent: 'i';\n\t\tdisplay: inline-block;\n\t\tfont-size: 0.8em;\n\t\tfont-weight: 900;\n\t\twidth: 1em;\n\t\theight: 1em;\n\t\tpadding: 0.2em;\n\t\tline-height: 1;\n\t\tborder: 1.5px solid var(--color-text);\n\t\tborder-radius: 50%;\n\t\ttext-align: center;\n\t\tmargin: 0 0.5em 0 0;\n\t\tposition: relative;\n\t\ttop: -0.05em;\n\t}\n\n\t.grid {\n\t\t--width: min(100vw, 40vh, 380px);\n\t\tmax-width: var(--width);\n\t\talign-self: center;\n\t\tjustify-self: center;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tjustify-content: flex-start;\n\t}\n\n\t.grid .row {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(5, 1fr);\n\t\tgrid-gap: 0.2rem;\n\t\tmargin: 0 0 0.2rem 0;\n\t}\n\n\t@media (prefers-reduced-motion: no-preference) {\n\t\t.grid.bad-guess .row.current {\n\t\t\tanimation: wiggle 0.5s;\n\t\t}\n\t}\n\n\t.grid.playing .row.current {\n\t\tfilter: drop-shadow(3px 3px 10px var(--color-bg-0));\n\t}\n\n\t.letter {\n\t\taspect-ratio: 1;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\ttext-align: center;\n\t\tbox-sizing: border-box;\n\t\ttext-transform: lowercase;\n\t\tborder: none;\n\t\tfont-size: calc(0.08 * var(--width));\n\t\tborder-radius: 2px;\n\t\tbackground: white;\n\t\tmargin: 0;\n\t\tcolor: rgba(0, 0, 0, 0.7);\n\t}\n\n\t.letter.missing {\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tcolor: rgba(0, 0, 0, 0.5);\n\t}\n\n\t.letter.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.letter.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.selected {\n\t\toutline: 2px solid var(--color-theme-1);\n\t}\n\n\t.controls {\n\t\ttext-align: center;\n\t\tjustify-content: center;\n\t\theight: min(18vh, 10rem);\n\t}\n\n\t.keyboard {\n\t\t--gap: 0.2rem;\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: var(--gap);\n\t\theight: 100%;\n\t}\n\n\t.keyboard .row {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tgap: 0.2rem;\n\t\tflex: 1;\n\t}\n\n\t.keyboard button,\n\t.keyboard button:disabled {\n\t\t--size: min(8vw, 4vh, 40px);\n\t\tbackground-color: white;\n\t\tcolor: black;\n\t\twidth: var(--size);\n\t\tborder: none;\n\t\tborder-radius: 2px;\n\t\tfont-size: calc(var(--size) * 0.5);\n\t\tmargin: 0;\n\t}\n\n\t.keyboard button.exact {\n\t\tbackground: var(--color-theme-2);\n\t\tcolor: white;\n\t}\n\n\t.keyboard button.missing {\n\t\topacity: 0.5;\n\t}\n\n\t.keyboard button.close {\n\t\tborder: 2px solid var(--color-theme-2);\n\t}\n\n\t.keyboard button:focus {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t.keyboard button[data-key='enter'],\n\t.keyboard button[data-key='backspace'] {\n\t\tposition: absolute;\n\t\tbottom: 0;\n\t\twidth: calc(1.5 * var(--size));\n\t\theight: calc(1 / 3 * (100% - 2 * var(--gap)));\n\t\ttext-transform: uppercase;\n\t\tfont-size: calc(0.3 * var(--size));\n\t\tpadding-top: calc(0.15 * var(--size));\n\t}\n\n\t.keyboard button[data-key='enter'] {\n\t\tright: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='backspace'] {\n\t\tleft: calc(50% + 3.5 * var(--size) + 0.8rem);\n\t}\n\n\t.keyboard button[data-key='enter']:disabled {\n\t\topacity: 0.5;\n\t}\n\n\t.restart {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t\tbackground: rgba(255, 255, 255, 0.5);\n\t\tborder-radius: 2px;\n\t\tborder: none;\n\t}\n\n\t.restart:focus,\n\t.restart:hover {\n\t\tbackground: var(--color-theme-1);\n\t\tcolor: white;\n\t\toutline: none;\n\t}\n\n\t@keyframes wiggle {\n\t\t0% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t\t10% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t30% {\n\t\t\ttransform: translateX(4px);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(-6px);\n\t\t}\n\t\t70% {\n\t\t\ttransform: translateX(+4px);\n\t\t}\n\t\t90% {\n\t\t\ttransform: translateX(-2px);\n\t\t}\n\t\t100% {\n\t\t\ttransform: translateX(0);\n\t\t}\n\t}\n</style>\n"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"name": "src/routes/sverdle/game.ts",
|
package/dist/testing.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import process$1 from 'node:process';
|
|
4
|
-
import { a as commonjsGlobal, g as getDefaultExportFromCjs, c as create, b as be } from './main-
|
|
4
|
+
import { a as commonjsGlobal, g as getDefaultExportFromCjs, c as create, b as be } from './main-CCykm_Ik.js';
|
|
5
5
|
import require$$1 from 'fs';
|
|
6
6
|
import require$$1$1 from 'path';
|
|
7
7
|
import require$$5 from 'events';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sv",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI for creating and updating SvelteKit projects",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"tar-fs": "^3.0.6",
|
|
38
38
|
"tinyexec": "^0.3.1",
|
|
39
39
|
"valibot": "^0.41.0",
|
|
40
|
+
"@sveltejs/cli-core": "0.0.0",
|
|
40
41
|
"@sveltejs/addons": "0.0.0",
|
|
41
42
|
"@sveltejs/clack-prompts": "0.9.1",
|
|
42
|
-
"@sveltejs/create": "0.0.0"
|
|
43
|
-
"@sveltejs/cli-core": "0.0.0"
|
|
43
|
+
"@sveltejs/create": "0.0.0"
|
|
44
44
|
},
|
|
45
45
|
"keywords": [
|
|
46
46
|
"create",
|
|
@@ -632,12 +632,12 @@ var R = class {
|
|
|
632
632
|
if (!e)
|
|
633
633
|
throw new Error("No process was started");
|
|
634
634
|
let n = "", r = "";
|
|
635
|
-
if (this._streamErr)
|
|
636
|
-
for await (let o of this._streamErr)
|
|
637
|
-
n += o.toString();
|
|
638
635
|
if (this._streamOut)
|
|
639
636
|
for await (let o of this._streamOut)
|
|
640
637
|
r += o.toString();
|
|
638
|
+
if (this._streamErr)
|
|
639
|
+
for await (let o of this._streamErr)
|
|
640
|
+
n += o.toString();
|
|
641
641
|
if (await this._processClosed, this._options?.stdin && await this._options.stdin, e.removeAllListeners(), this._thrownError)
|
|
642
642
|
throw this._thrownError;
|
|
643
643
|
let s = {
|