@dodona/papyros 0.3.4 → 0.3.7-scoped

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/README.md CHANGED
@@ -23,9 +23,14 @@ Currently, Papyros provides support for the following programming languages:
23
23
 
24
24
  ## Using Papyros in your own project
25
25
 
26
- You can install Papyros on your system using npm:
26
+ You can add Papyros to your project as follows:
27
+ - npm:
27
28
  ```shell
28
- npm install -g @dodona/papyros
29
+ npm install @dodona/papyros
30
+ ```
31
+ - yarn:
32
+ ```shell
33
+ yarn add @dodona/papyros
29
34
  ```
30
35
 
31
36
  Papyros currently supports two modes of operation: stand-alone and embedded.
@@ -38,50 +43,61 @@ as the user knows for what purpose Papyros is being used. For example, when used
38
43
  scope of a Python exercise in Dodona, there is no need to support other programming languages.
39
44
  The locale should also match that of the actual application.
40
45
 
41
- The easiest way to initialize Papyros is by using the static method `Papyros.fromElement`.
42
- This method expects a parent element that wraps the scratchpad and a `PapyrosConfig` object.
46
+ Using Papyros in your project is done by following a few steps. First, you create a new
47
+ Papyros instance with a `PapyrosConfig` object.
43
48
  The following options are supported:
44
49
 
45
50
  - `standAlone`: Whether to operate in stand-alone or embedded mode as described above.
51
+ - `programmingLanguage`: The [programming language](/src/ProgrammingLanguage.ts) to use in the CodeEditor and Backend.
46
52
  - `locale`: The locale to use, currently English and Dutch translations are provided.
47
- - `programmingLanguage`: The language to use in the CodeEditor and Backend
48
53
  - `inputMode`: How the users can provide input, according to the [InputMode enum](/src/InputManager.ts)
