pxt-core 9.2.9 → 9.2.10

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/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(/[ `]|(?:&#96;)|(?:&#9;)|(?:img)/g, "").trim();
110807
+ text = text.replaceAll(templateLiteral, "");
111047
110808
  text = text.replace(/^["`\(\)]*/, '').replace(/["`\(\)]*$/, '');
111048
110809
  text = text.replace(/&#10;/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 = "img(\"\"\"";
110973
+ res = `${templateLiteral}("""`;
111213
110974
  break;
111214
110975
  default:
111215
- res = "img`";
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
- if (this.config.palette && pxt.appTarget.runtime) {
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() {
@@ -160874,7 +160642,7 @@ function checkIfTaggedCommitAsync() {
160874
160642
  });
160875
160643
  }
160876
160644
  let readJson = nodeutil.readJson;
160877
- function ciAsync() {
160645
+ async function ciAsync() {
160878
160646
  forceCloudBuild = true;
160879
160647
  const buildInfo = ciBuildInfo();
160880
160648
  pxt.log(`ci build using ${buildInfo.ci}`);
@@ -160920,55 +160688,54 @@ function ciAsync() {
160920
160688
  let pkg = readJson("package.json");
160921
160689
  if (pkg["name"] == "pxt-core") {
160922
160690
  pxt.log("pxt-core build");
160923
- return checkIfTaggedCommitAsync()
160924
- .then(isTaggedCommit => {
160925
- pxt.log(`is tagged commit: ${isTaggedCommit}`);
160926
- let p = npmPublishAsync();
160927
- if (branch === "master" && isTaggedCommit) {
160928
- if (uploadDocs)
160929
- p = p
160930
- .then(() => buildWebStringsAsync())
160931
- .then(() => crowdin.execCrowdinAsync("upload", "built/webstrings.json"))
160932
- .then(() => crowdin.execCrowdinAsync("upload", "built/skillmap-strings.json"))
160933
- .then(() => crowdin.execCrowdinAsync("upload", "built/authcode-strings.json"))
160934
- .then(() => crowdin.execCrowdinAsync("upload", "built/multiplayer-strings.json"))
160935
- .then(() => crowdin.execCrowdinAsync("upload", "built/kiosk-strings.json"));
160936
- if (uploadApiStrings)
160937
- p = p.then(() => crowdin.execCrowdinAsync("upload", "built/strings.json"));
160938
- if (uploadDocs || uploadApiStrings)
160939
- p = p.then(() => crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs));
160691
+ const isTaggedCommit = await checkIfTaggedCommitAsync();
160692
+ pxt.log(`is tagged commit: ${isTaggedCommit}`);
160693
+ await npmPublishAsync();
160694
+ if (branch === "master" && isTaggedCommit) {
160695
+ if (uploadDocs) {
160696
+ await buildWebStringsAsync();
160697
+ await crowdin.uploadBuiltStringsAsync("built/webstrings.json");
160698
+ await crowdin.uploadBuiltStringsAsync(`built/skillmap-strings.json`);
160699
+ await crowdin.uploadBuiltStringsAsync(`built/authcode-strings.json`);
160700
+ await crowdin.uploadBuiltStringsAsync(`built/multiplayer-strings.json`);
160701
+ await crowdin.uploadBuiltStringsAsync(`built/kiosk-strings.json`);
160702
+ }
160703
+ if (uploadApiStrings) {
160704
+ await crowdin.uploadBuiltStringsAsync("built/strings.json");
160940
160705
  }
160941
- return p;
160942
- });
160706
+ if (uploadDocs || uploadApiStrings) {
160707
+ await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
160708
+ pxt.log("translations uploaded");
160709
+ }
160710
+ else {
160711
+ pxt.log("skipping translations upload");
160712
+ }
160713
+ }
160943
160714
  }
160944
160715
  else {
160945
160716
  pxt.log("target build");
160946
- return internalBuildTargetAsync()
160947
- .then(() => internalCheckDocsAsync(true))
160948
- .then(() => blockTestsAsync())
160949
- .then(() => npmPublishAsync())
160950
- .then(() => {
160951
- if (!process.env["PXT_ACCESS_TOKEN"]) {
160952
- // pull request, don't try to upload target
160953
- pxt.log('no token, skipping upload');
160954
- return Promise.resolve();
160955
- }
160717
+ await internalBuildTargetAsync();
160718
+ await internalCheckDocsAsync(true);
160719
+ await blockTestsAsync();
160720
+ await npmPublishAsync();
160721
+ if (!process.env["PXT_ACCESS_TOKEN"]) {
160722
+ // pull request, don't try to upload target
160723
+ pxt.log('no token, skipping upload');
160724
+ }
160725
+ else {
160956
160726
  const trg = readLocalPxTarget();
160957
160727
  const label = `${trg.id}/${tag || latest}`;
160958
160728
  pxt.log(`uploading target with label ${label}...`);
160959
- return uploadTargetAsync(label);
160960
- })
160961
- .then(() => {
160962
- pxt.log("target uploaded");
160963
- if (uploadDocs || uploadApiStrings) {
160964
- return crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs)
160965
- .then(() => pxt.log("translations uploaded"));
160966
- }
160967
- else {
160968
- pxt.log("skipping translations upload");
160969
- return Promise.resolve();
160970
- }
160971
- });
160729
+ await uploadTargetAsync(label);
160730
+ }
160731
+ pxt.log("target uploaded");
160732
+ if (uploadDocs || uploadApiStrings) {
160733
+ await crowdin.internalUploadTargetTranslationsAsync(uploadApiStrings, uploadDocs);
160734
+ pxt.log("translations uploaded");
160735
+ }
160736
+ else {
160737
+ pxt.log("skipping translations upload");
160738
+ }
160972
160739
  }
160973
160740
  }
160974
160741
  function lintJSONInDirectory(dir) {
@@ -166839,7 +166606,7 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
166839
166606
  advanced: true,
166840
166607
  }, pc => uploadTargetRefsAsync(pc.args[0]));
166841
166608
  advancedCommand("uploadtt", "upload tagged release", uploadTaggedTargetAsync, "");
166842
- advancedCommand("downloadtrgtranslations", "download translations from bundled projects", crowdin.downloadTargetTranslationsAsync, "<package>");
166609
+ advancedCommand("downloadtrgtranslations", "download translations from bundled projects", crowdin.downloadTargetTranslationsAsync, "[package]");
166843
166610
  p.defineCommand({
166844
166611
  name: "checkdocs",
166845
166612
  onlineHelp: true,
@@ -166917,7 +166684,19 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
166917
166684
  }
166918
166685
  }, buildAuthcodeAsync);
166919
166686
  advancedCommand("augmentdocs", "test markdown docs replacements", augmnetDocsAsync, "<temlate.md> <doc.md>");
166920
- advancedCommand("crowdin", "upload, download, clean, stats files to/from crowdin", pc => crowdin.execCrowdinAsync.apply(undefined, pc.args), "<cmd> <path> [output]");
166687
+ p.defineCommand({
166688
+ name: "crowdin",
166689
+ advanced: true,
166690
+ argString: "<cmd> <path> [output]",
166691
+ help: "upload, download, clean, stats files to/from crowdin",
166692
+ flags: {
166693
+ test: { description: "test run, do not upload files to crowdin" }
166694
+ }
166695
+ }, pc => {
166696
+ if (pc.flags.test)
166697
+ pxt.crowdin.setTestMode();
166698
+ return crowdin.execCrowdinAsync.apply(undefined, pc.args);
166699
+ });
166921
166700
  advancedCommand("hidlist", "list HID devices", hid.listAsync);
166922
166701
  advancedCommand("hidserial", "run HID serial forwarding", hid.serialAsync, undefined, true);
166923
166702
  advancedCommand("hiddmesg", "fetch DMESG buffer over HID and print it", hid.dmesgAsync, undefined, true);
@@ -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 */)).join(",") + "]";
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);
@@ -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;
@@ -8597,7 +8597,7 @@ var pxtblockly;
8597
8597
  const existing = pxt.lookupProjectAssetByTSReference(text, project);
