Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
188bead
install pfem
cocomarine May 28, 2026
e8ed800
update webpack config to disable ESM strict resolution for pfem
cocomarine May 28, 2026
cfa91e6
add pfem to skulpt runner WIP pyodide runner
cocomarine May 28, 2026
e594994
Merge branch 'main' into 1448-add-improved-error-messaging
cocomarine Jun 1, 2026
088617a
fix pyodide error
cocomarine Jun 1, 2026
ffb0c84
Merge branch 'main' into 1448-add-improved-error-messaging
cocomarine Jun 1, 2026
3ae80e6
add friendly error enabled attribute
cocomarine Jun 1, 2026
cb9f905
fix errors due to ESM to CJS transform
cocomarine Jun 1, 2026
4bf16ec
remove unnecessary mock
cocomarine Jun 1, 2026
9af9cfe
add friendlyError to redux and show in ErrorMessage
cocomarine Jun 1, 2026
7c05ba7
minor fixes
cocomarine Jun 1, 2026
c1b803f
update editorslice and errormessage tests
cocomarine Jun 2, 2026
0958129
update pyodide and skulpt runner tests
cocomarine Jun 2, 2026
6ff35ec
plain text friendly error for now
cocomarine Jun 2, 2026
0ac2991
add dompurify
cocomarine Jun 2, 2026
64c2c4c
dispatch friendly error html and use css to restrict to title and sum…
cocomarine Jun 2, 2026
4fda69e
update runner tests
cocomarine Jun 2, 2026
3dc2a2e
update editorslice test
cocomarine Jun 2, 2026
5be1299
stub out friendlyerror html in tests
cocomarine Jun 3, 2026
113797f
refactor: remove defaulting to editor styles
maxelkins May 29, 2026
9a5b56c
refactor: move error message to `EditorInput`
maxelkins May 29, 2026
4971474
feat: add initial FriendlyErrorMessage UI component into ErrorMessage
maxelkins May 29, 2026
3dbfc83
revert: move error back to output panel
maxelkins Jun 2, 2026
626bd41
use FriendlyErrorMessage component and update styling
cocomarine Jun 3, 2026
9a8b187
add font size to original error message and minor fixes
cocomarine Jun 3, 2026
8bd51f8
remove fem stub, add friendly test, revert error message test
cocomarine Jun 3, 2026
f309c11
update cypress test helper to new class
cocomarine Jun 3, 2026
aa137a3
update cypress test
cocomarine Jun 3, 2026
c744d3e
intercept the copydeck request before running code
cocomarine Jun 3, 2026
a194986
fix flaky test
cocomarine Jun 3, 2026
d4684b4
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 3, 2026
4ad3ef1
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 4, 2026
da8c411
resolve conflicts
cocomarine Jun 4, 2026
7a807ff
try using fixture of copydeck for test
cocomarine Jun 4, 2026
b696959
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 4, 2026
9bc9022
update pyodide cy
cocomarine Jun 4, 2026
adce42e
Merge branch '1448-and-ui-branches-combined' of github.com:RaspberryP…
cocomarine Jun 4, 2026
454a80d
uncomment test
cocomarine Jun 4, 2026
3ff953e
WIP move pyodide error to input panel
cocomarine Jun 4, 2026
7113cac
move error to input panel and show input panel in mobile when error e…
cocomarine Jun 5, 2026
ccfa903
update tests
cocomarine Jun 5, 2026
54e3cea
add styling to pfem var and tidy
cocomarine Jun 5, 2026
1df6e2e
add styling to pfem and fix pyodide friendly error
cocomarine Jun 5, 2026
f2fdaad
use logical css
cocomarine Jun 5, 2026
50c402d
update pfem styling
cocomarine Jun 8, 2026
8fe26da
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 8, 2026
bf0991a
update styling
cocomarine Jun 9, 2026
625e12e
update error trace object for pyodide pfem
cocomarine Jun 9, 2026
cb14058
improve codeLine and add caret line test
cocomarine Jun 9, 2026
1d875c3
linting
cocomarine Jun 9, 2026
15a8862
tidy
cocomarine Jun 9, 2026
28fece4
show error to output only mode pyodide
cocomarine Jun 10, 2026
8716bdd
update pfem to 0.3.0
cocomarine Jun 10, 2026
3d832eb
feat: update PFEM lib to 0.5.0, pass `file` to friendlyExplain() expl…
grega Jun 10, 2026
91d8fa3
update test and revert back to using trace object
cocomarine Jun 10, 2026
15b02dd
Merge branch '1448-and-ui-branches-combined' of github.com:RaspberryP…
cocomarine Jun 10, 2026
13e3a78
add rawTrace back in and update test
cocomarine Jun 10, 2026
185c1f4
feat: bump PFEM to version 6, gaining a11y improvements
grega Jun 10, 2026
1242226
add language guard and update fixutre
cocomarine Jun 11, 2026
15f8aea
Merge branch '1448-and-ui-branches-combined' of github.com:RaspberryP…
cocomarine Jun 11, 2026
763849e
add try catch for pfem and update test
cocomarine Jun 11, 2026
93bd4fc
bump PFEM to version 7 for copy and variant update
cocomarine Jun 11, 2026
9f7c403
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 11, 2026
b6a3cc9
update svg path for file icon
cocomarine Jun 11, 2026
0b23980
Merge branch 'main' into 1448-and-ui-branches-combined
cocomarine Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ npmMinimalAgeGate: 7d
npmPreapprovedPackages:
- "@raspberrypifoundation/design-system-react"
- "@raspberrypifoundation/design-system-core"
- "@RaspberryPiFoundation/scratch-gui"
- "@RaspberryPiFoundation/scratch-gui"
- "@raspberrypifoundation/python-friendly-error-messages"
39 changes: 39 additions & 0 deletions cypress/e2e/spec-wc-pyodide.cy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
getEditorShadow,
getErrorMessage,
getFriendlyErrorMessage,
getFileButtonByName,
getProgramInput,
getPyodideOutput,
Expand Down Expand Up @@ -253,3 +254,41 @@ print(text_out)
);
});
});

