pxt-core 8.0.3 → 8.1.2

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.
Files changed (42) hide show
  1. package/built/backendutils.js +13 -6
  2. package/built/pxt.js +20 -7
  3. package/built/pxtblockly.js +2 -0
  4. package/built/pxtblocks.js +2 -0
  5. package/built/pxtcompiler.js +1 -0
  6. package/built/pxteditor.d.ts +11 -0
  7. package/built/pxteditor.js +199 -2
  8. package/built/pxtlib.js +14 -7
  9. package/built/pxtrunner.d.ts +1 -0
  10. package/built/pxtrunner.js +2 -1
  11. package/built/pxtsim.d.ts +1 -0
  12. package/built/pxtsim.js +5 -0
  13. package/built/server.js +1 -1
  14. package/built/target.js +1 -1
  15. package/built/web/blockly.css +1 -1
  16. package/built/web/main.js +1 -1
  17. package/built/web/pxtapp.js +1 -1
  18. package/built/web/pxtblockly.js +1 -1
  19. package/built/web/pxtblocks.js +1 -1
  20. package/built/web/pxtcompiler.js +1 -1
  21. package/built/web/pxteditor.js +1 -1
  22. package/built/web/pxtembed.js +2 -2
  23. package/built/web/pxtlib.js +1 -1
  24. package/built/web/pxtrunner.js +1 -1
  25. package/built/web/pxtsim.js +1 -1
  26. package/built/web/pxtworker.js +1 -1
  27. package/built/web/rtlblockly.css +1 -1
  28. package/built/web/rtlsemantic.css +1 -1
  29. package/built/web/semantic.css +1 -1
  30. package/common-docs/release-tests/editor.md +2 -1
  31. package/docfiles/domains-template.html +1 -0
  32. package/package.json +2 -1
  33. package/react-common/components/controls/EmbedVideo.tsx +45 -0
  34. package/react-common/styles/controls/EmbedVideo.less +4 -0
  35. package/theme/blockly-core.less +0 -4
  36. package/theme/common.less +5 -0
  37. package/theme/serial.less +27 -2
  38. package/theme/toolbox.less +4 -0
  39. package/theme/tutorial-sidebar.less +6 -0
  40. package/webapp/public/index.html +2 -1
  41. package/webapp/public/run.html +3 -1
  42. package/webapp/public/zip.js/zip.min.js +28 -0
@@ -689,13 +689,20 @@ var pxt;
689
689
  docs.prepTemplate = prepTemplate;
