pxt-core 7.4.10 → 7.4.14

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 (61) hide show
  1. package/built/cli.js +109 -83
  2. package/built/pxt.js +123 -97
  3. package/built/pxtblockly.js +151 -61
  4. package/built/pxtblocks.d.ts +7 -0
  5. package/built/pxtblocks.js +91 -58
  6. package/built/pxtlib.js +14 -14
  7. package/built/target.js +1 -1
  8. package/built/web/blockly.css +1 -1
  9. package/built/web/main.js +1 -1
  10. package/built/web/pxtapp.js +1 -1
  11. package/built/web/pxtasseteditor.js +1 -1
  12. package/built/web/pxtblockly.js +53 -1
  13. package/built/web/pxtblocks.js +1 -1
  14. package/built/web/pxtembed.js +53 -1
  15. package/built/web/pxtlib.js +1 -1
  16. package/built/web/pxtworker.js +1 -1
  17. package/built/web/react-common-skillmap.css +13 -0
  18. package/built/web/rtlblockly.css +1 -1
  19. package/built/web/rtlreact-common-skillmap.css +13 -0
  20. package/built/web/rtlsemantic.css +14 -2
  21. package/built/web/semantic.css +14 -2
  22. package/built/web/skillmap/css/main.369ecead.chunk.css +1 -0
  23. package/built/web/skillmap/js/2.dc66e964.chunk.js +2 -0
  24. package/built/web/skillmap/js/main.e89a1af7.chunk.js +1 -0
  25. package/docfiles/tracking.html +1 -1
  26. package/localtypings/pxtarget.d.ts +1 -0
  27. package/localtypings/pxtblockly.d.ts +37 -0
  28. package/package.json +7 -3
  29. package/react-common/components/Checkbox.tsx +25 -0
  30. package/react-common/components/Notification.tsx +82 -0
  31. package/react-common/components/controls/Button.tsx +62 -0
  32. package/react-common/components/controls/List.tsx +29 -0
  33. package/react-common/components/profile/Badge.tsx +33 -0
  34. package/react-common/components/profile/BadgeInfo.tsx +74 -0
  35. package/react-common/components/profile/BadgeList.tsx +67 -0
  36. package/react-common/components/profile/Profile.tsx +42 -0
  37. package/react-common/components/profile/UserNotification.tsx +32 -0
  38. package/react-common/components/profile/UserPane.tsx +64 -0
  39. package/react-common/components/types.d.ts +29 -0
  40. package/react-common/components/util.tsx +52 -0
  41. package/react-common/styles/controls/Button.less +157 -0
  42. package/react-common/styles/controls/Icon.less +11 -0
  43. package/react-common/styles/controls/List.less +12 -0
  44. package/{built/web/react-common.css → react-common/styles/profile/profile.less} +1 -0
  45. package/react-common/styles/react-common-skillmap-core.less +10 -0
  46. package/react-common/styles/react-common-skillmap.less +12 -0
  47. package/react-common/styles/react-common-variables.less +12 -0
  48. package/react-common/styles/react-common.less +8 -0
  49. package/react-common/tsconfig.json +36 -0
  50. package/theme/blockly-core.less +16 -0
  51. package/theme/common-components.less +7 -0
  52. package/theme/common.less +1 -1
  53. package/theme/highcontrast.less +4 -0
  54. package/theme/pxt.less +2 -0
  55. package/theme/tutorial-sidebar.less +64 -6
  56. package/webapp/public/blockly/blockly_compressed.js +3 -3
  57. package/webapp/public/blockly/plugins.js +57 -0
  58. package/webapp/public/skillmap.html +3 -3
  59. package/built/web/skillmap/css/main.96b1b3f1.chunk.css +0 -1
  60. package/built/web/skillmap/js/2.7dd06a3a.chunk.js +0 -2
  61. package/built/web/skillmap/js/main.d5bb4f6b.chunk.js +0 -1
package/built/cli.js CHANGED
@@ -1728,94 +1728,120 @@ ${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')}
1728
1728
  nodeutil.writeFileSync("built/target-strings.json", nodeutil.stringify(targetStringsSorted));
1729
1729
  pxt.log(`target-strings.json built`);
1730
1730
  }