8598
8598
  if (existing)
8599
8599
  return existing;
8600
- const frames = parseImageArrayString(text);
8600
+ const frames = parseImageArrayString(text, this.params.taggedTemplate);
8601
8601
  if (frames && frames.length) {
8602
8602
  const id = this.sourceBlock_.id;
8603
8603
  const newAnimation = {
@@ -8633,7 +8633,7 @@ var pxtblockly;
8633
8633
  if (!this.asset)
8634
8634
  return "[]";
8635
8635
  if (this.isTemporaryAsset()) {
8636
- return "[" + this.asset.frames.map(frame => pxt.sprite.bitmapToImageLiteral(pxt.sprite.Bitmap.fromData(frame), "typescript" /* pxt.editor.FileType.TypeScript */)).join(",") + "]";
8636
+ return "[" + this.asset.frames.map(frame => pxt.sprite.bitmapToImageLiteral(pxt.sprite.Bitmap.fromData(frame), "typescript" /* pxt.editor.FileType.TypeScript */, this.params.taggedTemplate)).join(",") + "]";
8637
8637
  }
8638
8638
  return pxt.getTSReferenceForAsset(this.asset);
8639
8639
  }
@@ -8712,6 +8712,7 @@ var pxtblockly;
8712
8712
  }
8713
8713
  parsed.initWidth = withDefault(opts.initWidth, parsed.initWidth);
