pxt-core 9.2.9 → 9.2.11
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/built/cli.js +56 -45
- package/built/crowdin.d.ts +2 -1
- package/built/crowdin.js +218 -213
- package/built/crowdinApi.d.ts +10 -0
- package/built/crowdinApi.js +374 -0
- package/built/pxt.js +97 -298
- package/built/pxtblockly.js +8 -6
- package/built/pxtblocks.d.ts +4 -0
- package/built/pxtblocks.js +8 -6
- package/built/pxtlib.d.ts +3 -37
- package/built/pxtlib.js +41 -253
- package/built/target.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxtasseteditor.js +1 -1
- package/built/web/pxtblockly.js +1 -1
- package/built/web/pxtblocks.js +1 -1
- package/built/web/pxtembed.js +2 -2
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/localtypings/pxtarget.d.ts +3 -0
- package/package.json +5 -1
package/built/pxt.js
CHANGED
|
@@ -105304,251 +105304,11 @@ var pxt;
|
|
|
105304
105304
|
(function (crowdin) {
|
|
105305
105305
|
crowdin.KEY_VARIABLE = "CROWDIN_KEY";
|
|
105306
105306
|
crowdin.testMode = false;
|
|
105307
|
-
crowdin.TEST_KEY = "!!!testmode!!!";
|
|
105308
105307
|
function setTestMode() {
|
|
105309
105308
|
pxt.crowdin.testMode = true;
|
|
105310
105309
|
pxt.log(`CROWDIN TEST MODE - files will NOT be uploaded`);
|
|
105311
105310
|
}
|
|
105312
105311
|
crowdin.setTestMode = setTestMode;
|
|
105313
|
-
function multipartPostAsync(key, uri, data = {}, filename = null, filecontents = null) {
|
|
105314
|
-
if (crowdin.testMode || key == crowdin.TEST_KEY) {
|
|
105315
|
-
const resp = {
|
|
105316
|
-
success: true
|
|
105317
|
-
};
|
|
105318
|
-
return Promise.resolve({ statusCode: 200, headers: {}, text: JSON.stringify(resp), json: resp });
|
|
105319
|
-
}
|
|
105320
|
-
return pxt.Util.multipartPostAsync(uri, data, filename, filecontents);
|
|
105321
|
-
}
|
|
105322
|
-
function apiUri(branch, prj, key, cmd, args) {
|
|
105323
|
-
pxt.Util.assert(!!prj && !!key && !!cmd);
|
|
105324
|
-
const apiRoot = "https://api.crowdin.com/api/project/" + prj + "/";
|
|
105325
|
-
args = args || {};
|
|
105326
|
-
if (crowdin.testMode)
|
|
105327
|
-
delete args["key"]; // ensure no key is passed in test mode
|
|
105328
|
-
else
|
|
105329
|
-
args["key"] = key;
|
|
105330
|
-
if (branch)
|
|
105331
|
-
args["branch"] = branch;
|
|
105332
|
-
return apiRoot + cmd + "?" + Object.keys(args).map(k => `${k}=${encodeURIComponent(args[k])}`).join("&");
|
|
105333
|
-
}
|
|
105334
|
-
function downloadTranslationsAsync(branch, prj, key, filename, options = {}) {
|
|
105335
|
-
const q = { json: "true" };
|
|
105336
|
-
const infoUri = apiUri(branch, prj, key, "info", q);
|
|
105337
|
-
const r = {};
|
|
105338
|
-
filename = normalizeFileName(filename);
|
|
105339
|
-
return pxt.Util.httpGetTextAsync(infoUri).then(respText => {
|
|
105340
|
-
const info = JSON.parse(respText);
|
|
105341
|
-
if (!info)
|
|
105342
|
-
throw new Error("info failed");
|
|
105343
|
-
let todo = info.languages.filter(l => l.code != "en");
|
|
105344
|
-
if (pxt.appTarget && pxt.appTarget.appTheme && pxt.appTarget.appTheme.availableLocales)
|
|
105345
|
-
todo = todo.filter(l => pxt.appTarget.appTheme.availableLocales.indexOf(l.code) > -1);
|
|
105346
|
-
pxt.log('languages: ' + todo.map(l => l.code).join(', '));
|
|
105347
|
-
const nextFile = () => {
|
|
105348
|
-
const item = todo.pop();
|
|
105349
|
-
if (!item)
|
|
105350
|
-
return Promise.resolve();
|
|
105351
|
-
const exportFileUri = apiUri(branch, prj, key, "export-file", {
|
|
105352
|
-
file: filename,
|
|
105353
|
-
language: item.code,
|
|
105354
|
-
export_translated_only: options.translatedOnly ? "1" : "0",
|
|
105355
|
-
export_approved_only: options.validatedOnly ? "1" : "0"
|
|
105356
|
-
});
|
|
105357
|
-
pxt.log(`downloading ${item.name} - ${item.code} (${todo.length} more)`);
|
|
105358
|
-
return pxt.Util.httpGetTextAsync(exportFileUri).then((transationsText) => {
|
|
105359
|
-
try {
|
|
105360
|
-
const translations = JSON.parse(transationsText);
|
|
105361
|
-
if (translations)
|
|
105362
|
-
r[item.code] = translations;
|
|
105363
|
-
}
|
|
105364
|
-
catch (e) {
|
|
105365
|
-
pxt.log(exportFileUri + ' ' + e);
|
|
105366
|
-
}
|
|
105367
|
-
return nextFile();
|
|
105368
|
-
}).then(() => pxt.Util.delay(1000)); // throttling otherwise crowdin fails
|
|
105369
|
-
};
|
|
105370
|
-
return nextFile();
|
|
105371
|
-
}).then(() => r);
|
|
105372
|
-
}
|
|
105373
|
-
crowdin.downloadTranslationsAsync = downloadTranslationsAsync;
|
|
105374
|
-
function mkIncr(filename) {
|
|
105375
|
-
let cnt = 0;
|
|
105376
|
-
return function incr() {
|
|
105377
|
-
if (cnt++ > 10) {
|
|
105378
|
-
throw new Error("Too many API calls for " + filename);
|
|
105379
|
-
}
|
|
105380
|
-
};
|
|
105381
|
-
}
|
|
105382
|
-
function createDirectoryAsync(branch, prj, key, name, incr) {
|
|
105383
|
-
name = normalizeFileName(name);
|
|
105384
|
-
pxt.debug(`create directory ${branch || ""}/${name}`);
|
|
105385
|
-
if (!incr)
|
|
105386
|
-
incr = mkIncr(name);
|
|
105387
|
-
return multipartPostAsync(key, apiUri(branch, prj, key, "add-directory"), { json: "true", name: name })
|
|
105388
|
-
.then(resp => {
|
|
105389
|
-
pxt.debug(`crowdin resp: ${resp.statusCode}`);
|
|
105390
|
-
// 400 returned by folder already exists
|
|
105391
|
-
if (resp.statusCode == 200 || resp.statusCode == 400)
|
|
105392
|
-
return Promise.resolve();
|
|
105393
|
-
if (resp.statusCode == 500 && resp.text) {
|
|
105394
|
-
const json = JSON.parse(resp.text);
|
|
105395
|
-
if (json.error.code === 50) {
|
|
105396
|
-
pxt.log('directory already exists');
|
|
105397
|
-
return Promise.resolve();
|
|
105398
|
-
}
|
|
105399
|
-
}
|
|
105400
|
-
const data = resp.json || JSON.parse(resp.text) || { error: {} };
|
|
105401
|
-
if (resp.statusCode == 404 && data.error.code == 17) {
|
|
105402
|
-
pxt.log(`parent directory missing for ${name}`);
|
|
105403
|
-
const par = name.replace(/\/[^\/]+$/, "");
|
|
105404
|
-
if (par != name) {
|
|
105405
|
-
return createDirectoryAsync(branch, prj, key, par, incr)
|
|
105406
|
-
.then(() => createDirectoryAsync(branch, prj, key, name, incr)); // retry
|
|
105407
|
-
}
|
|
105408
|
-
}
|
|
105409
|
-
throw new Error(`cannot create directory ${branch || ""}/${name}: ${resp.statusCode} ${JSON.stringify(data)}`);
|
|
105410
|
-
});
|
|
105411
|
-
}
|
|
105412
|
-
crowdin.createDirectoryAsync = createDirectoryAsync;
|
|
105413
|
-
function normalizeFileName(filename) {
|
|
105414
|
-
return filename.replace(/\\/g, '/');
|
|
105415
|
-
}
|
|
105416
|
-
function uploadTranslationAsync(branch, prj, key, filename, data) {
|
|
105417
|
-
pxt.Util.assert(!!prj);
|
|
105418
|
-
pxt.Util.assert(!!key);
|
|
105419
|
-
filename = normalizeFileName(filename);
|
|
105420
|
-
const incr = mkIncr(filename);
|
|
105421
|
-
function startAsync() {
|
|
105422
|
-
return uploadAsync("update-file", { update_option: "update_as_unapproved" });
|
|
105423
|
-
}
|
|
105424
|
-
function uploadAsync(op, opts) {
|
|
105425
|
-
opts["type"] = "auto";
|
|
105426
|
-
opts["json"] = "";
|
|
105427
|
-
opts["escape_quotes"] = "0";
|
|
105428
|
-
incr();
|
|
105429
|
-
return multipartPostAsync(key, apiUri(branch, prj, key, op), opts, filename, data)
|
|
105430
|
-
.then(resp => handleResponseAsync(resp));
|
|
105431
|
-
}
|
|
105432
|
-
function handleResponseAsync(resp) {
|
|
105433
|
-
var _a, _b, _c;
|
|
105434
|
-
const code = resp.statusCode;
|
|
105435
|
-
const errorData = pxt.Util.jsonTryParse(resp.text) || {};
|
|
105436
|
-
pxt.debug(`upload result: ${code}`);
|
|
105437
|
-
if (code == 404 && errorData.error && errorData.error.code == 8) {
|
|
105438
|
-
pxt.log(`create new translation file: ${filename}`);
|
|
105439
|
-
return uploadAsync("add-file", {});
|
|
105440
|
-
}
|
|
105441
|
-
else if (code == 404 && ((_a = errorData.error) === null || _a === void 0 ? void 0 : _a.code) == 17) {
|
|
105442
|
-
return createDirectoryAsync(branch, prj, key, filename.replace(/\/[^\/]+$/, ""), incr)
|
|
105443
|
-
.then(() => startAsync());
|
|
105444
|
-
}
|
|
105445
|
-
else if (!errorData.success && ((_b = errorData.error) === null || _b === void 0 ? void 0 : _b.code) == 53) {
|
|
105446
|
-
// file is being updated
|
|
105447
|
-
pxt.log(`${filename} being updated, waiting 5s and retry...`);
|
|
105448
|
-
return pxt.U.delay(5000) // wait 5s and try again
|
|
105449
|
-
.then(() => uploadTranslationAsync(branch, prj, key, filename, data));
|
|
105450
|
-
}
|
|
105451
|
-
else if (code == 429 && ((_c = errorData.error) === null || _c === void 0 ? void 0 : _c.code) == 55) {
|
|
105452
|
-
// Too many concurrent requests
|
|
105453
|
-
pxt.log(`Maximum concurrent requests reached, waiting 10s and retry...`);
|
|
105454
|
-
return pxt.U.delay(10 * 1000) // wait 10s and try again
|
|
105455
|
-
.then(() => uploadTranslationAsync(branch, prj, key, filename, data));
|
|
105456
|
-
}
|
|
105457
|
-
else if (code == 200 || errorData.success) {
|
|
105458
|
-
// something crowdin reports 500 with success=true
|
|
105459
|
-
return Promise.resolve();
|
|
105460
|
-
}
|
|
105461
|
-
else {
|
|
105462
|
-
throw new Error(`Error, upload translation: ${filename}, ${code}, ${resp.text}`);
|
|
105463
|
-
}
|
|
105464
|
-
}
|
|
105465
|
-
return startAsync();
|
|
105466
|
-
}
|
|
105467
|
-
crowdin.uploadTranslationAsync = uploadTranslationAsync;
|
|
105468
|
-
function flatten(allFiles, node, parentDir, branch) {
|
|
105469
|
-
const n = node.name;
|
|
105470
|
-
const d = parentDir ? parentDir + "/" + n : n;
|
|
105471
|
-
node.fullName = d;
|
|
105472
|
-
node.branch = branch || "";
|
|
105473
|
-
switch (node.node_type) {
|
|
105474
|
-
case "file":
|
|
105475
|
-
allFiles.push(node);
|
|
105476
|
-
break;
|
|
105477
|
-
case "directory":
|
|
105478
|
-
(node.files || []).forEach(f => flatten(allFiles, f, d, branch));
|
|
105479
|
-
break;
|
|
105480
|
-
case "branch":
|
|
105481
|
-
(node.files || []).forEach(f => flatten(allFiles, f, parentDir, node.name));
|
|
105482
|
-
break;
|
|
105483
|
-
}
|
|
105484
|
-
}
|
|
105485
|
-
function filterAndFlattenFiles(files, crowdinPath) {
|
|
105486
|
-
const pxtCrowdinBranch = pxt.appTarget.versions.pxtCrowdinBranch || "";
|
|
105487
|
-
const targetCrowdinBranch = pxt.appTarget.versions.targetCrowdinBranch || "";
|
|
105488
|
-
let allFiles = [];
|
|
105489
|
-
// flatten the files
|
|
105490
|
-
files.forEach(f => flatten(allFiles, f, ""));
|
|
105491
|
-
// top level files are for PXT, subolder are targets
|
|
105492
|
-
allFiles = allFiles.filter(f => {
|
|
105493
|
-
if (f.fullName.indexOf('/') < 0)
|
|
105494
|
-
return f.branch == pxtCrowdinBranch; // pxt file
|
|
105495
|
-
else
|
|
105496
|
-
return f.branch == targetCrowdinBranch;
|
|
105497
|
-
});
|
|
105498
|
-
// folder filter
|
|
105499
|
-
if (crowdinPath) {
|
|
105500
|
-
// filter out crowdin folder
|
|
105501
|
-
allFiles = allFiles.filter(f => f.fullName.indexOf(crowdinPath) == 0);
|
|
105502
|
-
}
|
|
105503
|
-
// filter out non-target files
|
|
105504
|
-
if (pxt.appTarget.id != "core") {
|
|
105505
|
-
const id = pxt.appTarget.id + '/';
|
|
105506
|
-
allFiles = allFiles.filter(f => {
|
|
105507
|
-
return f.fullName.indexOf('/') < 0 // top level file
|
|
105508
|
-
|| f.fullName.substr(0, id.length) == id // from the target folder
|
|
105509
|
-
|| f.fullName.indexOf('common-docs') >= 0; // common docs
|
|
105510
|
-
});
|
|
105511
|
-
}
|
|
105512
|
-
return allFiles;
|
|
105513
|
-
}
|
|
105514
|
-
function projectInfoAsync(prj, key) {
|
|
105515
|
-
const q = { json: "true" };
|
|
105516
|
-
const infoUri = apiUri("", prj, key, "info", q);
|
|
105517
|
-
return pxt.Util.httpGetTextAsync(infoUri).then(respText => {
|
|
105518
|
-
const info = JSON.parse(respText);
|
|
105519
|
-
return info;
|
|
105520
|
-
});
|
|
105521
|
-
}
|
|
105522
|
-
crowdin.projectInfoAsync = projectInfoAsync;
|
|
105523
|
-
/**
|
|
105524
|
-
* Scans files in crowdin and report files that are not on disk anymore
|
|
105525
|
-
*/
|
|
105526
|
-
function listFilesAsync(prj, key, crowdinPath) {
|
|
105527
|
-
pxt.log(`crowdin: listing files under ${crowdinPath}`);
|
|
105528
|
-
return projectInfoAsync(prj, key)
|
|
105529
|
-
.then(info => {
|
|
105530
|
-
if (!info)
|
|
105531
|
-
throw new Error("info failed");
|
|
105532
|
-
let allFiles = filterAndFlattenFiles(info.files, crowdinPath);
|
|
105533
|
-
pxt.debug(`crowdin: found ${allFiles.length} under ${crowdinPath}`);
|
|
105534
|
-
return allFiles.map(f => {
|
|
105535
|
-
return {
|
|
105536
|
-
fullName: f.fullName,
|
|
105537
|
-
branch: f.branch || ""
|
|
105538
|
-
};
|
|
105539
|
-
});
|
|
105540
|
-
});
|
|
105541
|
-
}
|
|
105542
|
-
crowdin.listFilesAsync = listFilesAsync;
|
|
105543
|
-
function languageStatsAsync(prj, key, lang) {
|
|
105544
|
-
const uri = apiUri("", prj, key, "language-status", { language: lang, json: "true" });
|
|
105545
|
-
return pxt.Util.httpGetJsonAsync(uri)
|
|
105546
|
-
.then(info => {
|
|
105547
|
-
const allFiles = filterAndFlattenFiles(info.files);
|
|
105548
|
-
return allFiles;
|
|
105549
|
-
});
|
|
105550
|
-
}
|
|
105551
|
-
crowdin.languageStatsAsync = languageStatsAsync;
|
|
105552
105312
|
function inContextLoadAsync(text) {
|
|
105553
105313
|
const node = document.createElement("input");
|
|
105554
105314
|
node.type = "text";
|
|
@@ -111039,11 +110799,12 @@ var pxt;
|
|
|
111039
110799
|
return result;
|
|
111040
110800
|
}
|
|
111041
110801
|
sprite_1.resizeTilemap = resizeTilemap;
|
|
111042
|
-
function imageLiteralToBitmap(text) {
|
|
110802
|
+
function imageLiteralToBitmap(text, templateLiteral = "img") {
|
|
111043
110803
|
// Strip the tagged template string business and the whitespace. We don't have to exhaustively
|
|
111044
110804
|
// replace encoded characters because the compiler will catch any disallowed characters and throw
|
|
111045
110805
|
// an error before the decompilation happens. 96 is backtick and 9 is tab
|
|
111046
110806
|
text = text.replace(/[ `]|(?:`)|(?:	)|(?:img)/g, "").trim();
|
|
110807
|
+
text = text.replaceAll(templateLiteral, "");
|
|
111047
110808
|
text = text.replace(/^["`\(\)]*/, '').replace(/["`\(\)]*$/, '');
|
|
111048
110809
|
text = text.replace(/ /g, "\n");
|
|
111049
110810
|
const rows = text.split("\n");
|
|
@@ -111205,14 +110966,14 @@ var pxt;
|
|
|
111205
110966
|
pxt.sprite.trimTilemapTileset(result);
|
|
111206
110967
|
}
|
|
111207
110968
|
sprite_1.updateTilemapReferencesFromResult = updateTilemapReferencesFromResult;
|
|
111208
|
-
function imageLiteralPrologue(fileType) {
|
|
110969
|
+
function imageLiteralPrologue(fileType, templateLiteral = "img") {
|
|
111209
110970
|
let res = '';
|
|
111210
110971
|
switch (fileType) {
|
|
111211
110972
|
case "python":
|
|
111212
|
-
res =
|
|
110973
|
+
res = `${templateLiteral}("""`;
|
|
111213
110974
|
break;
|
|
111214
110975
|
default:
|
|
111215
|
-
res =
|
|
110976
|
+
res = `${templateLiteral}\``;
|
|
111216
110977
|
break;
|
|
111217
110978
|
}
|
|
111218
110979
|
return res;
|
|
@@ -111243,10 +111004,10 @@ var pxt;
|
|
|
111243
111004
|
return res;
|
|
111244
111005
|
}
|
|
111245
111006
|
sprite_1.imageLiteralFromDimensions = imageLiteralFromDimensions;
|
|
111246
|
-
function bitmapToImageLiteral(bitmap, fileType) {
|
|
111007
|
+
function bitmapToImageLiteral(bitmap, fileType, templateLiteral = "img") {
|
|
111247
111008
|
if (!bitmap || bitmap.height === 0 || bitmap.width === 0)
|
|
111248
111009
|
return "";
|
|
111249
|
-
let res = imageLiteralPrologue(fileType);
|
|
111010
|
+
let res = imageLiteralPrologue(fileType, templateLiteral);
|
|
111250
111011
|
if (bitmap) {
|
|
111251
111012
|
const paddingBetweenPixels = (bitmap.width * bitmap.height > 300) ? "" : " ";
|
|
111252
111013
|
for (let r = 0; r < bitmap.height; r++) {
|
|
@@ -113747,11 +113508,7 @@ var pxt;
|
|
|
113747
113508
|
};
|
|
113748
113509
|
await loadDepsRecursive(null, this);
|
|
113749
113510
|
// get paletter config loading deps, so the more higher level packages take precedence
|
|
113750
|
-
|
|
113751
|
-
pxt.appTarget.runtime.palette = pxt.U.clone(this.config.palette);
|
|
113752
|
-
if (this.config.paletteNames)
|
|
113753
|
-
pxt.appTarget.runtime.paletteNames = this.config.paletteNames;
|
|
113754
|
-
}
|
|
113511
|
+
this.patchAppTargetPalette();
|
|
113755
113512
|
// get screen size loading deps, so the more higher level packages take precedence
|
|
113756
113513
|
if (this.config.screenSize && pxt.appTarget.runtime)
|
|
113757
113514
|
pxt.appTarget.runtime.screenSize = pxt.U.clone(this.config.screenSize);
|
|
@@ -113897,6 +113654,13 @@ var pxt;
|
|
|
113897
113654
|
}
|
|
113898
113655
|
return r;
|
|
113899
113656
|
}
|
|
113657
|
+
patchAppTargetPalette() {
|
|
113658
|
+
if (this.config.palette && pxt.appTarget.runtime) {
|
|
113659
|
+
pxt.appTarget.runtime.palette = pxt.U.clone(this.config.palette);
|
|
113660
|
+
if (this.config.paletteNames)
|
|
113661
|
+
pxt.appTarget.runtime.paletteNames = this.config.paletteNames;
|
|
113662
|
+
}
|
|
113663
|
+
}
|
|
113900
113664
|
}
|
|
113901
113665
|
Package.depWarnings = {};
|
|
113902
113666
|
pxt.Package = Package;
|
|
@@ -114158,6 +113922,10 @@ var pxt;
|
|
|
114158
113922
|
opts.jres = this.getJRes();
|
|
114159
113923
|
const functionOpts = pxt.appTarget.runtime && pxt.appTarget.runtime.functionsOptions;
|
|
114160
113924
|
opts.allowedArgumentTypes = functionOpts && functionOpts.extraFunctionEditorTypes && functionOpts.extraFunctionEditorTypes.map(info => info.typeName).concat("number", "boolean", "string");
|
|
113925
|
+
for (const dep of this.sortedDeps()) {
|
|
113926
|
+
dep.patchAppTargetPalette();
|
|
113927
|
+
}
|
|
113928
|
+
this.patchAppTargetPalette();
|
|
114161
113929
|
return opts;
|
|
114162
113930
|
}
|
|
114163
113931
|
prepareConfigToBePublished() {
|
|
@@ -118932,7 +118700,7 @@ var pxt;
|
|
|
118932
118700
|
if (!steps)
|
|
118933
118701
|
return undefined; // error parsing steps
|
|
118934
118702
|
// collect code and infer editor
|
|
118935
|
-
const { code, templateCode, editor, language, jres, assetJson, customTs, simThemeJson } = computeBodyMetadata(body);
|
|
118703
|
+
const { code, templateCode, templateLanguage, editor, language, jres, assetJson, customTs, simThemeJson } = computeBodyMetadata(body);
|
|
118936
118704
|
// noDiffs legacy
|
|
118937
118705
|
if (metadata.diffs === true // enabled in tutorial
|
|
118938
118706
|
|| (metadata.diffs !== false && metadata.noDiffs !== true // not disabled
|
|
@@ -118958,6 +118726,7 @@ var pxt;
|
|
|
118958
118726
|
activities,
|
|
118959
118727
|
code,
|
|
118960
118728
|
templateCode,
|
|
118729
|
+
templateLanguage,
|
|
118961
118730
|
metadata,
|
|
118962
118731
|
language,
|
|
118963
118732
|
jres,
|
|
@@ -118970,7 +118739,7 @@ var pxt;
|
|
|
118970
118739
|
}
|
|
118971
118740
|
tutorial_1.parseTutorial = parseTutorial;
|
|
118972
118741
|
function getMetadataRegex() {
|
|
118973
|
-
return /``` *(sim|block|blocks|filterblocks|spy|ghost|typescript|ts|js|javascript|template|python|jres|assetjson|customts|simtheme)\s*\n([\s\S]*?)\n```/gmi;
|
|
118742
|
+
return /``` *(sim|block|blocks|filterblocks|spy|ghost|typescript|ts|js|javascript|template|python|jres|assetjson|customts|simtheme|python-template|ts-template|typescript-template|js-template|javascript-template)\s*\n([\s\S]*?)\n```/gmi;
|
|
118974
118743
|
}
|
|
118975
118744
|
tutorial_1.getMetadataRegex = getMetadataRegex;
|
|
118976
118745
|
function computeBodyMetadata(body) {
|
|
@@ -118980,6 +118749,7 @@ var pxt;
|
|
|
118980
118749
|
let jres;
|
|
118981
118750
|
let code = [];
|
|
118982
118751
|
let templateCode;
|
|
118752
|
+
let templateLanguage;
|
|
118983
118753
|
let language;
|
|
118984
118754
|
let idx = 0;
|
|
118985
118755
|
let assetJson;
|
|
@@ -119015,6 +118785,22 @@ var pxt;
|
|
|
119015
118785
|
case "template":
|
|
119016
118786
|
templateCode = m2;
|
|
119017
118787
|
break;
|
|
118788
|
+
case "python-template":
|
|
118789
|
+
if (!checkTutorialEditor(pxt.PYTHON_PROJECT_NAME))
|
|
118790
|
+
return undefined;
|
|
118791
|
+
templateCode = m2;
|
|
118792
|
+
templateLanguage = "python";
|
|
118793
|
+
language = "python";
|
|
118794
|
+
break;
|
|
118795
|
+
case "ts-template":
|
|
118796
|
+
case "typescript-template":
|
|
118797
|
+
case "js-template":
|
|
118798
|
+
case "javascript-template":
|
|
118799
|
+
if (!checkTutorialEditor(pxt.JAVASCRIPT_PROJECT_NAME))
|
|
118800
|
+
return undefined;
|
|
118801
|
+
templateCode = m2;
|
|
118802
|
+
templateLanguage = "typescript";
|
|
118803
|
+
break;
|
|
119018
118804
|
case "jres":
|
|
119019
118805
|
jres = m2;
|
|
119020
118806
|
break;
|
|
@@ -119038,6 +118824,7 @@ var pxt;
|
|
|
119038
118824
|
return {
|
|
119039
118825
|
code,
|
|
119040
118826
|
templateCode,
|
|
118827
|
+
templateLanguage,
|
|
119041
118828
|
editor,
|
|
119042
118829
|
language,
|
|
119043
118830
|
jres,
|
|
@@ -119320,6 +119107,7 @@ ${code}
|
|
|
119320
119107
|
tutorialCode: tutorialInfo.code,
|
|
119321
119108
|
tutorialRecipe: !!recipe,
|
|
119322
119109
|
templateCode: tutorialInfo.templateCode,
|
|
119110
|
+
templateLanguage: tutorialInfo.templateLanguage,
|
|
119323
119111
|
autoexpandStep: ((_a = tutorialInfo.metadata) === null || _a === void 0 ? void 0 : _a.autoexpandOff) ? false : true,
|
|
119324
119112
|
metadata: tutorialInfo.metadata,
|
|
119325
119113
|
language: tutorialInfo.language,
|
|
@@ -160874,7 +160662,7 @@ function checkIfTaggedCommitAsync() {
|
|
|
160874
160662
|
});
|
|
160875
160663
|
}
|
|
160876
160664
|
let readJson = nodeutil.readJson;
|
|
160877
|
-
function ciAsync() {
|
|
160665
|
+
async function ciAsync() {
|
|
160878
160666
|
forceCloudBuild = true;
|
|
160879
160667
|
const buildInfo = ciBuildInfo();
|
|
160880
160668
|
pxt.log(`ci build using ${buildInfo.ci}`);
|
|
@@ -160920,55 +160708,54 @@ function ciAsync() {
|
|
|
160920
160708
|
let pkg = readJson("package.json");
|
|
160921
160709
|
if (pkg["name"] == "pxt-core") {
|
|
160922
160710
|
pxt.log("pxt-core build");
|
|
160923
|
-
|
|
160924
|
-
|
|
160925
|
-
|
|
160926
|
-
|
|
160927
|
-
if (
|
|
160928
|
-
|
|
160929
|
-
|
|
160930
|
-
|
|
160931
|
-
|
|
160932
|
-
|
|
160933
|
-
|
|
160934
|
-
|
|
160935
|
-
|
|
160936
|
-
|
|
160937
|
-
p = p.then(() => crowdin.execCrowdinAsync("upload", "built/strings.json"));
|
|
160938
|
-
if (uploadDocs || uploadApiStrings)
|
|
160939
|
-
p = p.then(() => crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs));
|
|
160711
|
+
const isTaggedCommit = await checkIfTaggedCommitAsync();
|
|
160712
|
+
pxt.log(`is tagged commit: ${isTaggedCommit}`);
|
|
160713
|
+
await npmPublishAsync();
|
|
160714
|
+
if (branch === "master" && isTaggedCommit) {
|
|
160715
|
+
if (uploadDocs) {
|
|
160716
|
+
await buildWebStringsAsync();
|
|
160717
|
+
await crowdin.uploadBuiltStringsAsync("built/webstrings.json");
|
|
160718
|
+
await crowdin.uploadBuiltStringsAsync(`built/skillmap-strings.json`);
|
|
160719
|
+
await crowdin.uploadBuiltStringsAsync(`built/authcode-strings.json`);
|
|
160720
|
+
await crowdin.uploadBuiltStringsAsync(`built/multiplayer-strings.json`);
|
|
160721
|
+
await crowdin.uploadBuiltStringsAsync(`built/kiosk-strings.json`);
|
|
160722
|
+
}
|
|
160723
|
+
if (uploadApiStrings) {
|
|
160724
|
+
await crowdin.uploadBuiltStringsAsync("built/strings.json");
|
|
160940
160725
|
}
|
|
160941
|
-
|
|
160942
|
-
|
|
160726
|
+
if (uploadDocs || uploadApiStrings) {
|
|
160727
|
+
await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
|
|
160728
|
+
pxt.log("translations uploaded");
|
|
160729
|
+
}
|
|
160730
|
+
else {
|
|
160731
|
+
pxt.log("skipping translations upload");
|
|
160732
|
+
}
|
|
160733
|
+
}
|
|
160943
160734
|
}
|
|
160944
160735
|
else {
|
|
160945
160736
|
pxt.log("target build");
|
|
160946
|
-
|
|
160947
|
-
|
|
160948
|
-
|
|
160949
|
-
|
|
160950
|
-
|
|
160951
|
-
|
|
160952
|
-
|
|
160953
|
-
|
|
160954
|
-
|
|
160955
|
-
}
|
|
160737
|
+
await internalBuildTargetAsync();
|
|
160738
|
+
await internalCheckDocsAsync(true);
|
|
160739
|
+
await blockTestsAsync();
|
|
160740
|
+
await npmPublishAsync();
|
|
160741
|
+
if (!process.env["PXT_ACCESS_TOKEN"]) {
|
|
160742
|
+
// pull request, don't try to upload target
|
|
160743
|
+
pxt.log('no token, skipping upload');
|
|
160744
|
+
}
|
|
160745
|
+
else {
|
|
160956
160746
|
const trg = readLocalPxTarget();
|
|
160957
160747
|
const label = `${trg.id}/${tag || latest}`;
|
|
160958
160748
|
pxt.log(`uploading target with label ${label}...`);
|
|
160959
|
-
|
|
160960
|
-
}
|
|
160961
|
-
|
|
160962
|
-
|
|
160963
|
-
|
|
160964
|
-
|
|
160965
|
-
|
|
160966
|
-
|
|
160967
|
-
|
|
160968
|
-
|
|
160969
|
-
return Promise.resolve();
|
|
160970
|
-
}
|
|
160971
|
-
});
|
|
160749
|
+
await uploadTargetAsync(label);
|
|
160750
|
+
}
|
|
160751
|
+
pxt.log("target uploaded");
|
|
160752
|
+
if (uploadDocs || uploadApiStrings) {
|
|
160753
|
+
await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
|
|
160754
|
+
pxt.log("translations uploaded");
|
|
160755
|
+
}
|
|
160756
|
+
else {
|
|
160757
|
+
pxt.log("skipping translations upload");
|
|
160758
|
+
}
|
|
160972
160759
|
}
|
|
160973
160760
|
}
|
|
160974
160761
|
function lintJSONInDirectory(dir) {
|
|
@@ -166839,7 +166626,7 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
|
|
|
166839
166626
|
advanced: true,
|
|
166840
166627
|
}, pc => uploadTargetRefsAsync(pc.args[0]));
|
|
166841
166628
|
advancedCommand("uploadtt", "upload tagged release", uploadTaggedTargetAsync, "");
|
|
166842
|
-
advancedCommand("downloadtrgtranslations", "download translations from bundled projects", crowdin.downloadTargetTranslationsAsync, "
|
|
166629
|
+
advancedCommand("downloadtrgtranslations", "download translations from bundled projects", crowdin.downloadTargetTranslationsAsync, "[package]");
|
|
166843
166630
|
p.defineCommand({
|
|
166844
166631
|
name: "checkdocs",
|
|
166845
166632
|
onlineHelp: true,
|
|
@@ -166917,7 +166704,19 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
|
|
|
166917
166704
|
}
|
|
166918
166705
|
}, buildAuthcodeAsync);
|
|
166919
166706
|
advancedCommand("augmentdocs", "test markdown docs replacements", augmnetDocsAsync, "<temlate.md> <doc.md>");
|
|
166920
|
-
|
|
166707
|
+
p.defineCommand({
|
|
166708
|
+
name: "crowdin",
|
|
166709
|
+
advanced: true,
|
|
166710
|
+
argString: "<cmd> <path> [output]",
|
|
166711
|
+
help: "upload, download, clean, stats files to/from crowdin",
|
|
166712
|
+
flags: {
|
|
166713
|
+
test: { description: "test run, do not upload files to crowdin" }
|
|
166714
|
+
}
|
|
166715
|
+
}, pc => {
|
|
166716
|
+
if (pc.flags.test)
|
|
166717
|
+
pxt.crowdin.setTestMode();
|
|
166718
|
+
return crowdin.execCrowdinAsync.apply(undefined, pc.args);
|
|
166719
|
+
});
|
|
166921
166720
|
advancedCommand("hidlist", "list HID devices", hid.listAsync);
|
|
166922
166721
|
advancedCommand("hidserial", "run HID serial forwarding", hid.serialAsync, undefined, true);
|
|
166923
166722
|
advancedCommand("hiddmesg", "fetch DMESG buffer over HID and print it", hid.dmesgAsync, undefined, true);
|
package/built/pxtblockly.js
CHANGED
|
@@ -12159,7 +12159,7 @@ var pxtblockly;
|
|
|
12159
12159
|
const existing = pxt.lookupProjectAssetByTSReference(text, project);
|
|
12160
12160
|
if (existing)
|
|
12161
12161
|
return existing;
|
|
12162
|
-
const frames = parseImageArrayString(text);
|
|
12162
|
+
const frames = parseImageArrayString(text, this.params.taggedTemplate);
|
|
12163
12163
|
if (frames && frames.length) {
|
|
12164
12164
|
const id = this.sourceBlock_.id;
|
|
12165
12165
|
const newAnimation = {
|
|
@@ -12195,7 +12195,7 @@ var pxtblockly;
|
|
|
12195
12195
|
if (!this.asset)
|
|
12196
12196
|
return "[]";
|
|
12197
12197
|
if (this.isTemporaryAsset()) {
|
|
12198
|
-
return "[" + this.asset.frames.map(frame => pxt.sprite.bitmapToImageLiteral(pxt.sprite.Bitmap.fromData(frame), "typescript" /* pxt.editor.FileType.TypeScript
|
|
12198
|
+
return "[" + this.asset.frames.map(frame => pxt.sprite.bitmapToImageLiteral(pxt.sprite.Bitmap.fromData(frame), "typescript" /* pxt.editor.FileType.TypeScript */, this.params.taggedTemplate)).join(",") + "]";
|
|
12199
12199
|
}
|
|
12200
12200
|
return pxt.getTSReferenceForAsset(this.asset);
|
|
12201
12201
|
}
|
|
@@ -12274,6 +12274,7 @@ var pxtblockly;
|
|
|
12274
12274
|
}
|
|
12275
12275
|
parsed.initWidth = withDefault(opts.initWidth, parsed.initWidth);
|
|
12276
12276
|
parsed.initHeight = withDefault(opts.initHeight, parsed.initHeight);
|
|
12277
|
+
parsed.taggedTemplate = opts.taggedTemplate;
|
|
12277
12278
|
return parsed;
|
|
12278
12279
|
function withDefault(raw, def) {
|
|
12279
12280
|
const res = parseInt(raw);
|
|
@@ -12283,11 +12284,11 @@ var pxtblockly;
|
|
|
12283
12284
|
return res;
|
|
12284
12285
|
}
|
|
12285
12286
|
}
|
|
12286
|
-
function parseImageArrayString(str) {
|
|
12287
|
+
function parseImageArrayString(str, templateLiteral) {
|
|
12287
12288
|
if (str.indexOf("[") === -1)
|
|
12288
12289
|
return null;
|
|
12289
12290
|
str = str.replace(/[\[\]]/mg, "");
|
|
12290
|
-
return str.split(",").map(s => pxt.sprite.imageLiteralToBitmap(s).data()).filter(b => b.height && b.width);
|
|
12291
|
+
return str.split(",").map(s => pxt.sprite.imageLiteralToBitmap(s, templateLiteral).data()).filter(b => b.height && b.width);
|
|
12291
12292
|
}
|
|
12292
12293
|
function isNumberType(type) {
|
|
12293
12294
|
return type === "math_number" || type === "math_integer" || type === "math_whole_number";
|
|
@@ -16326,7 +16327,7 @@ var pxtblockly;
|
|
|
16326
16327
|
if (this.getBlockData()) {
|
|
16327
16328
|
return project.lookupAsset("image" /* pxt.AssetType.Image */, this.getBlockData());
|
|
16328
16329
|
}
|
|
16329
|
-
const bmp = text ? pxt.sprite.imageLiteralToBitmap(text) : new pxt.sprite.Bitmap(this.params.initWidth, this.params.initHeight);
|
|
16330
|
+
const bmp = text ? pxt.sprite.imageLiteralToBitmap(text, this.params.taggedTemplate) : new pxt.sprite.Bitmap(this.params.initWidth, this.params.initHeight);
|
|
16330
16331
|
if (!bmp) {
|
|
16331
16332
|
this.isGreyBlock = true;
|
|
16332
16333
|
this.valueText = text;
|
|
@@ -16347,7 +16348,7 @@ var pxtblockly;
|
|
|
16347
16348
|
if (this.asset && !this.isTemporaryAsset()) {
|
|
16348
16349
|
return pxt.getTSReferenceForAsset(this.asset);
|
|
16349
16350
|
}
|
|
16350
|
-
return pxt.sprite.bitmapToImageLiteral(this.asset && pxt.sprite.Bitmap.fromData(this.asset.bitmap), "typescript" /* pxt.editor.FileType.TypeScript
|
|
16351
|
+
return pxt.sprite.bitmapToImageLiteral(this.asset && pxt.sprite.Bitmap.fromData(this.asset.bitmap), "typescript" /* pxt.editor.FileType.TypeScript */, this.params.taggedTemplate);
|
|
16351
16352
|
}
|
|
16352
16353
|
parseFieldOptions(opts) {
|
|
16353
16354
|
return parseFieldOptions(opts);
|
|
@@ -16402,6 +16403,7 @@ var pxtblockly;
|
|
|
16402
16403
|
parsed.initColor = withDefault(opts.initColor, parsed.initColor);
|
|
16403
16404
|
parsed.initWidth = withDefault(opts.initWidth, parsed.initWidth);
|
|
16404
16405
|
parsed.initHeight = withDefault(opts.initHeight, parsed.initHeight);
|
|
16406
|
+
parsed.taggedTemplate = opts.taggedTemplate;
|
|
16405
16407
|
return parsed;
|
|
16406
16408
|
function withDefault(raw, def) {
|
|
16407
16409
|
const res = parseInt(raw);
|
package/built/pxtblocks.d.ts
CHANGED
|
@@ -498,6 +498,7 @@ declare namespace pxtblockly {
|
|
|
498
498
|
disableResize: string;
|
|
499
499
|
filter?: string;
|
|
500
500
|
lightMode: boolean;
|
|
501
|
+
taggedTemplate?: string;
|
|
501
502
|
}
|
|
502
503
|
interface ParsedFieldAnimationOptions {
|
|
503
504
|
initWidth: number;
|
|
@@ -505,6 +506,7 @@ declare namespace pxtblockly {
|
|
|
505
506
|
disableResize: boolean;
|
|
506
507
|
filter?: string;
|
|
507
508
|
lightMode: boolean;
|
|
509
|
+
taggedTemplate?: string;
|
|
508
510
|
}
|
|
509
511
|
class FieldAnimationEditor extends FieldAssetEditor<FieldAnimationOptions, ParsedFieldAnimationOptions> {
|
|
510
512
|
protected frames: string[];
|
|
@@ -1293,6 +1295,7 @@ declare namespace pxtblockly {
|
|
|
1293
1295
|
disableResize: string;
|
|
1294
1296
|
filter?: string;
|
|
1295
1297
|
lightMode: boolean;
|
|
1298
|
+
taggedTemplate?: string;
|
|
1296
1299
|
}
|
|
1297
1300
|
interface ParsedSpriteEditorOptions {
|
|
1298
1301
|
initColor: number;
|
|
@@ -1301,6 +1304,7 @@ declare namespace pxtblockly {
|
|
|
1301
1304
|
disableResize: boolean;
|
|
1302
1305
|
filter?: string;
|
|
1303
1306
|
lightMode: boolean;
|
|
1307
|
+
taggedTemplate?: string;
|
|
1304
1308
|
}
|
|
1305
1309
|
export class FieldSpriteEditor extends FieldAssetEditor<FieldSpriteEditorOptions, ParsedSpriteEditorOptions> {
|
|
1306
1310
|
protected getAssetType(): pxt.AssetType;
|