1731
- function buildSemanticUIAsync(parsed) {
1732
- const forceRedbuild = parsed && parsed.flags["force"] || false;
1733
- if (!fs.existsSync(path.join("theme", "style.less")) ||
1734
- !fs.existsSync(path.join("theme", "theme.config")))
1735
- return Promise.resolve();
1736
- let dirty = !fs.existsSync("built/web/semantic.css");
1737
- if (!dirty) {
1738
- const csstime = fs.statSync("built/web/semantic.css").mtime;
1739
- dirty = nodeutil.allFiles("theme")
1740
- .map(f => fs.statSync(f))
1741
- .some(stat => stat.mtime > csstime);
1742
- }
1743
- if (!dirty && !forceRedbuild)
1744
- return Promise.resolve();
1745
- let pkg = readJson("package.json");
1731
+ async function buildSemanticUIAsync(parsed) {
1732
+ if (!fs.existsSync(path.join("theme", "style.less")) || !fs.existsSync(path.join("theme", "theme.config"))) {
1733
+ return;
1734
+ }
1735
+ const pkg = readJson("package.json");
1736
+ const isPxtCore = pkg["name"] === "pxt-core";
1746
1737
  nodeutil.mkdirP(path.join("built", "web"));
1747
1738
  const lessPath = require.resolve('less');
1748
1739
  const lessCPath = path.join(path.dirname(lessPath), '/bin/lessc');
1749
- return nodeutil.spawnAsync({
1740
+ const lessIncludePaths = [
1741
+ "node_modules/semantic-ui-less",
1742
+ "node_modules/pxt-core/theme",
1743
+ "theme/foo/bar",
1744
+ "theme",
1745
+ "node_modules/pxt-core/react-common/styles",
1746
+ "react-common/styles",
1747
+ "node_modules/@fortawesome",
1748
+ "node_modules/pxt-core/node_modules/@fortawesome" // for locally linked dev environment
1749
+ ].join(":");
1750
+ // Build semantic css
1751
+ await nodeutil.spawnAsync({
1750
1752
  cmd: "node",
1751
- args: [lessCPath, "theme/style.less", "built/web/semantic.css", "--include-path=node_modules/semantic-ui-less:node_modules/pxt-core/theme:theme/foo/bar"]
1752
- }).then(() => {
1753
- function linkFont(font, semCss) {
1754
- const fontFile = fs.readFileSync("node_modules/semantic-ui-less/themes/default/assets/fonts/" + font + ".woff");
1755
- const url = "url(data:application/font-woff;charset=utf-8;base64,"
1756
- + fontFile.toString("base64") + ") format('woff')";
1757
- const r = new RegExp(`src:.*url\\("fonts\/${font}\\.woff.*`, "g");
1758
- semCss = semCss.replace('src: url("fonts/' + font + '.eot");', "")
1759
- .replace(r, "src: " + url + ";");
1760
- return semCss;
1761
- }
1762
- let semCss = fs.readFileSync('built/web/semantic.css', "utf8");
1763
- semCss = linkFont("icons", semCss);
1764
- semCss = linkFont("outline-icons", semCss);
1765
- semCss = linkFont("brand-icons", semCss);
1766
- return semCss;
1767
- }).then((semCss) => {
1768
- // Append icons.css to semantic.css (custom pxt icons)
1769
- const iconsFile = (pkg["name"] == "pxt-core") ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
1770
- const iconsCss = fs.readFileSync(iconsFile, "utf-8");
1771
- const reactCommonFile = (pkg["name"] == "pxt-core") ? 'built/web/react-common.css' : 'node_modules/pxt-core/built/web/react-common.css';
1772
- const reactCommonCss = fs.readFileSync(reactCommonFile, "utf-8");
1773
- semCss = semCss + "\n" + iconsCss + "\n" + reactCommonCss;
1774
- nodeutil.writeFileSync('built/web/semantic.css', semCss);
1775
- }).then(() => {
1776
- // generate blockly css
1777
- if (!fs.existsSync(path.join("theme", "blockly.less")))
1778
- return Promise.resolve();
1779
- return nodeutil.spawnAsync({
1753
+ args: [
1754
+ lessCPath,
1755
+ "theme/style.less",
1756
+ "built/web/semantic.css",
1757
+ "--include-path=" + lessIncludePaths
1758
+ ]
1759
+ });
1760
+ // Inline all of our icon fonts
1761
+ let semCss = await readFileAsync('built/web/semantic.css', "utf8");
1762
+ semCss = await linkFontAsync("icons", semCss);
1763
+ semCss = await linkFontAsync("outline-icons", semCss);
1764
+ semCss = await linkFontAsync("brand-icons", semCss);
1765
+ // Append icons.css to semantic.css (custom pxt icons)
1766
+ const iconsFile = isPxtCore ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
1767
+ const iconsCss = await readFileAsync(iconsFile, "utf8");
1768
+ semCss = semCss + "\n" + iconsCss;
1769
+ nodeutil.writeFileSync('built/web/semantic.css', semCss);
1770
+ // Generate blockly css
1771
+ if (fs.existsSync(path.join("theme", "blockly.less"))) {
1772
+ await nodeutil.spawnAsync({
1780
1773
  cmd: "node",
1781
- args: [lessCPath, "theme/blockly.less", "built/web/blockly.css", "--include-path=node_modules/semantic-ui-less:node_modules/pxt-core/theme:theme/foo/bar"]
1782
- });
1783
- }).then(() => {
1784
- // run postcss with autoprefixer and rtlcss
1785
- pxt.debug("running postcss");
1786
- const postcss = require('postcss');
1787
- const browserList = [
1788
- "Chrome >= 38",
1789
- "Firefox >= 31",
1790
- "Edge >= 12",
1791
- "ie >= 11",
1792
- "Safari >= 9",
1793
- "Opera >= 21",
1794
- "iOS >= 9",
1795
- "ChromeAndroid >= 59",
1796
- "FirefoxAndroid >= 55"
1797
- ];
1798
- const cssnano = require('cssnano')({
1799
- zindex: false,
1800
- autoprefixer: { browsers: browserList, add: true }
1801
- });
1802
- const rtlcss = require('rtlcss');
1803
- const files = ['semantic.css', 'blockly.css'];
1804
- files.forEach(cssFile => {
1805
- fs.readFile(`built/web/${cssFile}`, "utf8", (err, css) => {
1806
- postcss([cssnano])
1807
- .process(css, { from: `built/web/${cssFile}`, to: `built/web/${cssFile}` }).then((result) => {
1808
- fs.writeFile(`built/web/${cssFile}`, result.css, (err2) => {
1809
- // process rtl css
1810
- postcss([rtlcss])
1811
- .process(result.css, { from: `built/web/${cssFile}`, to: `built/web/rtl${cssFile}` }).then((result2) => {
1812
- nodeutil.writeFileSync(`built/web/rtl${cssFile}`, result2.css, { encoding: "utf8" });
1813
- });
1814
- });
1815
- });
1816
- });
1774
+ args: [
1775
+ lessCPath,
1776
+ "theme/blockly.less",
1777
+ "built/web/blockly.css",
1778
+ "--include-path=" + lessIncludePaths
1779
+ ]
1817
1780
  });
1781
+ }
1782
+ // Generate react-common css for skillmap
1783
+ const skillmapFile = isPxtCore ? "react-common/styles/react-common-skillmap-core.less" :
1784
+ "node_modules/pxt-core/react-common/styles/react-common-skillmap.less";
1785
+ await nodeutil.spawnAsync({
1786
+ cmd: "node",
1787
+ args: [
1788
+ lessCPath,
1789
+ skillmapFile,
1790
+ "built/web/react-common-skillmap.css",
1791
+ "--include-path=" + lessIncludePaths
1792
+ ]
1793
+ });
1794
+ let fontAwesomeSource = "node_modules/@fortawesome/fontawesome-free/webfonts/";
1795
+ if (!fs.existsSync(fontAwesomeSource)) {
1796
+ fontAwesomeSource = "node_modules/pxt-core/" + fontAwesomeSource;
1797
+ }
1798
+ let skillmapCss = await readFileAsync(`built/web/react-common-skillmap.css`, "utf8");
1799
+ skillmapCss = await linkFontAsync("fa-solid-900", skillmapCss, fontAwesomeSource, "\\.\\.\\/webfonts\\/");
1800
+ skillmapCss = await linkFontAsync("fa-regular-400", skillmapCss, fontAwesomeSource, "\\.\\.\\/webfonts\\/");
1801
+ await writeFileAsync(`built/web/react-common-skillmap.css`, skillmapCss, "utf8");
1802
+ // Run postcss with autoprefixer and rtlcss
1803
+ pxt.debug("running postcss");
1804
+ const postcss = require('postcss');
1805
+ const browserList = [
1806
+ "Chrome >= 38",
1807
+ "Firefox >= 31",
1808
+ "Edge >= 12",
1809
+ "ie >= 11",
1810
+ "Safari >= 9",
1811
+ "Opera >= 21",
1812
+ "iOS >= 9",
1813
+ "ChromeAndroid >= 59",
1814
+ "FirefoxAndroid >= 55"
1815
+ ];
1816
+ const cssnano = require("cssnano")({
1817
+ zindex: false,
1818
+ autoprefixer: { browsers: browserList, add: true }
1818
1819
  });
1820
+ const rtlcss = require("rtlcss");
1821
+ const files = ["semantic.css", "blockly.css", "react-common-skillmap.css"];
1822
+ for (const cssFile of files) {
1823
+ const css = await readFileAsync(`built/web/${cssFile}`, "utf8");
1824
+ const processed = await postcss([cssnano])
1825
+ .process(css, { from: `built/web/${cssFile}`, to: `built/web/${cssFile}` });
1826
+ await writeFileAsync(`built/web/${cssFile}`, processed.css);
1827
+ const processedRtl = await postcss([rtlcss])
1828
+ .process(processed.css, { from: `built/web/${cssFile}`, to: `built/web/rtl${cssFile}` });
1829
+ await writeFileAsync(`built/web/rtl${cssFile}`, processedRtl.css, "utf8");
1830
+ }
1831
+ if (!isPxtCore) {
1832
+ // This is just to support the local skillmap serve for development
1833
+ nodeutil.cp("built/web/react-common-skillmap.css", "node_modules/pxt-core/skillmap/public/blb");
1834
+ }
1835
+ }
1836
+ async function linkFontAsync(font, semCss, sourceDir = "node_modules/semantic-ui-less/themes/default/assets/fonts/", refDir = "fonts\\/") {
1837
+ const fontFile = await readFileAsync(sourceDir + font + ".woff");
1838
+ const url = "url(data:application/font-woff;charset=utf-8;base64,"
1839
+ + fontFile.toString("base64") + ") format('woff')";
1840
+ const r = new RegExp(`src:.*url\\((?:"|')${refDir + font}\\.woff.*`, "g");
1841
+ semCss = semCss.replace('src: url("' + refDir + font + '.eot");', "")
1842
+ .replace('src: url(' + refDir + font + '.eot);', "")
1843
+ .replace(r, "src: " + url + ";");
1844
+ return semCss;
1819
1845
  }
1820
1846
  function buildWebStringsAsync() {
1821
1847
  if (pxt.appTarget.id != "core")
@@ -1838,7 +1864,7 @@ function buildSkillMapAsync(parsed) {
1838
1864
  nodeutil.cp("node_modules/pxt-core/built/pxtlib.js", `${skillmapRoot}/public/blb`);
1839
1865
  nodeutil.cp("built/web/semantic.css", `${skillmapRoot}/public/blb`);
1840
1866
  nodeutil.cp("node_modules/pxt-core/built/web/icons.css", `${skillmapRoot}/public/blb`);
1841
- nodeutil.cp("node_modules/pxt-core/built/web/react-common.css", `${skillmapRoot}/public/blb`);
1867
+ nodeutil.cp("node_modules/pxt-core/built/web/react-common-skillmap.css", `${skillmapRoot}/public/blb`);
1842
1868
  // copy 'assets' over from docs/static
1843
1869
  nodeutil.cpR("docs/static/skillmap/assets", `${skillmapRoot}/public/assets`);
1844
1870
  if (docsPath) {
@@ -6196,7 +6222,7 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
6196
6222
  help: "build required css files",
6197
6223
  flags: {
6198
6224
  force: {
6199
- description: "force re-compile of less files"
6225
+ description: "deprecated; now on by default"
6200
6226
  }
6201
6227
  }
6202
6228
  }, buildSemanticUIAsync);
package/built/pxt.js CHANGED
@@ -98123,7 +98123,7 @@ var pxt;
98123
98123
  return { success: false, res: undefined };
98124
98124
  }
98125
98125
  // Apply queued patches to the remote state in isolation and develop a final diff to send to the backend
98126
- const remotePrefs = pxt.U.deepCopy(getResult.resp);
98126
+ const remotePrefs = pxt.U.deepCopy(getResult.resp) || auth.DEFAULT_USER_PREFERENCES();
98127
98127
  const patchQueue = this.patchQueue;
98128
98128
  this.patchQueue = []; // Reset the queue
98129
98129
  patchQueue.forEach(patch => {
@@ -101667,7 +101667,7 @@ var pxt;
101667
101667
  'pxt_controls_for': {
101668
101668
  name: pxt.Util.lf("a loop that repeats the number of times you say"),
101669
101669
  tooltip: pxt.Util.lf("Have the variable '{0}' take on the values from 0 to the end number, counting by 1, and do the specified blocks."),
101670
- url: 'blocks/loops/for',
101670
+ url: '/blocks/loops/for',
101671
101671
  category: 'loops',
101672
101672
  block: {
101673
101673
  message0: pxt.Util.lf("for %1 from 0 to %2"),
@@ -101678,7 +101678,7 @@ var pxt;
101678
101678
  'controls_simple_for': {
101679
101679
  name: pxt.Util.lf("a loop that repeats the number of times you say"),
101680
101680
  tooltip: pxt.Util.lf("Have the variable '{0}' take on the values from 0 to the end number, counting by 1, and do the specified blocks."),
101681
- url: 'blocks/loops/for',
101681
+ url: '/blocks/loops/for',
101682
101682
  category: 'loops',
101683
101683
  block: {
101684
101684
  message0: pxt.Util.lf("for %1 from 0 to %2"),
@@ -101689,7 +101689,7 @@ var pxt;
101689
101689
  'pxt_controls_for_of': {
101690
101690
  name: pxt.Util.lf("a loop that repeats for each value in an array"),
101691
101691
  tooltip: pxt.Util.lf("Have the variable '{0}' take the value of each item in the array one by one, and do the specified blocks."),
101692
- url: 'blocks/loops/for-of',
101692
+ url: '/blocks/loops/for-of',
101693
101693
  category: 'loops',
101694
101694
  block: {
101695
101695
  message0: pxt.Util.lf("for element %1 of %2"),
@@ -101700,7 +101700,7 @@ var pxt;
101700
101700
  'controls_for_of': {
101701
101701
  name: pxt.Util.lf("a loop that repeats for each value in an array"),
101702
101702
  tooltip: pxt.Util.lf("Have the variable '{0}' take the value of each item in the array one by one, and do the specified blocks."),
101703
- url: 'blocks/loops/for-of',
101703
+ url: '/blocks/loops/for-of',
101704
101704
  category: 'loops',
101705
101705
  block: {
101706
101706
  message0: pxt.Util.lf("for element %1 of %2"),
@@ -101985,7 +101985,7 @@ var pxt;
101985
101985
  'text': {
101986
101986
  name: pxt.Util.lf("a piece of text"),
101987
101987
  tooltip: pxt.Util.lf("A letter, word, or line of text."),
101988
- url: 'types/string',
101988
+ url: '/types/string',
101989
101989
  category: 'text',
101990
101990
  block: {
101991
101991
  search: pxt.Util.lf("a piece of text") // Only used for search; this string is not surfaced in the block's text
@@ -101994,7 +101994,7 @@ var pxt;
101994
101994
  'text_length': {
101995
101995
  name: pxt.Util.lf("number of characters in the string"),
101996
101996
  tooltip: pxt.Util.lf("Returns the number of letters (including spaces) in the provided text."),
101997
- url: 'reference/text/length',
101997
+ url: '/reference/text/length',
101998
101998
  category: 'text',
101999
101999
  block: {
102000
102000
  TEXT_LENGTH_TITLE: pxt.Util.lf("length of %1")
@@ -102003,7 +102003,7 @@ var pxt;
102003
102003
  'text_join': {
102004
102004
  name: pxt.Util.lf("join items to create text"),
102005
102005
  tooltip: pxt.Util.lf("Create a piece of text by joining together any number of items."),
102006
- url: 'reference/text/join',
102006
+ url: '/reference/text/join',
102007
102007
  category: 'text',
102008
102008
  block: {
102009
102009
  TEXT_JOIN_TITLE_CREATEWITH: pxt.Util.lf("join")
@@ -102012,7 +102012,7 @@ var pxt;
102012
102012
  'procedures_defnoreturn': {
102013
102013
  name: pxt.Util.lf("define the function"),
102014
102014
  tooltip: pxt.Util.lf("Create a function."),
102015
- url: 'types/function/define',
102015
+ url: '/types/function/define',
102016
102016
  category: 'functions',
102017
102017
  block: {
102018
102018
  PROCEDURES_DEFNORETURN_TITLE: pxt.Util.lf("function"),
@@ -102022,7 +102022,7 @@ var pxt;
102022
102022
  'procedures_callnoreturn': {
102023
102023
  name: pxt.Util.lf("call the function"),
102024
102024
  tooltip: pxt.Util.lf("Call the user-defined function."),
102025
- url: 'types/function/call',
102025
+ url: '/types/function/call',
102026
102026
  category: 'functions',
102027
102027
  block: {
102028
102028
  PROCEDURES_CALLNORETURN_TITLE: pxt.Util.lf("call function")
@@ -102031,7 +102031,7 @@ var pxt;
102031
102031
  'function_return': {
102032
102032
  name: pxt.Util.lf("return a value from within a function"),
102033
102033
  tooltip: pxt.Util.lf("Return a value from within a user-defined function."),
102034
- url: 'types/function/return',
102034
+ url: '/types/function/return',
102035
102035
  category: 'functions',
102036
102036
  block: {
102037
102037
  message_with_value: pxt.Util.lf("return %1"),
@@ -102041,7 +102041,7 @@ var pxt;
102041
102041
  'function_definition': {
102042
102042
  name: pxt.Util.lf("define the function"),
102043
102043
  tooltip: pxt.Util.lf("Create a function."),
102044
- url: 'types/function/define',
102044
+ url: '/types/function/define',
102045
102045
  category: 'functions',
102046
102046
  block: {
102047
102047
  FUNCTIONS_EDIT_OPTION: pxt.Util.lf("Edit Function")
@@ -102050,7 +102050,7 @@ var pxt;
102050
102050
  'function_call': {
102051
102051
  name: pxt.Util.lf("call the function"),
102052
102052
  tooltip: pxt.Util.lf("Call the user-defined function."),
102053
- url: 'types/function/call',
102053
+ url: '/types/function/call',
102054
102054
  category: 'functions',
102055
102055
  block: {
102056
102056
  FUNCTIONS_CALL_TITLE: pxt.Util.lf("call"),
@@ -102060,7 +102060,7 @@ var pxt;
102060
102060
  'function_call_output': {
102061
102061
  name: pxt.Util.lf("call the function with a return value"),
102062
102062
  tooltip: pxt.Util.lf("Call the user-defined function with a return value."),
102063
- url: 'types/function/call',
102063
+ url: '/types/function/call',
102064
102064
  category: 'functions',
102065
102065
  block: {}
102066
102066
  }
@@ -157678,94 +157678,120 @@ ${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')}
157678
157678
  nodeutil.writeFileSync("built/target-strings.json", nodeutil.stringify(targetStringsSorted));
157679
157679
  pxt.log(`target-strings.json built`);
157680
157680
  }
157681
- function buildSemanticUIAsync(parsed) {
157682
- const forceRedbuild = parsed && parsed.flags["force"] || false;
157683
- if (!fs.existsSync(path.join("theme", "style.less")) ||
157684
- !fs.existsSync(path.join("theme", "theme.config")))
157685
- return Promise.resolve();
157686
- let dirty = !fs.existsSync("built/web/semantic.css");
157687
- if (!dirty) {
157688
- const csstime = fs.statSync("built/web/semantic.css").mtime;
157689
- dirty = nodeutil.allFiles("theme")
157690
- .map(f => fs.statSync(f))
157691
- .some(stat => stat.mtime > csstime);
157692
- }
157693
- if (!dirty && !forceRedbuild)
157694
- return Promise.resolve();
157695
- let pkg = readJson("package.json");
157681
+ async function buildSemanticUIAsync(parsed) {
157682
+ if (!fs.existsSync(path.join("theme", "style.less")) || !fs.existsSync(path.join("theme", "theme.config"))) {
157683
+ return;
157684
+ }
157685
+ const pkg = readJson("package.json");
157686
+ const isPxtCore = pkg["name"] === "pxt-core";
157696
157687
  nodeutil.mkdirP(path.join("built", "web"));
157697
157688
  const lessPath = require.resolve('less');
157698
157689
  const lessCPath = path.join(path.dirname(lessPath), '/bin/lessc');
157699
- return nodeutil.spawnAsync({
157690
+ const lessIncludePaths = [
157691
+ "node_modules/semantic-ui-less",
157692
+ "node_modules/pxt-core/theme",
157693
+ "theme/foo/bar",
157694
+ "theme",
157695
+ "node_modules/pxt-core/react-common/styles",
157696
+ "react-common/styles",
157697
+ "node_modules/@fortawesome",
157698
+ "node_modules/pxt-core/node_modules/@fortawesome" // for locally linked dev environment
157699
+ ].join(":");
157700
+ // Build semantic css
157701
+ await nodeutil.spawnAsync({
157700
157702
  cmd: "node",
157701
- args: [lessCPath, "theme/style.less", "built/web/semantic.css", "--include-path=node_modules/semantic-ui-less:node_modules/pxt-core/theme:theme/foo/bar"]
157702
- }).then(() => {
157703
- function linkFont(font, semCss) {
157704
- const fontFile = fs.readFileSync("node_modules/semantic-ui-less/themes/default/assets/fonts/" + font + ".woff");
157705
- const url = "url(data:application/font-woff;charset=utf-8;base64,"
157706
- + fontFile.toString("base64") + ") format('woff')";
157707
- const r = new RegExp(`src:.*url\\("fonts\/${font}\\.woff.*`, "g");
157708
- semCss = semCss.replace('src: url("fonts/' + font + '.eot");', "")
157709
- .replace(r, "src: " + url + ";");
157710
- return semCss;
157711
- }
157712
- let semCss = fs.readFileSync('built/web/semantic.css', "utf8");
157713
- semCss = linkFont("icons", semCss);
157714
- semCss = linkFont("outline-icons", semCss);
157715
- semCss = linkFont("brand-icons", semCss);
157716
- return semCss;
157717
- }).then((semCss) => {
157718
- // Append icons.css to semantic.css (custom pxt icons)
157719
- const iconsFile = (pkg["name"] == "pxt-core") ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
157720
- const iconsCss = fs.readFileSync(iconsFile, "utf-8");
157721
- const reactCommonFile = (pkg["name"] == "pxt-core") ? 'built/web/react-common.css' : 'node_modules/pxt-core/built/web/react-common.css';
157722
- const reactCommonCss = fs.readFileSync(reactCommonFile, "utf-8");
157723
- semCss = semCss + "\n" + iconsCss + "\n" + reactCommonCss;
157724
- nodeutil.writeFileSync('built/web/semantic.css', semCss);
157725
- }).then(() => {
157726
- // generate blockly css
157727
- if (!fs.existsSync(path.join("theme", "blockly.less")))
157728
- return Promise.resolve();
157729
- return nodeutil.spawnAsync({
157703
+ args: [
157704
+ lessCPath,
157705
+ "theme/style.less",
157706
+ "built/web/semantic.css",
157707
+ "--include-path=" + lessIncludePaths
157708
+ ]
157709
+ });
157710
+ // Inline all of our icon fonts
157711
+ let semCss = await readFileAsync('built/web/semantic.css', "utf8");
157712
+ semCss = await linkFontAsync("icons", semCss);
157713
+ semCss = await linkFontAsync("outline-icons", semCss);
157714
+ semCss = await linkFontAsync("brand-icons", semCss);
157715
+ // Append icons.css to semantic.css (custom pxt icons)
157716
+ const iconsFile = isPxtCore ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
157717
+ const iconsCss = await readFileAsync(iconsFile, "utf8");
157718
+ semCss = semCss + "\n" + iconsCss;
157719
+ nodeutil.writeFileSync('built/web/semantic.css', semCss);
157720
+ // Generate blockly css
157721
+ if (fs.existsSync(path.join("theme", "blockly.less"))) {
157722
+ await nodeutil.spawnAsync({
157730
157723
  cmd: "node",
157731
- args: [lessCPath, "theme/blockly.less", "built/web/blockly.css", "--include-path=node_modules/semantic-ui-less:node_modules/pxt-core/theme:theme/foo/bar"]
157732
- });
157733
- }).then(() => {
157734
- // run postcss with autoprefixer and rtlcss
157735
- pxt.debug("running postcss");
157736
- const postcss = require('postcss');
157737
- const browserList = [
157738
- "Chrome >= 38",
157739
- "Firefox >= 31",
157740
- "Edge >= 12",
157741
- "ie >= 11",
157742
- "Safari >= 9",
157743
- "Opera >= 21",
157744
- "iOS >= 9",
157745
- "ChromeAndroid >= 59",
157746
- "FirefoxAndroid >= 55"
157747
- ];
157748
- const cssnano = require('cssnano')({
157749
- zindex: false,
157750
- autoprefixer: { browsers: browserList, add: true }
157751
- });
157752
- const rtlcss = require('rtlcss');
157753
- const files = ['semantic.css', 'blockly.css'];
157754
- files.forEach(cssFile => {
157755
- fs.readFile(`built/web/${cssFile}`, "utf8", (err, css) => {
157756
- postcss([cssnano])
157757
- .process(css, { from: `built/web/${cssFile}`, to: `built/web/${cssFile}` }).then((result) => {
157758
- fs.writeFile(`built/web/${cssFile}`, result.css, (err2) => {
157759
- // process rtl css
157760
- postcss([rtlcss])
157761
- .process(result.css, { from: `built/web/${cssFile}`, to: `built/web/rtl${cssFile}` }).then((result2) => {
157762
- nodeutil.writeFileSync(`built/web/rtl${cssFile}`, result2.css, { encoding: "utf8" });
157763
- });
157764
- });
157765
- });
157766
- });
157724
+ args: [
157725
+ lessCPath,
157726
+ "theme/blockly.less",
157727
+ "built/web/blockly.css",
157728
+ "--include-path=" + lessIncludePaths
157729
+ ]
157767
157730
  });
157731
+ }
157732
+ // Generate react-common css for skillmap
157733
+ const skillmapFile = isPxtCore ? "react-common/styles/react-common-skillmap-core.less" :
157734
+ "node_modules/pxt-core/react-common/styles/react-common-skillmap.less";
157735
+ await nodeutil.spawnAsync({
157736
+ cmd: "node",
157737
+ args: [
157738
+ lessCPath,
157739
+ skillmapFile,
157740
+ "built/web/react-common-skillmap.css",
157741
+ "--include-path=" + lessIncludePaths
157742
+ ]
157743
+ });
157744
+ let fontAwesomeSource = "node_modules/@fortawesome/fontawesome-free/webfonts/";
157745
+ if (!fs.existsSync(fontAwesomeSource)) {
157746
+ fontAwesomeSource = "node_modules/pxt-core/" + fontAwesomeSource;
157747
+ }
157748
+ let skillmapCss = await readFileAsync(`built/web/react-common-skillmap.css`, "utf8");
157749
+ skillmapCss = await linkFontAsync("fa-solid-900", skillmapCss, fontAwesomeSource, "\\.\\.\\/webfonts\\/");
157750
+ skillmapCss = await linkFontAsync("fa-regular-400", skillmapCss, fontAwesomeSource, "\\.\\.\\/webfonts\\/");
157751
+ await writeFileAsync(`built/web/react-common-skillmap.css`, skillmapCss, "utf8");
157752
+ // Run postcss with autoprefixer and rtlcss
157753
+ pxt.debug("running postcss");
157754
+ const postcss = require('postcss');
157755
+ const browserList = [
157756
+ "Chrome >= 38",
157757
+ "Firefox >= 31",
157758
+ "Edge >= 12",
157759
+ "ie >= 11",
157760
+ "Safari >= 9",
157761
+ "Opera >= 21",
157762
+ "iOS >= 9",
157763
+ "ChromeAndroid >= 59",
157764
+ "FirefoxAndroid >= 55"
157765
+ ];
157766
+ const cssnano = require("cssnano")({
157767
+ zindex: false,
157768
+ autoprefixer: { browsers: browserList, add: true }
157768
157769
  });
157770
+ const rtlcss = require("rtlcss");
157771
+ const files = ["semantic.css", "blockly.css", "react-common-skillmap.css"];
157772
+ for (const cssFile of files) {
157773
+ const css = await readFileAsync(`built/web/${cssFile}`, "utf8");
157774
+ const processed = await postcss([cssnano])
157775
+ .process(css, { from: `built/web/${cssFile}`, to: `built/web/${cssFile}` });
157776
+ await writeFileAsync(`built/web/${cssFile}`, processed.css);
157777
+ const processedRtl = await postcss([rtlcss])
157778
+ .process(processed.css, { from: `built/web/${cssFile}`, to: `built/web/rtl${cssFile}` });
157779
+ await writeFileAsync(`built/web/rtl${cssFile}`, processedRtl.css, "utf8");
157780
+ }
157781
+ if (!isPxtCore) {
157782
+ // This is just to support the local skillmap serve for development
157783
+ nodeutil.cp("built/web/react-common-skillmap.css", "node_modules/pxt-core/skillmap/public/blb");
157784
+ }
157785
+ }
157786
+ async function linkFontAsync(font, semCss, sourceDir = "node_modules/semantic-ui-less/themes/default/assets/fonts/", refDir = "fonts\\/") {
157787
+ const fontFile = await readFileAsync(sourceDir + font + ".woff");
157788
+ const url = "url(data:application/font-woff;charset=utf-8;base64,"
157789
+ + fontFile.toString("base64") + ") format('woff')";
157790
+ const r = new RegExp(`src:.*url\\((?:"|')${refDir + font}\\.woff.*`, "g");
157791
+ semCss = semCss.replace('src: url("' + refDir + font + '.eot");', "")
157792
+ .replace('src: url(' + refDir + font + '.eot);', "")
157793
+ .replace(r, "src: " + url + ";");
157794
+ return semCss;
157769
157795
  }
157770
157796
  function buildWebStringsAsync() {
157771
157797
  if (pxt.appTarget.id != "core")
@@ -157788,7 +157814,7 @@ function buildSkillMapAsync(parsed) {
157788
157814
  nodeutil.cp("node_modules/pxt-core/built/pxtlib.js", `${skillmapRoot}/public/blb`);
157789
157815
  nodeutil.cp("built/web/semantic.css", `${skillmapRoot}/public/blb`);
157790
157816
  nodeutil.cp("node_modules/pxt-core/built/web/icons.css", `${skillmapRoot}/public/blb`);
157791
- nodeutil.cp("node_modules/pxt-core/built/web/react-common.css", `${skillmapRoot}/public/blb`);
157817
+ nodeutil.cp("node_modules/pxt-core/built/web/react-common-skillmap.css", `${skillmapRoot}/public/blb`);
157792
157818
  // copy 'assets' over from docs/static
157793
157819
  nodeutil.cpR("docs/static/skillmap/assets", `${skillmapRoot}/public/assets`);
157794
157820
  if (docsPath) {
@@ -162146,7 +162172,7 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
162146
162172
  help: "build required css files",
162147
162173
  flags: {
162148
162174
  force: {
162149
- description: "force re-compile of less files"
162175
+ description: "deprecated; now on by default"
162150
162176
  }
162151
162177
  }
162152
162178
  }, buildSemanticUIAsync);