describe("When friendly errors enabled with pyodide", () => {
beforeEach(() => {
cy.intercept("GET", "**/python-error-copydecks/**", {
fixture: "copydeck.json",
}).as("copydeck");

const params = new URLSearchParams();
params.set("friendly_errors_enabled", "true");

cy.visit({
url: `${origin}?${params.toString()}`,
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
});
cy.window().then((win) => {
Object.defineProperty(win, "crossOriginIsolated", {
value: true,
configurable: true,
});
});
cy.wait("@copydeck");
});

it("shows a friendly error message when an error occurs", () => {
runCode("print(kitten)");
getErrorMessage().should(
"contain",
"NameError: name 'kitten' is not defined on line 1 of main.py",
);
getFriendlyErrorMessage().should(
"contain",
"This variable doesn't exist here",
);
});
});
33 changes: 33 additions & 0 deletions cypress/e2e/spec-wc-skulpt.cy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
getErrorMessage,
getFriendlyErrorMessage,
getP5Canvas,
getPythonConsoleOutput,
getSkulptRunner,
Expand Down Expand Up @@ -149,3 +150,35 @@ describe("Running the code with skulpt", () => {
);
});
});

describe("When friendly errors enabled with skulpt", () => {
beforeEach(() => {
cy.intercept("GET", "**/python-error-copydecks/**", {
fixture: "copydeck.json",
}).as("copydeck");

const params = new URLSearchParams();
params.set("friendly_errors_enabled", "true");

cy.visit(`${origin}?${params.toString()}`);
cy.window().then((win) => {
Object.defineProperty(win, "crossOriginIsolated", {
value: false,
configurable: true,
});
});
cy.wait("@copydeck");
});

it("shows a friendly error message when an error occurs", () => {
runCode("import turtle\nprint(kitten)");
getErrorMessage().should(
"contain",
"NameError: name 'kitten' is not defined on line 2 of main.py",
);
getFriendlyErrorMessage().should(
"contain",
"This variable doesn't exist here",
);
});
});
46 changes: 46 additions & 0 deletions cypress/fixtures/copydeck.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"meta": {
"language": "en",
"version": 1
},