8714
8714
  parsed.initHeight = withDefault(opts.initHeight, parsed.initHeight);
8715
+ parsed.taggedTemplate = opts.taggedTemplate;
8715
8716
  return parsed;
8716
8717
  function withDefault(raw, def) {
8717
8718
  const res = parseInt(raw);
@@ -8721,11 +8722,11 @@ var pxtblockly;
8721
8722
  return res;
8722
8723
  }
8723
8724
  }
8724
- function parseImageArrayString(str) {
8725
+ function parseImageArrayString(str, templateLiteral) {
8725
8726
  if (str.indexOf("[") === -1)
8726
8727
  return null;
8727
8728
  str = str.replace(/[\[\]]/mg, "");
8728
- return str.split(",").map(s => pxt.sprite.imageLiteralToBitmap(s).data()).filter(b => b.height && b.width);
8729
+ return str.split(",").map(s => pxt.sprite.imageLiteralToBitmap(s, templateLiteral).data()).filter(b => b.height && b.width);
8729
8730
  }
8730
8731
  function isNumberType(type) {
8731
8732
  return type === "math_number" || type === "math_integer" || type === "math_whole_number";
@@ -12764,7 +12765,7 @@ var pxtblockly;
12764
12765
  if (this.getBlockData()) {
12765
12766
  return project.lookupAsset("image" /* pxt.AssetType.Image */, this.getBlockData());
12766
12767
  }
12767
- const bmp = text ? pxt.sprite.imageLiteralToBitmap(text) : new pxt.sprite.Bitmap(this.params.initWidth, this.params.initHeight);
12768
+ const bmp = text ? pxt.sprite.imageLiteralToBitmap(text, this.params.taggedTemplate) : new pxt.sprite.Bitmap(this.params.initWidth, this.params.initHeight);
12768
12769
  if (!bmp) {
12769
12770
  this.isGreyBlock = true;
12770
12771
  this.valueText = text;
@@ -12785,7 +12786,7 @@ var pxtblockly;
12785
12786
  if (this.asset && !this.isTemporaryAsset()) {
12786
12787
  return pxt.getTSReferenceForAsset(this.asset);
12787
12788
  }
12788
- return pxt.sprite.bitmapToImageLiteral(this.asset && pxt.sprite.Bitmap.fromData(this.asset.bitmap), "typescript" /* pxt.editor.FileType.TypeScript */);
12789
+ return pxt.sprite.bitmapToImageLiteral(this.asset && pxt.sprite.Bitmap.fromData(this.asset.bitmap), "typescript" /* pxt.editor.FileType.TypeScript */, this.params.taggedTemplate);
12789
12790
  }
12790
12791
  parseFieldOptions(opts) {
12791
12792
  return parseFieldOptions(opts);
@@ -12840,6 +12841,7 @@ var pxtblockly;
12840
12841
  parsed.initColor = withDefault(opts.initColor, parsed.initColor);
12841
12842
  parsed.initWidth = withDefault(opts.initWidth, parsed.initWidth);
12842
12843
  parsed.initHeight = withDefault(opts.initHeight, parsed.initHeight);
12844
+ parsed.taggedTemplate = opts.taggedTemplate;
12843
12845
  return parsed;
12844
12846
  function withDefault(raw, def) {
12845
12847
  const res = parseInt(raw);