49
-
50
- Furthermore, you can provide fine-grained configuration in embedded mode by providing `RenderOptions`
51
- to each main component in the application. You minimally need to specify the ID of the parent element.
52
- You can also specify attributes, such as `style` or `data`, or `classNames` to be used.
53
- The main components are the following:
54
-
55
- - `code`: the CodeEditor.
56
- - `panel`: the StatusPanel in the CodeEditor
57
- - `input`: the field for the user input
58
- - `output`: the panel for output of the code
54
+ - `example`: Optional name of the selected example, only appliccable in standAlone-mode
55
+ - `channelOptions`: Optional options to provide to the [sync-message](https://github.com/alexmojaki/sync-message) channel. Extra is the serviceWorkerName, which is the relative pathname to the service worker script
56
+
57
+ Furthermore, you can provide fine-grained configuration by providing `RenderOptions` to each main component in the application when rendering Papyros. You minimally need to specify the ID of the parent element.
58
+ You can also specify attributes, such as `style`, `data`-attributes or `classNames` to be used.
59
+ The components you can style like this are the following:
60
+ - `standAloneOptions`: for the global application in standAlone mode
61
+ - `codeEditorOptions`: for the CodeEditor.
62
+ - `statusPanelOptions`: for the StatusPanel in the CodeEditor
63
+ - `inputOptions`: for the field that handles the user input
64
+ - `outputOptions`: for the panel that displays the output of the code
59
65
 
60
66
  ### User input
61
67
 
62
68
  Important to note is that handling asynchronous input in a synchronous way is not straightforward.
63
- This requires advanced features which are not available by default in your browser. We support two options
69
+ This requires advanced features which are not available by default in your browser. We support two options based on [sync-message](https://github.com/alexmojaki/sync-message).
64
70
 
65
71
  The most efficient and practical way is using SharedArrayBuffers, which requires the presence of certain HTTP headers.
66
72
  The following headers must be set on resources using Papyros.
67
- ```json
68
- 'Cross-Origin-Opener-Policy': 'same-origin',
69
- 'Cross-Origin-Embedder-Policy': 'require-corp'
73
+ ```yaml
74
+ {
75
+ "Cross-Origin-Opener-Policy": "same-origin",
76
+ "Cross-Origin-Embedder-Policy": "require-corp"
77
+ }
70
78
  ```
71
- If you are also embedding other components (such as iframes) in those pages, you will also need to set
72
- 'Cross-Origin-Resource-Policy' to 'cross-origin' to make them work correctly. In order to limit the effect of this
73
- change, it is advised to restrict access using the 'Access-Control-Allow-Origin'-header to prevent abuse of including code.
79
+ If you are also embedding other components (such as iframes, videos or images) in those pages, you will also need to set the `Cross-Origin-Resource-Policy`-header to `cross-origin` to make them work correctly. If these elements come from external URLs, it will likely not be possible to keep using them. An alternative is described below.
74
80
 
75
81
  If you would like to use this project without enabling these HTTP headers, we provide a solution using a service worker.
76
- If your application does not use a service worker yet, a default service worker is pre-built and included in the package.
77
- Simply copy the file located [here](dist/inputServiceWorker.js) to a location of choice in your application where it can be served.
78
- Then, before launching your instance of Papyros, make a call to configureInput with the location of the folder and the name of the file.
82
+ If your application does not use a service worker yet, you can create one based on the [service worker used in stand-alone mode](src/InputServiceWorker.ts)).
83
+ If you already use a service worker, simply include our [InputWorker](src/workers/input/InputWorker.ts) in your existing service worker using imports (you can import it separately from /dist/workers/input/InputWorker). An example of how to use it can be found in our described service worker. Afterwards, inform Papyros of the location using the channelOptions described earlier.
84
+
85
+ ### Code editor
86
+
87
+ The editor used in Papyros is powered by [CodeMirror 6](https://codemirror.net/6/). It is accessible in code via an instance of Papyros and by default allows configuring many options:
88
+ - the [programming language](/src/ProgrammingLanguage.ts) of the contents (for e.g. syntax higlighting)
89
+ - the displayed placeholder
90
+ - the indentation unit
91
+ - the shown panel
92
+ - the autocompletion source
93
+ - the linting source
94
+ - the theme used to style the editor
79
95
 
80
- If you already use a service worker, simply include our functionality in your existing worker using imports. An example can be found [here](src/InputServiceWorker.ts). Afterwards, inform Papyros of this using configureInput as above.
96
+ If you need more specific functionality, this can be added in your own code by accessing the internal CodeMirror editorView.
81
97
 
82
98
  ## Documentation
83
99
 
84
- Visit our web page at <https://docs.dodona.be/papyros/>.
100
+ Visit our documentation page at <https://docs.dodona.be/papyros/>.
85
101
 
86
102
  ## Building and developing
87
103
 
package/dist/Backend.d.ts CHANGED
@@ -36,14 +36,45 @@ export interface WorkerAutocompleteContext {
36
36
  } | null;
37
37
  }
38
38
  export interface WorkerDiagnostic {
39
+ /**
40
+ * 1-based index of the starting line containing the issue
41
+ */
39
42
  lineNr: number;
43
+ /**
44
+ * 0-based index of the column in the starting line
45
+ */
40
46
  columnNr: number;
47
+ /**
48
+ * 1-based index of the ending line containing the issue
49
+ * Can be the same as lineNr
50
+ */
51
+ endLineNr: number;
52
+ /**
53
+ * 0-based index of the column in the ending line
54
+ */
55
+ endColumnNr: number;
56
+ /**
57
+ * Severity of the issue
58
+ */
41
59
  severity: "info" | "warning" | "error";
60
+ /**
61
+ * Message describing the issue
62
+ */
42
63
  message: string;
43
64
  }
44
65
  export declare abstract class Backend<Extras extends SyncExtras = SyncExtras> {
66
+ /**
67
+ * SyncExtras object that grants access to helpful methods
68
+ * for synchronous operations
69
+ */
45
70
  protected extras: Extras;
71
+ /**
72
+ * Callback to handle events published by this Backend
73
+ */
46
74
  protected onEvent: (e: BackendEvent) => any;
75
+ /**
76
+ * Queue to handle published events without overloading the thread
77
+ */
47
78
  protected queue: BackendEventQueue;
48
79
  /**
49
80
  * Constructor is limited as it is meant to be used as a WebWorker
@@ -58,9 +89,10 @@ export declare abstract class Backend<Extras extends SyncExtras = SyncExtras> {
58
89
  /**
59
90
  * Initialize the backend by doing all setup-related work
60
91
  * @param {function(BackendEvent):void} onEvent Callback for when events occur
92
+ * @param {function():void} onOverflow Callback for when overflow occurs
61
93
  * @return {Promise<void>} Promise of launching
62
94
  */
63
- launch(onEvent: (e: BackendEvent) => void): Promise<void>;
95
+ launch(onEvent: (e: BackendEvent) => void, onOverflow: () => void): Promise<void>;
64
96
  /**
65
97
  * Executes the given code
66
98
  * @param {Extras} extras Helper properties to run code
@@ -8,7 +8,8 @@ export declare enum BackendEventType {
8
8
  Output = "output",
9
9
  Sleep = "sleep",
10
10
  Error = "error",
11
- Interrupt = "interrupt"
11
+ Interrupt = "interrupt",
12
+ Loading = "loading"
12
13
  }
13
14
  /**
14
15
  * All possible types for ease of iteration
@@ -25,6 +25,14 @@ export declare class BackendEventQueue {
25
25
  * Queue storing Output-events after overflowing
26
26
  */
27
27
  private overflow;
28
+ /**
29
+ * Callback for when overflow occurs
30
+ */
31
+ private onOverflow;
32
+ /**
33
+ * Keep track whether the queue reached its limit this run
34
+ */
35
+ private overflown;
28
36
  /**
29
37
  * Time in milliseconds when the last flush occurred
30
38
  */
@@ -38,11 +46,12 @@ export declare class BackendEventQueue {
38
46
  */
39
47
  private decoder;
40
48
  /**
41
- * @param {Function} callback Function to process events in the queue
49
+ * @param {function(BackendEvent):void} callback Function to process events in the queue
50
+ * @param {function():void} onOverflow Callback for when overflow occurs
42
51
  * @param {number} limit The maximal amount of output lines to send before overflowing
43
52
  * @param {number} flushTime The time in milliseconds before sending events through
44
53
  */
45
- constructor(callback: (e: BackendEvent) => void, limit?: number, flushTime?: number);
54
+ constructor(callback: (e: BackendEvent) => void, onOverflow: () => void, limit?: number, flushTime?: number);
46
55
  /**
47
56
  * Add an element to the queue
48
57
  * @param {BackendEventType} type The type of the event
@@ -26,6 +26,10 @@ export declare abstract class BackendManager {
26
26
  * Uses an Array to maintain order of subscription
27
27
  */
28
28
  private static subscriberMap;
29
+ /**
30
+ * Whether the BackendManager is publishing events
31
+ */
32
+ private static halted;
29
33
  /**
30
34
  * The channel used to communicate with the SyncClients
31
35
  */
@@ -59,5 +63,6 @@ export declare abstract class BackendManager {
59
63
  * @param {BackendEventType} e The event to publish
60
64
  */
61
65
  static publish(e: BackendEvent): void;
66
+ private static halt;
62
67
  }
63
68
  export {};
@@ -17,10 +17,11 @@ export declare class CodeEditor extends Renderable {
17
17
  private compartments;
18
18
  /**
19
19
  * Construct a new CodeEditor
20
+ * @param {Function} onRunRequest Callback for when the user wants to run the code
20
21
  * @param {string} initialCode The initial code to display
21
22
  * @param {number} indentLength The length in spaces for the indent unit
22
23
  */
23
- constructor(initialCode?: string, indentLength?: number);
24
+ constructor(onRunRequest: () => void, initialCode?: string, indentLength?: number);
24
25
  /**
25
26
  * Helper method to dispatch configuration changes at runtime
26
27
  * @param {Array<[Option, Extension]>} items Array of items to reconfigure
@@ -51,6 +52,10 @@ export declare class CodeEditor extends Renderable {
51
52
  * @param {number} indentLength The number of spaces to use for indentation
52
53
  */
53
54
  setIndentLength(indentLength: number): void;
55
+ /**
56
+ * @param {Function} onChange Listener that performs actions on the new contents
57
+ */
58
+ onChange(onChange: ((newContent: string) => void)): void;
54
59
  /**
55
60
  * @param {HTMLElement} panel The panel to display at the bottom of the editor
56
61
  */
@@ -82,7 +87,6 @@ export declare class CodeEditor extends Renderable {
82
87
  * - special character highlighting
83
88
  * - the undo history
84
89
  * - a fold gutter
85
- * - gutter for linting
86
90
  * - custom selection drawing
87
91
  * - multiple selections
88
92
  * - reindentation on input
@@ -2,6 +2,7 @@ import { CodeEditor } from "./CodeEditor";
2
2
  import { InputManager } from "./InputManager";
3
3
  import { ProgrammingLanguage } from "./ProgrammingLanguage";
4
4
  import { RenderOptions, ButtonOptions, Renderable } from "./util/Rendering";
5
+ import { OutputManager } from "./OutputManager";
5
6
  interface CodeRunnerRenderOptions {
6
7
  /**
7
8
  * Options for rendering the panel
@@ -15,6 +16,10 @@ interface CodeRunnerRenderOptions {
15
16
  * Options for rendering the editor
16
17
  */
17
18
  codeEditorOptions: RenderOptions;
19
+ /**
20
+ * RenderOptions for the output field
21
+ */
22
+ outputOptions: RenderOptions;
18
23
  }
19
24
  /**
20
25
  * Enum representing the possible states while processing code
@@ -26,6 +31,19 @@ export declare enum RunState {
26
31
  Stopping = "stopping",
27
32
  Ready = "ready"
28
33
  }
34
+ /**
35
+ * Interface to represent information required when handling loading events
36
+ */
37
+ export interface LoadingData {
38
+ /**
39
+ * List of module names that are being loaded
40
+ */
41
+ modules: Array<string>;
42
+ /**
43
+ * Whether the modules are being loaded or have been loaded
44
+ */
45
+ loading: boolean;
46
+ }
29
47
  /**
30
48
  * Helper component to manage and visualize the current RunState
31
49
  */
@@ -42,6 +60,10 @@ export declare class CodeRunner extends Renderable<CodeRunnerRenderOptions> {
42
60
  * Component to request and handle input from the user
43
61
  */
44
62
  readonly inputManager: InputManager;
63
+ /**
64
+ * Component to handle output generated by the user's code
65
+ */
66
+ readonly outputManager: OutputManager;
45
67
  /**
46
68
  * The backend that executes the code asynchronously
47
69
  */
@@ -54,6 +76,14 @@ export declare class CodeRunner extends Renderable<CodeRunnerRenderOptions> {
54
76
  * Buttons managed by this component
55
77
  */
56
78
  private buttons;
79
+ /**
80
+ * Array of packages that are being installed
81
+ */
82
+ private loadingPackages;
83
+ /**
84
+ * Previous state to restore when loading is done
85
+ */
86
+ private previousState;
57
87
  /**
58
88
  * Construct a new RunStateManager with the given listeners
59
89
  * @param {ProgrammingLanguage} programmingLanguage The language to use
@@ -86,7 +116,7 @@ export declare class CodeRunner extends Renderable<CodeRunnerRenderOptions> {
86
116
  * Show or hide the spinning circle, representing a running animation
87
117
  * @param {boolean} show Whether to show the spinner
88
118
  */
89
- showSpinner(show: boolean): void;
119
+ private showSpinner;
90
120
  /**
91
121
  * Show the current state of the program to the user
92
122
  * @param {RunState} state The current state of the run
@@ -102,9 +132,14 @@ export declare class CodeRunner extends Renderable<CodeRunnerRenderOptions> {
102
132
  addButton(options: ButtonOptions, onClick: () => void): void;
103
133
  protected _render(options: CodeRunnerRenderOptions): HTMLElement;
104
134
  /**
105
- * Run the code that is currently present in the editor
135
+ * @param {string} code The code to run
106
136
  * @return {Promise<void>} Promise of running the code
107
137
  */
108
- runCode(): Promise<void>;
138
+ runCode(code: string): Promise<void>;
139
+ /**
140
+ * Callback to handle loading events
141
+ * @param {BackendEvent} e The loading event
142
+ */
143
+ private onLoad;
109
144
  }
110
145
  export {};
@@ -1,4 +1,10 @@
1
1
  import { ProgrammingLanguage } from "./ProgrammingLanguage";
2
+ /**
3
+ * Add a prefix to a string, ensuring uniqueness in the page
4
+ * @param {string} s The value to add a prefix to
5
+ * @return {string} The value with an almost certainly unused prefix
6
+ */
7
+ export declare function addPapyrosPrefix(s: string): string;
2
8
  export declare const MAIN_APP_ID: string;
3
9
  export declare const OUTPUT_AREA_WRAPPER_ID: string;
4
10
  export declare const OUTPUT_AREA_ID: string;
@@ -1,4 +1,3 @@
1
- import { UserInputHandler } from "./input/UserInputHandler";
2
1
  import { Renderable, RenderOptions } from "./util/Rendering";
3
2
  export declare enum InputMode {
4
3
  Interactive = "interactive",
@@ -15,7 +14,7 @@ export declare class InputManager extends Renderable {
15
14
  private buildInputHandlerMap;
16
15
  getInputMode(): InputMode;
17
16
  setInputMode(inputMode: InputMode): void;
18
- get inputHandler(): UserInputHandler;
17
+ private get inputHandler();
19
18
  isWaiting(): boolean;
20
19
  protected _render(options: RenderOptions): void;
21
20
  private waitWithPrompt;
package/dist/Library.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { BackendEvent } from "./BackendEvent";
2
2
  import { CodeEditor } from "./CodeEditor";
3
3
  import { InputManager, InputMode } from "./InputManager";
4
- import { OutputManager } from "./OutputManager";
5
- import { Papyros } from "./Papyros";
4
+ import { FriendlyError, OutputManager } from "./OutputManager";
5
+ import { Papyros, PapyrosConfig, PapyrosRenderOptions } from "./Papyros";
6
6
  import { CodeRunner, RunState } from "./CodeRunner";
7
- export * from "./ProgrammingLanguage";
8
- export type { BackendEvent };
9
- export { Papyros, CodeEditor, RunState, CodeRunner, InputManager, InputMode, OutputManager, };
7
+ import { BackendManager } from "./BackendManager";
8
+ import { ProgrammingLanguage } from "./ProgrammingLanguage";
9
+ import { WorkerAutocompleteContext, WorkerDiagnostic } from "./Backend";
10
+ import { ButtonOptions, RenderOptions } from "./util/Rendering";
11
+ export type { BackendEvent, FriendlyError, WorkerAutocompleteContext, WorkerDiagnostic, PapyrosConfig, PapyrosRenderOptions, RenderOptions, ButtonOptions };
12
+ export { Papyros, ProgrammingLanguage, BackendManager, CodeEditor, CodeRunner, RunState, InputManager, InputMode, OutputManager };