"errors": {
"NameError": {
"variants": [
{
"if": {
"not_message": ["is not defined"]
},
"title": "This variable doesn't exist yet",
"summary": "Your code uses the variable {{name}}, but it hasn't been created yet. Check {{loc}}. If you meant to print the text {{name}}, put it in double quotes.",
"why": "Without speech marks Python treats {{name}} as a variable, and this variable does not exist yet.",
"steps": [
"If it is meant to be text, put speech marks around {{name}}.",
"If it is meant to be a variable, make it first (for example: {{name}} = 0).",
"Check spelling and capital letters."
],
"_placeholders": {
"name": "The undefined variable name, e.g. kittens",
"loc": "Where it was used, e.g. line 2 in main.py"
}
},
{
"if": {
"match_message": ["is not defined"]
},
"title": "This variable doesn't exist here",
"summary": "{{name}} might be created somewhere else, but you're using it at {{loc}}. If you meant the text {{name}}, put it in double quotes.",
"why": "A variable created in another place might not be available here.",
"steps": [
"Move the line that makes it to above where you use it.",
"Or set it here just before you use it."
],
"_placeholders": {
"name": "The variable name used out of scope, e.g. total",
"loc": "Where it was referenced, e.g. line 8 in main.py"
}
}
]
}
}
}
5 changes: 4 additions & 1 deletion cypress/helpers/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ export const getP5Canvas = () => getEditorShadow().find(".p5Canvas");
export const getTurtleOutput = () => getEditorShadow().find("#turtleOutput");

export const getErrorMessage = () =>
getEditorShadow().find(".error-message__content");
getEditorShadow().find(".error-message__python");

export const getFriendlyErrorMessage = () =>
getEditorShadow().find(".friendly-error-message");

export const getTextOutputTab = () =>
getPyodideOutput().findByLabelText("Text output");
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@hello-pangea/dnd": "^16.2.0",
"@juggle/resize-observer": "^3.3.1",
"@raspberrypifoundation/design-system-react": "^2.7.0",
"@raspberrypifoundation/python-friendly-error-messages": "0.1.6",
"@raspberrypifoundation/python-friendly-error-messages": "0.7.0",
"@react-three/drei": "9.114.3",
"@react-three/fiber": "^8.0.13",
"@reduxjs/toolkit": "^1.6.2",
Expand Down
2 changes: 1 addition & 1 deletion src/PyodideWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ const PyodideWorker = () => {

const line = match ? parseInt(match[2], 10) : "";

return { file, line, mistake, type, info };
return { file, line, mistake, type, info, rawTraceback: error.message };
};

initialisePyodide();
Expand Down
3 changes: 3 additions & 0 deletions src/assets/error_file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/cancel_FILL.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 3 additions & 5 deletions src/assets/stylesheets/EditorPanel.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@forward '@raspberrypifoundation/design-system-core/scss/properties/spacing';
@use '@raspberrypifoundation/design-system-core/scss/mixins/typography' as typography;
@forward "@raspberrypifoundation/design-system-core/scss/properties/spacing";
@use "@raspberrypifoundation/design-system-core/scss/mixins/typography" as
typography;

// Scrollbar-width is needed from scrollbar to show in Chrome
.editor-wrapper {
Expand Down Expand Up @@ -31,7 +32,6 @@
overscroll-behavior-x: none;
font-family: var(--wc-font-family-monospace);


.cm-content {
flex: 1;
padding-block-start: var(--space-0-5);
Expand Down Expand Up @@ -60,5 +60,3 @@
display: none;
}
}


40 changes: 20 additions & 20 deletions src/assets/stylesheets/ErrorMessage.scss
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
@use "./rpf_design_system/font-size" as *;
@use "./rpf_design_system/spacing" as *;
@use "@raspberrypifoundation/design-system-core/scss/mixins/typography" as
typography;