690
690
  function setupRenderer(renderer) {
691
691
  renderer.image = function (href, title, text) {
692
- let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
693
- if (title) {
694
- out += ' title="' + title + '"';
692
+ if (href.startsWith("youtube:")) {
693
+ let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
694
+ + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
695
+ return out;
696
+ }
697
+ else {
698
+ let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
699
+ if (title) {
700
+ out += ' title="' + title + '"';
701
+ }
702
+ out += ' loading="lazy"';
703
+ out += this.options.xhtml ? '/>' : '>';
704
+ return out;
695
705
  }
696
- out += ' loading="lazy"';
697
- out += this.options.xhtml ? '/>' : '>';
698
- return out;
699
706
  };
700
707
  renderer.listitem = function (text) {
701
708
  const m = /^\s*\[( |x)\]/i.exec(text);
package/built/pxt.js CHANGED
@@ -106384,13 +106384,20 @@ var pxt;
106384
106384
  docs.prepTemplate = prepTemplate;
106385
106385
  function setupRenderer(renderer) {
106386
106386
  renderer.image = function (href, title, text) {
106387
- let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
106388
- if (title) {
106389
- out += ' title="' + title + '"';
106387
+ if (href.startsWith("youtube:")) {
106388
+ let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
106389
+ + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
106390
+ return out;
106391
+ }
106392
+ else {
106393
+ let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
106394
+ if (title) {
106395
+ out += ' title="' + title + '"';
106396
+ }
106397
+ out += ' loading="lazy"';
106398
+ out += this.options.xhtml ? '/>' : '>';
106399
+ return out;
106390
106400
  }
106391
- out += ' loading="lazy"';
106392
- out += this.options.xhtml ? '/>' : '>';
106393
- return out;
106394
106401
  };
106395
106402
  renderer.listitem = function (text) {
106396
106403
  const m = /^\s*\[( |x)\]/i.exec(text);
@@ -115688,7 +115695,7 @@ var pxt;
115688
115695
  id,
115689
115696
  type: "tilemap" /* Tilemap */,
115690
115697
  meta: {
115691
- displayName: id
115698
+ displayName: name || id
115692
115699
  },
115693
115700
  data: data
115694
115701
  });
@@ -139471,6 +139478,7 @@ var ts;
139471
139478
  let snippet;
139472
139479
  if (preDefinedSnippet) {
139473
139480
  snippet = [preDefinedSnippet];
139481
+ snippetPrefix = undefined;
139474
139482
  }
139475
139483
  else {
139476
139484
  snippet = [fnName];
@@ -153186,6 +153194,8 @@ var pxsim;
153186
153194
  frame.frameBorder = "0";
153187
153195
  frame.dataset['runid'] = this.runId;
153188
153196
  frame.dataset['origin'] = new URL(furl).origin || "*";
153197
+ if (this._runOptions.autofocus)
153198
+ frame.setAttribute("autofocus", "true");
153189
153199
  wrapper.appendChild(frame);
153190
153200
  const i = document.createElement("i");
153191
153201
  i.className = "videoplay xicon icon";
@@ -153439,11 +153449,14 @@ var pxsim;
153439
153449
  return true;
153440
153450
  }
153441
153451
  handleMessage(msg, source) {
153452
+ var _a;
153442
153453
  switch (msg.type || '') {
153443
153454
  case 'ready': {
153444
153455
  const frameid = msg.frameid;
153445
153456
  const frame = document.getElementById(frameid);
153446
153457
  if (frame) {
153458
+ if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.autofocus)
153459
+ frame.focus();
153447
153460
  this.startFrame(frame);
153448
153461
  if (this.options.revealElement)
153449
153462
  this.options.revealElement(frame);
@@ -15502,6 +15502,8 @@ var pxtblockly;
15502
15502
  getScaledBBox: () => bbox
15503
15503
  };
15504
15504
  Blockly.WidgetDiv.show(widgetOwner, this.sourceBlock_.RTL, () => {
15505
+ if (document.activeElement && document.activeElement.tagName === "INPUT")
15506
+ document.activeElement.blur();
15505
15507
  fv.hide();
15506
15508
  widgetDiv.classList.remove("sound-effect-editor-widget");
15507
15509
  widgetDiv.style.transform = "";
@@ -11940,6 +11940,8 @@ var pxtblockly;
11940
11940
  getScaledBBox: () => bbox
11941
11941
  };
11942
11942
  Blockly.WidgetDiv.show(widgetOwner, this.sourceBlock_.RTL, () => {
11943
+ if (document.activeElement && document.activeElement.tagName === "INPUT")
11944
+ document.activeElement.blur();
11943
11945
  fv.hide();
11944
11946
  widgetDiv.classList.remove("sound-effect-editor-widget");
11945
11947
  widgetDiv.style.transform = "";
@@ -18441,6 +18441,7 @@ var ts;
18441
18441
  let snippet;
18442
18442
  if (preDefinedSnippet) {
18443
18443
  snippet = [preDefinedSnippet];
18444
+ snippetPrefix = undefined;
18444
18445
  }
18445
18446
  else {
18446
18447
  snippet = [fnName];
@@ -1045,6 +1045,7 @@ declare namespace pxt.editor {
1045
1045
  isRegex: boolean;
1046
1046
  matchWholeWord: boolean;
1047
1047
  matchCase: boolean;
1048
+ validateRange?: (range: monaco.Range, model: monaco.editor.ITextModel) => monaco.Range;
1048
1049
  }
1049
1050
  function registerMonacoFieldEditor(name: string, definition: MonacoFieldEditorDefinition): void;
1050
1051
  function getMonacoFieldEditor(name: string): MonacoFieldEditorDefinition;
@@ -1068,6 +1069,16 @@ declare namespace pxt.editor {
1068
1069
  protected getOptions(): any;
1069
1070
  }
1070
1071
  }
1072
+ declare namespace pxt.editor {
1073
+ class MonacoSoundEffectEditor extends MonacoReactFieldEditor<pxt.assets.Sound> {
1074
+ protected value: pxt.assets.Sound;
1075
+ protected textToValue(text: string): pxt.assets.Sound;
1076
+ protected resultToText(result: pxt.assets.Sound): string;
1077
+ protected getFieldEditorId(): string;
1078
+ protected getOptions(): any;
1079
+ }
1080
+ const soundEditorDefinition: MonacoFieldEditorDefinition;
1081
+ }
1071
1082
  declare namespace pxt.editor {
1072
1083
  class MonacoSpriteEditor extends MonacoReactFieldEditor<pxt.ProjectImage> {
1073
1084
  protected isPython: boolean;
@@ -930,6 +930,203 @@ var pxt;
930
930
  /// <reference path="./monacoFieldEditor.ts" />
931
931
  /// <reference path="./field_react.ts" />
932
932
  var pxt;
933
+ (function (pxt) {
934
+ var editor;
935
+ (function (editor) {
936
+ const fieldEditorId = "soundeffect-editor";
937
+ // music.createSoundEffect(WaveShape.Sine, 5000, 0, 255, 0, 500, SoundExpressionEffect.None, InterpolationCurve.Linear
938
+ class MonacoSoundEffectEditor extends editor.MonacoReactFieldEditor {
939
+ textToValue(text) {
940
+ const out = defaultSound();
941
+ this.value = out;
942
+ const argMatch = /\(([^)]*)\)/.exec(text);
943
+ const args = argMatch[1].split(",").map(a => a.replace(/\s/g, ""));
944
+ if (args.length !== 8)
945
+ return out;
946
+ switch (args[0]) {
947
+ case "WaveShape.Sawtooth":
948
+ out.wave = "sawtooth";
949
+ break;
950
+ case "WaveShape.Square":
951
+ out.wave = "square";
952
+ break;
953
+ case "WaveShape.Noise":
954
+ out.wave = "noise";
955
+ break;
956
+ case "WaveShape.Triangle":
957
+ out.wave = "triangle";
958
+ break;
959
+ case "WaveShape.Sine":
960
+ default:
961
+ out.wave = "sine";
962
+ break;
963
+ }
964
+ const withDefault = (val, def) => {
965
+ return isNaN(val) ? def : val;
966
+ };
967
+ out.startFrequency = withDefault(parseInt(args[1]), out.startFrequency);
968
+ out.endFrequency = withDefault(parseInt(args[2]), out.endFrequency);
969
+ out.startVolume = withDefault(parseInt(args[3]), out.startVolume);
970
+ out.endVolume = withDefault(parseInt(args[4]), out.endVolume);
971
+ out.duration = withDefault(parseInt(args[5]), out.duration);
972
+ switch (args[6]) {
973
+ case "SoundExpressionEffect.Vibrato":
974
+ out.effect = "vibrato";
975
+ break;
976
+ case "SoundExpressionEffect.Tremolo":
977
+ out.effect = "tremolo";
978
+ break;
979
+ case "SoundExpressionEffect.Warble":
980
+ out.effect = "warble";
981
+ break;
982
+ case "SoundExpressionEffect.None":
983
+ default:
984
+ out.effect = "none";
985
+ break;
986
+ }
987
+ switch (args[7]) {
988
+ case "InterpolationCurve.Logarithmic":
989
+ out.interpolation = "logarithmic";
990
+ break;
991
+ case "InterpolationCurve.Curve":
992
+ out.interpolation = "curve";
993
+ break;
994
+ case "InterpolationCurve.Linear":
995
+ default:
996
+ out.interpolation = "linear";
997
+ break;
998
+ }
999
+ return out;
1000
+ }
1001
+ resultToText(result) {
1002
+ result = this.value;
1003
+ let waveShape;
1004
+ switch (result.wave) {
1005
+ case "sine":
1006
+ waveShape = "WaveShape.Sine";
1007
+ break;
1008
+ case "square":
1009
+ waveShape = "WaveShape.Square";
1010
+ break;
1011
+ case "triangle":
1012
+ waveShape = "WaveShape.Triangle";
1013
+ break;
1014
+ case "noise":
1015
+ waveShape = "WaveShape.Noise";
1016
+ break;
1017
+ case "sawtooth":
1018
+ waveShape = "WaveShape.Sawtooth";
1019
+ break;
1020
+ }
1021
+ let effect;
1022
+ switch (result.effect) {
1023
+ case "vibrato":
1024
+ effect = "SoundExpressionEffect.Vibrato";
1025
+ break;
1026
+ case "tremolo":
1027
+ effect = "SoundExpressionEffect.Tremolo";
1028
+ break;
1029
+ case "warble":
1030
+ effect = "SoundExpressionEffect.Warble";
1031
+ break;
1032
+ case "none":
1033
+ effect = "SoundExpressionEffect.None";
1034
+ break;
1035
+ }
1036
+ let interpolation;
1037
+ switch (result.interpolation) {
1038
+ case "curve":
1039
+ interpolation = "InterpolationCurve.Curve";
1040
+ break;
1041
+ case "linear":
1042
+ interpolation = "InterpolationCurve.Linear";
1043
+ break;
1044
+ case "logarithmic":
1045
+ interpolation = "InterpolationCurve.Logarithmic";
1046
+ break;
1047
+ }
1048
+ return `music.createSoundEffect(${waveShape}, ${Math.round(result.startFrequency)}, ${Math.round(result.endFrequency)}, ${Math.round(result.startVolume)}, ${Math.round(result.endVolume)}, ${Math.round(result.duration)}, ${effect}, ${interpolation})`;
1049
+ }
1050
+ getFieldEditorId() {
1051
+ return fieldEditorId;
1052
+ }
1053
+ getOptions() {
1054
+ return {
1055
+ onClose: () => this.fv.hide(),
1056
+ onSoundChange: (newValue) => this.value = newValue,
1057
+ initialSound: this.value,
1058
+ useFlex: true
1059
+ };
1060
+ }
1061
+ }
1062
+ editor.MonacoSoundEffectEditor = MonacoSoundEffectEditor;
1063
+ function validateRange(range, model) {
1064
+ let currentLine = range.startLineNumber;
1065
+ let currentColumn = 0;
1066
+ let foundStart = false;
1067
+ let parenCount = 0;
1068
+ const methodName = "createSoundEffect";
1069
+ const totalLines = model.getLineCount();
1070
+ while (currentLine < totalLines) {
1071
+ const lineContent = model.getLineContent(currentLine);
1072
+ const startIndex = lineContent.indexOf(methodName);
1073
+ if (startIndex !== -1) {
1074
+ foundStart = true;
1075
+ currentColumn = startIndex + methodName.length;
1076
+ }
1077
+ if (foundStart) {
1078
+ while (currentColumn < lineContent.length) {
1079
+ const currentChar = lineContent.charAt(currentColumn);
1080
+ if (currentChar === "(") {
1081
+ parenCount++;
1082
+ }
1083
+ else if (currentChar === ")") {
1084
+ parenCount--;
1085
+ if (parenCount === 0) {
1086
+ return new monaco.Range(range.startLineNumber, range.startColumn, currentLine, currentColumn + model.getLineMinColumn(currentLine) + 1);
1087
+ }
1088
+ }
1089
+ currentColumn++;
1090
+ }
1091
+ }
1092
+ currentColumn = 0;
1093
+ currentLine++;
1094
+ }
1095
+ return undefined;
1096
+ }
1097
+ function defaultSound() {
1098
+ return {
1099
+ wave: "sine",
1100
+ startFrequency: 5000,
1101
+ endFrequency: 0,
1102
+ startVolume: 255,
1103
+ endVolume: 0,
1104
+ duration: 500,
1105
+ effect: "none",
1106
+ interpolation: "linear"
1107
+ };
1108
+ }
1109
+ editor.soundEditorDefinition = {
1110
+ id: fieldEditorId,
1111
+ foldMatches: true,
1112
+ glyphCssClass: "fas fa-music sprite-focus-hover",
1113
+ heightInPixels: 510,
1114
+ matcher: {
1115
+ // match both JS and python
1116
+ searchString: "music\\s*\\.\\s*createSoundEffect\\s*\\(",
1117
+ isRegex: true,
1118
+ matchCase: true,
1119
+ matchWholeWord: false,
1120
+ validateRange
1121
+ },
1122
+ proto: MonacoSoundEffectEditor
1123
+ };
1124
+ editor.registerMonacoFieldEditor(fieldEditorId, editor.soundEditorDefinition);
1125
+ })(editor = pxt.editor || (pxt.editor = {}));
1126
+ })(pxt || (pxt = {}));
1127
+ /// <reference path="./monacoFieldEditor.ts" />
1128
+ /// <reference path="./field_react.ts" />
1129
+ var pxt;
933
1130
  (function (pxt) {
934
1131
  var editor;
935
1132
  (function (editor) {
@@ -1048,8 +1245,8 @@ var pxt;
1048
1245
  let proj;
1049
1246
  let id;
1050
1247
  if (name) {
1051
- let id = ts.pxtc.escapeIdentifier(name);
1052
- proj = project.getTilemap(id);
1248
+ id = ts.pxtc.escapeIdentifier(name);
1249
+ proj = project.getTilemap(id) || project.lookupAssetByName("tilemap" /* Tilemap */, name);
1053
1250
  }
1054
1251
  if (!proj) {
1055
1252
  let tileWidth = 16;
package/built/pxtlib.js CHANGED
@@ -8698,13 +8698,20 @@ var pxt;
8698
8698
  docs.prepTemplate = prepTemplate;
8699
8699
  function setupRenderer(renderer) {
8700
8700
  renderer.image = function (href, title, text) {
8701
- let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
8702
- if (title) {
8703
- out += ' title="' + title + '"';
8701
+ if (href.startsWith("youtube:")) {
8702
+ let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
8703
+ + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
8704
+ return out;
8705
+ }
8706
+ else {
8707
+ let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
8708
+ if (title) {
8709
+ out += ' title="' + title + '"';
8710
+ }
8711
+ out += ' loading="lazy"';
8712
+ out += this.options.xhtml ? '/>' : '>';
8713
+ return out;
8704
8714
  }
8705
- out += ' loading="lazy"';
8706
- out += this.options.xhtml ? '/>' : '>';
8707
- return out;
8708
8715
  };
8709
8716
  renderer.listitem = function (text) {
8710
8717
  const m = /^\s*\[( |x)\]/i.exec(text);
@@ -18002,7 +18009,7 @@ var pxt;
18002
18009
  id,
18003
18010
  type: "tilemap" /* Tilemap */,
18004
18011
  meta: {
18005
- displayName: id
18012
+ displayName: name || id
18006
18013
  },
18007
18014
  data: data
18008
18015
  });
@@ -97,6 +97,7 @@ declare namespace pxt.runner {
97
97
  dependencies?: string[];
98
98
  builtJsInfo?: pxtc.BuiltSimJsInfo;
99
99
  single?: boolean;
100
+ autofocus?: boolean;
100
101
  }
101
102
  let mainPkg: pxt.MainPackage;
102
103
  function initFooter(footer: HTMLElement, shareId?: string): void;
@@ -1749,7 +1749,8 @@ var pxt;
1749
1749
  highContrast: simOptions.highContrast,
1750
1750
  storedState: storedState,
1751
1751
  light: simOptions.light,
1752
- single: simOptions.single
1752
+ single: simOptions.single,
1753
+ autofocus: simOptions.autofocus
1753
1754
  };
1754
1755
  if (pxt.appTarget.simulator && !simOptions.fullScreen)
1755
1756
  runOptions.aspectRatio = parts.length && pxt.appTarget.simulator.partsAspectRatio
package/built/pxtsim.d.ts CHANGED
@@ -1268,6 +1268,7 @@ declare namespace pxsim {
1268
1268
  ipc?: boolean;
1269
1269
  dependencies?: Map<string>;
1270
1270
  single?: boolean;
1271
+ autofocus?: boolean;
1271
1272
  }
1272
1273
  interface HwDebugger {
1273
1274
  postMessage: (msg: pxsim.SimulatorMessage) => void;
package/built/pxtsim.js CHANGED
@@ -6309,6 +6309,8 @@ var pxsim;
6309
6309
  frame.frameBorder = "0";
6310
6310
  frame.dataset['runid'] = this.runId;
6311
6311
  frame.dataset['origin'] = new URL(furl).origin || "*";
6312
+ if (this._runOptions.autofocus)
6313
+ frame.setAttribute("autofocus", "true");
6312
6314
  wrapper.appendChild(frame);
6313
6315
  const i = document.createElement("i");
6314
6316
  i.className = "videoplay xicon icon";
@@ -6562,11 +6564,14 @@ var pxsim;
6562
6564
  return true;
6563
6565
  }
6564
6566
  handleMessage(msg, source) {
6567
+ var _a;
6565
6568
  switch (msg.type || '') {
6566
6569
  case 'ready': {
6567
6570
  const frameid = msg.frameid;
6568
6571
  const frame = document.getElementById(frameid);
6569
6572
  if (frame) {
6573
+ if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.autofocus)
6574
+ frame.focus();
6570
6575
  this.startFrame(frame);
6571
6576
  if (this.options.revealElement)
6572
6577
  this.options.revealElement(frame);
package/built/server.js CHANGED
@@ -1026,7 +1026,7 @@ function serveAsync(options) {
1026
1026
  return;
1027
1027
  }
1028
1028
  let publicDir = path.join(nodeutil.pxtCoreDir, "webapp/public");
1029
- if (pathname == "/--embed") {
1029
+ if (pathname == "/--embed" || pathname === "/---embed") {
1030
1030
  sendFile(path.join(publicDir, 'embed.js'));
1031
1031
  return;
1032
1032
  }