.error-message {
color: #7e0305;
background-color: #fde2e1;
padding: $space-0-75 $space-1-25;
color: var(--rpf-red-900);
background-color: var(--rpf-red-100);
border-block-start: 1px solid var(--editor-color-outline);
padding: var(--space-1);
overflow-y: auto;
scrollbar-width: thin;
max-block-size: 30%;

&__content {
&__error {
padding: 0;
margin: 0;
white-space: pre-wrap;
overflow-wrap: break-word;
font-weight: bold;
}

&--medium {
@include font-size-1-5(regular);
}

&--large {
@include font-size-2(regular);
}
&__python {
display: flex;
gap: var(--space-1);
@include typography.style-1;

// Only displaying title and summary of friendlyError
&__friendly {
.pfem__why,
.pfem__steps,
.pfem__patch,
.pfem__details {
display: none;
&--medium {
@include typography.style-1;
}

&--large {
@include typography.style-2;
}
}
}
58 changes: 58 additions & 0 deletions src/assets/stylesheets/FriendlyErrorMessage.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.friendly-error-message {
background-color: var(--rpf-white);
padding: var(--space-1) var(--space-1-5);
color: var(--rpf-text-primary);
border-radius: var(--space-1);
margin-block-start: var(--space-1);

&__content {
line-height: 1.75rem;

.pfem__title {
font-weight: 600;
display: inline;
}

.pfem__summary {
display: inline;

&::before {
content: " - ";
}
}

.pfem__var, .pfem__code, .pfem__file, .pfem__line {
font-family: var(--wc-font-family-monospace);
border-radius: 0.25rem;
padding: 0.2rem var(--space-0-5);
}

.pfem__var {
background-color: var(--rpf-green-100);
}

.pfem__code {
background-color: var(--rpf-grey-100);
}

.pfem__file {
white-space: nowrap;
background-color: var(--rpf-yellow-100);

&::before {
content: "";
display: inline-block;
inline-size: 1em;
block-size: 1em;
background: url("../error_file.svg") no-repeat center;
background-size: contain;
Comment thread
Copilot marked this conversation as resolved.
margin-inline-end: 0.12rem;
vertical-align: middle;
}
}

.pfem__line {
background-color: var(--rpf-blue-100);
}
}
}
37 changes: 28 additions & 9 deletions src/assets/stylesheets/InternalStyles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
@use "./EditorFinalStep.scss" as *;
@use "./Loader.scss" as *;
@use "./LoadFailed.scss" as *;
@use "./FriendlyErrorMessage" as *;

@use "./settings/fonts" as fonts;

Expand Down Expand Up @@ -158,7 +159,9 @@ button:focus-visible {
// Primary button
--rpf-button-primary-background-color: var(--editor-color-theme);
--rpf-button-primary-background-color-focus: var(--editor-color-theme);
--rpf-button-primary-background-color-hover: var(--editor-color-theme-secondary);
--rpf-button-primary-background-color-hover: var(
--editor-color-theme-secondary
);
--rpf-button-primary-background-color-active: var(--rpf-navy-600);
--rpf-button-primary-background-color-disabled: var(--rpf-navy-200);
--rpf-button-primary-color-disabled: var(--rpf-grey-600);
Expand All @@ -167,10 +170,16 @@ button:focus-visible {
// Secondary button
--rpf-button-secondary-background-color: var(--editor-color-theme);
--rpf-button-secondary-background-color-focus: var(--rpf-brand-raspberry);
--rpf-button-secondary-background-color-hover: var(--editor-color-theme-tertiary);
--rpf-button-secondary-background-color-hover: var(
--editor-color-theme-tertiary
);
--rpf-button-secondary-border-color: var(--editor-color-theme);
--rpf-button-secondary-border-color-hover: var(--editor-color-theme-secondary);
--rpf-button-secondary-background-color-active: var(--editor-color-theme-secondary);
--rpf-button-secondary-border-color-hover: var(
--editor-color-theme-secondary
);
--rpf-button-secondary-background-color-active: var(
--editor-color-theme-secondary
);
--rpf-button-secondary-background-color-disabled: var(--rpf-grey-50);
--rpf-button-secondary-text-color: var(--editor-color-theme);

Expand Down Expand Up @@ -230,7 +239,9 @@ button:focus-visible {
--rpf-button-secondary-text-color: var(--rpf-white);
--rpf-button-secondary-background-color: var(--editor-color-layer-2);
--rpf-button-secondary-background-color-active: var(--rpf-navy-200);
--rpf-button-secondary-color-disabled-background: var(--editor-color-layer-3);
--rpf-button-secondary-color-disabled-background: var(
--editor-color-layer-3
);
--rpf-button-secondary-background-color-hover: var(--editor-color-outline);
--rpf-button-secondary-border-color: var(--editor-color-theme);
--rpf-button-secondary-border-color-hover: var(--editor-color-theme);
Expand All @@ -240,9 +251,17 @@ button:focus-visible {
// Tertiary button
--rpf-button-tertiary-text-color-hover: var(--rpf-grey-200);
--rpf-button-tertiary-danger-text-color: var(--rpf-red-600);
--rpf-button-tertiary-danger-background-color-hover: rgba(255, 255, 255, 0.1);
--rpf-button-tertiary-danger-background-color-active: rgba(255, 255, 255, 0.15);
--rpf-button-tertiary-danger-background-color-hover: rgba(
255,
255,
255,
0.1
);
--rpf-button-tertiary-danger-background-color-active: rgba(
255,
255,
255,
0.15
);
}
}


Loading
Loading