@dodona/papyros 1.0.1 → 2.0.0-beta.0

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 (109) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/dist/App.d.ts +1 -1
  4. package/dist/App.js +73 -0
  5. package/dist/App.js.map +1 -0
  6. package/dist/Backend.d.ts +0 -48
  7. package/dist/Backend.js +76 -0
  8. package/dist/Backend.js.map +1 -0
  9. package/dist/BackendEvent.d.ts +0 -0
  10. package/dist/BackendEvent.js +24 -0
  11. package/dist/BackendEvent.js.map +1 -0
  12. package/dist/BackendEventQueue.d.ts +0 -0
  13. package/dist/BackendEventQueue.js +135 -0
  14. package/dist/BackendEventQueue.js.map +1 -0
  15. package/dist/BackendManager.d.ts +1 -1
  16. package/dist/BackendManager.js +94 -0
  17. package/dist/BackendManager.js.map +1 -0
  18. package/dist/CodeRunner.d.ts +0 -0
  19. package/dist/CodeRunner.js +372 -0
  20. package/dist/CodeRunner.js.map +1 -0
  21. package/dist/Constants.d.ts +0 -0
  22. package/dist/Constants.js +36 -0
  23. package/dist/Constants.js.map +1 -0
  24. package/dist/InputManager.d.ts +0 -0
  25. package/dist/InputManager.js +102 -0
  26. package/dist/InputManager.js.map +1 -0
  27. package/dist/InputServiceWorker.d.ts +0 -0
  28. package/dist/InputServiceWorker.js +37 -0
  29. package/dist/InputServiceWorker.js.map +1 -0
  30. package/dist/Library.d.ts +2 -2
  31. package/dist/Library.js +9 -1
  32. package/dist/Library.js.map +1 -0
  33. package/dist/OutputManager.d.ts +0 -0
  34. package/dist/OutputManager.js +161 -0
  35. package/dist/OutputManager.js.map +1 -0
  36. package/dist/Papyros.css +563 -0
  37. package/dist/Papyros.d.ts +0 -1
  38. package/dist/Papyros.js +268 -0
  39. package/dist/Papyros.js.map +1 -0
  40. package/dist/ProgrammingLanguage.d.ts +0 -0
  41. package/dist/ProgrammingLanguage.js +9 -0
  42. package/dist/ProgrammingLanguage.js.map +1 -0
  43. package/dist/Translations.d.ts +74 -74
  44. package/dist/Translations.js +164 -0
  45. package/dist/Translations.js.map +1 -0
  46. package/dist/editor/BatchInputEditor.d.ts +0 -0
  47. package/dist/editor/BatchInputEditor.js +71 -0
  48. package/dist/editor/BatchInputEditor.js.map +1 -0
  49. package/dist/editor/CodeEditor.d.ts +0 -5
  50. package/dist/editor/CodeEditor.js +180 -0
  51. package/dist/editor/CodeEditor.js.map +1 -0
  52. package/dist/editor/CodeMirrorEditor.d.ts +0 -0
  53. package/dist/editor/CodeMirrorEditor.js +168 -0
  54. package/dist/editor/CodeMirrorEditor.js.map +1 -0
  55. package/dist/editor/DarkTheme.d.ts +0 -0
  56. package/dist/editor/DarkTheme.js +73 -0
  57. package/dist/editor/DarkTheme.js.map +1 -0
  58. package/dist/editor/Gutters.d.ts +0 -0
  59. package/dist/editor/Gutters.js +162 -0
  60. package/dist/editor/Gutters.js.map +1 -0
  61. package/dist/examples/Examples.d.ts +0 -0
  62. package/dist/examples/Examples.js +23 -0
  63. package/dist/examples/Examples.js.map +1 -0
  64. package/dist/examples/JavaScriptExamples.d.ts +0 -0
  65. package/dist/examples/JavaScriptExamples.js +16 -0
  66. package/dist/examples/JavaScriptExamples.js.map +1 -0
  67. package/dist/examples/PythonExamples.d.ts +0 -0
  68. package/dist/examples/PythonExamples.js +163 -0
  69. package/dist/examples/PythonExamples.js.map +1 -0
  70. package/dist/input/BatchInputHandler.d.ts +0 -0
  71. package/dist/input/BatchInputHandler.js +112 -0
  72. package/dist/input/BatchInputHandler.js.map +1 -0
  73. package/dist/input/InteractiveInputHandler.d.ts +0 -0
  74. package/dist/input/InteractiveInputHandler.js +90 -0
  75. package/dist/input/InteractiveInputHandler.js.map +1 -0
  76. package/dist/input/UserInputHandler.d.ts +0 -0
  77. package/dist/input/UserInputHandler.js +40 -0
  78. package/dist/input/UserInputHandler.js.map +1 -0
  79. package/dist/util/HTMLShapes.d.ts +0 -0
  80. package/dist/util/HTMLShapes.js +25 -0
  81. package/dist/util/HTMLShapes.js.map +1 -0
  82. package/dist/util/Logging.d.ts +0 -0
  83. package/dist/util/Logging.js +30 -0
  84. package/dist/util/Logging.js.map +1 -0
  85. package/dist/util/Rendering.d.ts +0 -0
  86. package/dist/util/Rendering.js +139 -0
  87. package/dist/util/Rendering.js.map +1 -0
  88. package/dist/util/Util.d.ts +1 -1
  89. package/dist/util/Util.js +148 -0
  90. package/dist/util/Util.js.map +1 -0
  91. package/dist/workers/input/InputWorker.d.ts +0 -0
  92. package/dist/workers/input/InputWorker.js +63 -1
  93. package/dist/workers/input/InputWorker.js.map +1 -0
  94. package/dist/workers/javascript/JavaScriptWorker.d.ts +39 -0
  95. package/dist/workers/javascript/JavaScriptWorker.js +148 -0
  96. package/dist/workers/javascript/JavaScriptWorker.js.map +1 -0
  97. package/dist/workers/javascript/worker.d.ts +1 -0
  98. package/dist/workers/javascript/worker.js +5 -0
  99. package/dist/workers/javascript/worker.js.map +1 -0
  100. package/dist/workers/python/PythonWorker.d.ts +31 -0
  101. package/dist/workers/python/PythonWorker.js +106 -0
  102. package/dist/workers/python/PythonWorker.js.map +1 -0
  103. package/dist/workers/python/python_package.tar.gz +0 -0
  104. package/dist/workers/python/worker.d.ts +1 -0
  105. package/dist/workers/python/worker.js +5 -0
  106. package/dist/workers/python/worker.js.map +1 -0
  107. package/package.json +45 -42
  108. package/dist/workers/javascript/JavaScriptWorker.worker.d.ts +0 -2
  109. package/dist/workers/python/PythonWorker.worker.d.ts +0 -2
@@ -0,0 +1,90 @@
1
+ import { INPUT_TA_ID, SEND_INPUT_BTN_ID } from "../Constants";
2
+ import { InputMode } from "../InputManager";
3
+ import { addListener, getElement, t } from "../util/Util";
4
+ import { UserInputHandler } from "./UserInputHandler";
5
+ import { renderButton, renderWithOptions } from "../util/Rendering";
6
+ /**
7
+ * Input handler that takes input from the user in an interactive fashion
8
+ */
9
+ export class InteractiveInputHandler extends UserInputHandler {
10
+ /**
11
+ * Retrieve the button that users can click to send their input
12
+ */
13
+ get sendButton() {
14
+ return getElement(SEND_INPUT_BTN_ID);
15
+ }
16
+ /**
17
+ * Retrieve the HTMLInputElement for this InputHandler
18
+ */
19
+ get inputArea() {
20
+ return getElement(INPUT_TA_ID);
21
+ }
22
+ getInputMode() {
23
+ return InputMode.Interactive;
24
+ }
25
+ hasNext() {
26
+ return this.waiting; // Allow sending empty lines when the user does this explicitly
27
+ }
28
+ next() {
29
+ const value = this.inputArea.value;
30
+ this.reset();
31
+ return value;
32
+ }
33
+ waitWithPrompt(waiting, prompt) {
34
+ this.waiting = waiting;
35
+ this.sendButton.disabled = !waiting;
36
+ this.inputArea.disabled = !waiting;
37
+ super.waitWithPrompt(waiting, prompt);
38
+ }
39
+ setPlaceholder(placeholder) {
40
+ if (this.waiting) {
41
+ this.inputArea.setAttribute("placeholder", placeholder);
42
+ this.inputArea.setAttribute("title", "");
43
+ }
44
+ else {
45
+ this.inputArea.setAttribute("placeholder", "");
46
+ this.inputArea.setAttribute("title", t("Papyros.input_disabled"));
47
+ }
48
+ }
49
+ focus() {
50
+ this.inputArea.focus();
51
+ }
52
+ toggle() {
53
+ this.reset();
54
+ }
55
+ onRunStart() {
56
+ this.reset();
57
+ }
58
+ onRunEnd() {
59
+ // Intentionally empty
60
+ }
61
+ _render(options) {
62
+ const buttonHTML = renderButton({
63
+ id: SEND_INPUT_BTN_ID,
64
+ // eslint-disable-next-line max-len
65
+ classNames: "_tw-text-black _tw-bg-white _tw-border-2 dark:_tw-text-white dark:_tw-bg-dark-mode-bg",
66
+ buttonText: t("Papyros.enter")
67
+ });
68
+ renderWithOptions(options, `
69
+ <div class="_tw-flex _tw-flex-row _tw-my-1">
70
+ <input id="${INPUT_TA_ID}" type="text"
71
+ class="_tw-border _tw-w-full _tw-mr-0.5 _tw-px-1 _tw-rounded-lg
72
+ dark:_tw-border-dark-mode-content dark:_tw-bg-dark-mode-bg
73
+ placeholder:_tw-text-placeholder-grey disabled:_tw-cursor-not-allowed
74
+ focus:_tw-outline-none focus:_tw-ring-1 focus:_tw-ring-blue-500">
75
+ </input>
76
+ ${buttonHTML}
77
+ </div>`);
78
+ addListener(SEND_INPUT_BTN_ID, () => this.inputCallback(this.next()), "click");
79
+ this.inputArea.addEventListener("keydown", (ev) => {
80
+ if (this.waiting && ev.key && ev.key.toLowerCase() === "enter") {
81
+ this.inputCallback(this.next());
82
+ }
83
+ });
84
+ }
85
+ reset() {
86
+ super.reset();
87
+ this.inputArea.value = "";
88
+ }
89
+ }
90
+ //# sourceMappingURL=InteractiveInputHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InteractiveInputHandler.js","sourceRoot":"","sources":["../../src/input/InteractiveInputHandler.ts"],"names":[],"mappings":"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"}
File without changes
@@ -0,0 +1,40 @@
1
+ import { t } from "../util/Util";
2
+ import { Renderable } from "../util/Rendering";
3
+ /**
4
+ * Base class for components that handle input from the user
5
+ */
6
+ export class UserInputHandler extends Renderable {
7
+ /**
8
+ * Construct a new UserInputHandler
9
+ * @param {function()} inputCallback Callback for when the user has entered a value
10
+ */
11
+ constructor(inputCallback) {
12
+ super();
13
+ this.waiting = false;
14
+ this.inputCallback = inputCallback;
15
+ }
16
+ /**
17
+ * Wait for input of the user for a certain prompt
18
+ * @param {boolean} waiting Whether we are waiting for input
19
+ * @param {string} prompt Optional message to display if waiting
20
+ */
21
+ waitWithPrompt(waiting, prompt = "") {
22
+ this.waiting = waiting;
23
+ this.setPlaceholder(prompt || t(`Papyros.input_placeholder.${this.getInputMode()}`));
24
+ if (this.waiting) {
25
+ // Focusing is a rendering operation
26
+ // Subclasses can execute code after this operation, skipping the rendering
27
+ // Using setTimeout ensures rendering will be done when the main thread has time
28
+ // eslint-disable-next-line max-len
29
+ // More info here: https://stackoverflow.com/questions/1096436/document-getelementbyidid-focus-is-not-working-for-firefox-or-chrome
30
+ setTimeout(() => this.focus(), 0);
31
+ }
32
+ }
33
+ /**
34
+ * Helper method to reset internal state
35
+ */
36
+ reset() {
37
+ this.waiting = false;
38
+ }
39
+ }
40
+ //# sourceMappingURL=UserInputHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserInputHandler.js","sourceRoot":"","sources":["../../src/input/UserInputHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;GAEG;AACH,MAAM,OAAgB,gBAAiB,SAAQ,UAAqC;IAUhF;;;OAGG;IACH,YAAY,aAAqC;QAC7C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACvC,CAAC;IA6CD;;;;OAIG;IACI,cAAc,CAAC,OAAgB,EAAE,MAAM,GAAG,EAAE;QAC/C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,CAAC,6BAA6B,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;QACrF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,oCAAoC;YACpC,2EAA2E;YAC3E,gFAAgF;YAChF,mCAAmC;YACnC,mIAAmI;YACnI,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;IAED;;OAEG;IACO,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;CACJ"}
File without changes
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Draw a spinning circle to represent a loading animation
3
+ * @param {string} id HTML id for this element
4
+ * @param {string} borderColors The tailwind color classes for the borders of the circle
5
+ * @return {string} A string representation of the circle
6
+ */
7
+ export function renderSpinningCircle(id, borderColors) {
8
+ return `
9
+ <div id="${id}" class="_tw-animate-spin _tw-rounded-full ${borderColors}
10
+ _tw-border-2 _tw-h-[20px] _tw-w-[20px] _tw-mr-3"></div>`;
11
+ }
12
+ /**
13
+ * Wrap text (best a single character) in a circle to provide information to the user
14
+ * @param {string} content The symbol in the circle, e.g. ? of !
15
+ * @param {string} title The information to display when hovering over the element
16
+ * @param {string} colorClasses The classes to color the content
17
+ * @return {string} A string representation of the circle with content
18
+ */
19
+ export function renderInCircle(content, title, colorClasses) {
20
+ const htmlTitle = title ? `title="${title}"` : "";
21
+ return `<span ${htmlTitle} class="_tw-display-block _tw-font-bold _tw-text-center
22
+ _tw-w-[10px] _tw-h-[10px] _tw-rounded-full _tw-px-1 _tw-mx-1
23
+ _tw-bg-white-500 _tw-border-2 ${colorClasses}">${content}</span>`;
24
+ }
25
+ //# sourceMappingURL=HTMLShapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HTMLShapes.js","sourceRoot":"","sources":["../../src/util/HTMLShapes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAU,EAAE,YAAoB;IACjE,OAAO;WACA,EAAE,8CAA8C,YAAY;yDACd,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAAa,EAAE,YAAoB;IAC/E,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,OAAO,SAAS,SAAS;;oCAEO,YAAY,KAAK,OAAO,SAAS,CAAC;AACtE,CAAC"}
File without changes
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Enum representing the importance of a log message
3
+ * This is helpful for debugging while allowing filtering in production
4
+ */
5
+ export var LogType;
6
+ (function (LogType) {
7
+ LogType[LogType["Debug"] = 0] = "Debug";
8
+ LogType[LogType["Error"] = 1] = "Error";
9
+ LogType[LogType["Important"] = 2] = "Important";
10
+ })(LogType || (LogType = {}));
11
+ const ENVIRONMENT = process.env.NODE_ENV || "development";
12
+ // Log everything in development
13
+ const SHOULD_LOG = ENVIRONMENT !== "production";
14
+ /**
15
+ * Helper method to log useful information at runtime
16
+ * @param {LogType} logType The importance of this log message
17
+ * @param {any[]} args The data to log
18
+ */
19
+ export function papyrosLog(logType, ...args) {
20
+ const doLog = SHOULD_LOG || logType !== LogType.Debug;
21
+ if (doLog) {
22
+ if (logType === LogType.Error) {
23
+ console.error(...args);
24
+ }
25
+ else {
26
+ console.log(...args);
27
+ }
28
+ }
29
+ }
30
+ //# sourceMappingURL=Logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logging.js","sourceRoot":"","sources":["../../src/util/Logging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAN,IAAY,OAEX;AAFD,WAAY,OAAO;IACf,uCAAK,CAAA;IAAE,uCAAK,CAAA;IAAE,+CAAS,CAAA;AAC3B,CAAC,EAFW,OAAO,KAAP,OAAO,QAElB;AAED,MAAM,WAAW,GAAW,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;AAClE,gCAAgC;AAChC,MAAM,UAAU,GAAG,WAAW,KAAK,YAAY,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB,EAAE,GAAG,IAAW;IACvD,MAAM,KAAK,GAAG,UAAU,IAAI,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC;IACtD,IAAI,KAAK,EAAE,CAAC;QACR,IAAI,OAAO,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;AACL,CAAC"}
File without changes
@@ -0,0 +1,139 @@
1
+ /* eslint-disable max-len */
2
+ import { getElement } from "./Util";
3
+ import escapeHTML from "escape-html";
4
+ /**
5
+ * Helper method to append classes to the class attribute of an HTMLElement
6
+ * as consecutive whitespace is not allowed
7
+ * @param {Object} options Object containing classNames
8
+ * @param {string} classNames The classes to append
9
+ */
10
+ export function appendClasses(options, classNames) {
11
+ if (options.classNames && !options.classNames.includes(classNames)) {
12
+ options.classNames = `${options.classNames} ${classNames}`;
13
+ }
14
+ else {
15
+ options.classNames = classNames;
16
+ }
17
+ }
18
+ /**
19
+ * Helper method to add attributes to options with a possibly undefined attribute Map
20
+ * @param {Object} options Object containing attributes
21
+ * @param {Map<string, string>} attributes The attributes to add
22
+ */
23
+ export function addAttributes(options, attributes) {
24
+ options.attributes = new Map([
25
+ ...(options.attributes || []),
26
+ ...attributes
27
+ ]);
28
+ }
29
+ /**
30
+ * Renders an element with the given options
31
+ * @param {RenderOptions} options Options to be used while rendering
32
+ * @param {string | HTMLElement} content What to fill the parent with.
33
+ * If the content is a string, it should be properly formatted HTML
34
+ * @return {HTMLElement} The parent with the new child
35
+ */
36
+ export function renderWithOptions(options, content) {
37
+ const parent = getElement(options.parentElementId);
38
+ if (options.classNames) {
39
+ parent.classList.add(...options.classNames.split(" "));
40
+ }
41
+ parent.classList.toggle("_tw-dark", Boolean(options.darkMode));
42
+ if (options.attributes) {
43
+ for (const [attr, value] of options.attributes.entries()) {
44
+ parent.setAttribute(attr, value);
45
+ }
46
+ }
47
+ if (typeof content === "string") {
48
+ parent.innerHTML = content;
49
+ }
50
+ else {
51
+ parent.replaceChildren(content);
52
+ }
53
+ return parent;
54
+ }
55
+ /**
56
+ * Construct a HTML button string from the given options
57
+ * @param {ButtonOptions} options The options for the button
58
+ * @return {string} HTML string for the button
59
+ */
60
+ export function renderButton(options) {
61
+ appendClasses(options, "papyros-button");
62
+ return `
63
+ <button id="${options.id}" type="button"
64
+ class="${options.classNames}">
65
+ ${options.buttonText}
66
+ </button>`;
67
+ }
68
+ /**
69
+ * Constructs the options for use within an HTML select element
70
+ * @param {Array<T>} options All options to display in the list
71
+ * @param {function(T):string} optionText Function to convert the elements to a string
72
+ * @param {T} selected The initially selected element in the list, if any
73
+ * @return {string} The string representation of the select options
74
+ */
75
+ export function renderSelectOptions(options, optionText, selected) {
76
+ return options.map((option) => {
77
+ const selectedValue = option === selected ? "selected" : "";
78
+ return `
79
+ <option ${selectedValue} value="${escapeHTML(option)}" class="dark:_tw-text-white dark:_tw-bg-dark-mode-bg">
80
+ ${optionText(option)}
81
+ </option>
82
+ `;
83
+ }).join("\n");
84
+ }
85
+ /**
86
+ * Build a string representation of an HTML label element
87
+ * @param {string} labelText Optional text to display in a label
88
+ * If not provided, no label is created
89
+ * @param {string} forElement The id of the element this label is for
90
+ * @return {string} The HTML string of the label
91
+ */
92
+ export function renderLabel(labelText, forElement) {
93
+ return labelText ? `
94
+ <label for="${forElement}"
95
+ class="dark:_tw-text-white dark:_tw-bg-dark-mode-bg _tw-px-1">${labelText}: </label>` : "";
96
+ }
97
+ /**
98
+ * Constructs an HTML select element
99
+ * @param {string} selectId The HTML id for the element
100
+ * @param {Array<T>} options to display in the list
101
+ * @param {function(T):string} optionText to convert elements to a string
102
+ * @param {T} selected The initially selected element in the list, if any
103
+ * @param {string} labelText Optional text to display in a label
104
+ * @return {string} The string representation of the select element
105
+ */
106
+ export function renderSelect(selectId, options, optionText, selected, labelText) {
107
+ const select = `
108
+ <select id="${selectId}" class="_tw-m-2 _tw-border-2 _tw-px-1 _tw-rounded-lg
109
+ dark:_tw-text-white dark:_tw-bg-dark-mode-bg dark:_tw-border-dark-mode-content">
110
+ ${renderSelectOptions(options, optionText, selected)}
111
+ </select>`;
112
+ return `
113
+ ${renderLabel(labelText, selectId)}
114
+ ${select}
115
+ `;
116
+ }
117
+ /**
118
+ * Helper superclass to handle storing options used during rendering
119
+ * to allow re-rendering without needing to explicitly store used options each time
120
+ */
121
+ export class Renderable {
122
+ get renderOptions() {
123
+ if (!this._renderOptions) {
124
+ throw new Error(`${this.constructor.name} not yet rendered!`);
125
+ }
126
+ return this._renderOptions;
127
+ }
128
+ /**
129
+ * Render this component into the DOM
130
+ * @param {Options} options Optional options to render with. If omitted, stored options are used
131
+ */
132
+ render(options) {
133
+ if (options) {
134
+ this._renderOptions = options;
135
+ }
136
+ this._render(this.renderOptions);
137
+ }
138
+ }
139
+ //# sourceMappingURL=Rendering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rendering.js","sourceRoot":"","sources":["../../src/util/Rendering.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ export declare function getLocales(): Array<string>;
8
8
  /**
9
9
  * Helper type to access a HTML element, either via its id or the element itself
10
10
  */
11
- declare type ElementIdentifier = string | HTMLElement;
11
+ type ElementIdentifier = string | HTMLElement;
12
12
  /**
13
13
  * Resolve an ElementIdentifier to the corresponding HTLMElement
14
14
  * @param {ElementIdentifier} elementId The identifier for the element
@@ -0,0 +1,148 @@
1
+ import I18n from "i18n-js";
2
+ import { TRANSLATIONS } from "../Translations";
3
+ import { LogType, papyrosLog } from "./Logging";
4
+ // Shorthand for ease of use
5
+ export const t = I18n.t;
6
+ /**
7
+ * Add the translations for Papyros to the I18n instance
8
+ */
9
+ export function loadTranslations() {
10
+ for (const [language, translations] of Object.entries(TRANSLATIONS)) {
11
+ // Add keys to already existing translations if they exist
12
+ I18n.translations[language] = Object.assign((I18n.translations[language] || {}), translations);
13
+ }
14
+ }
15
+ export function getLocales() {
16
+ return Object.keys(TRANSLATIONS);
17
+ }
18
+ /**
19
+ * Resolve an ElementIdentifier to the corresponding HTLMElement
20
+ * @param {ElementIdentifier} elementId The identifier for the element
21
+ * @return {T} The corresponding element
22
+ */
23
+ export function getElement(elementId) {
24
+ if (typeof elementId === "string") {
25
+ return document.getElementById(elementId);
26
+ }
27
+ else {
28
+ return elementId;
29
+ }
30
+ }
31
+ /**
32
+ * Add a listener to an HTML element for an event on an attribute
33
+ * Element attributes tend to be strings, but string Enums can also be used
34
+ * by using the type-parameter T
35
+ * @param {ElementIdentifier} elementId Identifier for the element
36
+ * @param {function(T)} onEvent The listener for the event
37
+ * @param {string} eventType The type of the event
38
+ * @param {string} attribute The attribute affected by the event
39
+ */
40
+ export function addListener(elementId, onEvent, eventType = "change", attribute = "value") {
41
+ const element = getElement(elementId);
42
+ element.addEventListener(eventType, () => {
43
+ onEvent(element[attribute] || element.getAttribute(attribute));
44
+ });
45
+ }
46
+ /**
47
+ * Unset the selected item of a select element to prevent a default selection
48
+ * @param {ElementIdentifier} selectId Identifier for the select element
49
+ */
50
+ export function removeSelection(selectId) {
51
+ getElement(selectId).selectedIndex = -1;
52
+ }
53
+ /**
54
+ * Parse the data contained within a PapyrosEvent using its contentType
55
+ * Supported content types are: text/plain, text/json, img/png;base64
56
+ * @param {string} data The data to parse
57
+ * @param {string} contentType The content type of the data
58
+ * @return {any} The parsed data
59
+ */
60
+ export function parseData(data, contentType) {
61
+ if (!contentType) {
62
+ return data;
63
+ }
64
+ const [baseType, specificType] = contentType.split("/");
65
+ switch (baseType) {
66
+ case "text": {
67
+ switch (specificType) {
68
+ case "plain": {
69
+ return data;
70
+ }
71
+ case "json": {
72
+ return JSON.parse(data);
73
+ }
74
+ case "integer": {
75
+ return parseInt(data);
76
+ }
77
+ case "float": {
78
+ return parseFloat(data);
79
+ }
80
+ }
81
+ break;
82
+ }
83
+ case "img": {
84
+ switch (specificType) {
85
+ case "png;base64": {
86
+ return data;
87
+ }
88
+ }
89
+ break;
90
+ }
91
+ case "application": {
92
+ // Content such as application/json does not need parsing as it is in the correct shape
93
+ return data;
94
+ }
95
+ }
96
+ papyrosLog(LogType.Important, `Unhandled content type: ${contentType}`);
97
+ return data;
98
+ }
99
+ export function downloadResults(data, filename) {
100
+ const blob = new Blob([data], { type: "text/plain" });
101
+ const elem = window.document.createElement("a");
102
+ // Cast URL to any as TypeScript doesn't recognize it properly
103
+ // error TS2339: Property 'revokeObjectURL' does not exist on type
104
+ const windowUrl = URL;
105
+ elem.href = windowUrl.createObjectURL(blob);
106
+ elem.download = filename;
107
+ document.body.appendChild(elem);
108
+ elem.click();
109
+ document.body.removeChild(elem);
110
+ windowUrl.revokeObjectURL(elem.href);
111
+ }
112
+ /**
113
+ * Obtain the url of the current page without hashes, identifiers, query params, ...
114
+ * @param {boolean} endingSlash Whether the url should end in a slash
115
+ * @return {string} The current url
116
+ */
117
+ export function cleanCurrentUrl(endingSlash = false) {
118
+ let url = location.origin + location.pathname;
119
+ if (endingSlash && !url.endsWith("/")) {
120
+ url += "/";
121
+ }
122
+ else if (!endingSlash && url.endsWith("/")) {
123
+ url = url.slice(0, url.length - 1);
124
+ }
125
+ return url;
126
+ }
127
+ /**
128
+ * Focus an element, setting the user's caret at the end of the contents
129
+ * Needed to ensure focusing a contenteditable element works as expected
130
+ * @param {HTMLElement} el The element to focus
131
+ */
132
+ export function placeCaretAtEnd(el) {
133
+ // eslint-disable-next-line max-len
134
+ // Source: https://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
135
+ el.focus();
136
+ if (typeof window.getSelection !== "undefined" &&
137
+ typeof document.createRange !== "undefined") {
138
+ const range = document.createRange();
139
+ range.selectNodeContents(el);
140
+ range.collapse(false);
141
+ const sel = window.getSelection();
142
+ if (sel) {
143
+ sel.removeAllRanges();
144
+ sel.addRange(range);
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=Util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Util.js","sourceRoot":"","sources":["../../src/util/Util.ts"],"names":[],"mappings":"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"}
File without changes
@@ -1 +1,63 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Papyros=t():e.Papyros=t()}(self,(()=>(()=>{var e={137:e=>{self,e.exports=(()=>{"use strict";var e={d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{isServiceWorkerRequest:()=>s,serviceWorkerFetchListener:()=>i,asyncSleep:()=>u,ServiceWorkerError:()=>c,writeMessageAtomics:()=>a,writeMessageServiceWorker:()=>f,writeMessage:()=>d,makeChannel:()=>l,makeAtomicsChannel:()=>y,makeServiceWorkerChannel:()=>p,readMessage:()=>h,syncSleep:()=>v,uuidv4:()=>g});var r=function(e,t,r,n){return new(r||(r=Promise))((function(o,s){function i(e){try{c(n.next(e))}catch(e){s(e)}}function u(e){try{c(n.throw(e))}catch(e){s(e)}}function c(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,u)}c((n=n.apply(e,t||[])).next())}))};const n="__SyncMessageServiceWorkerInput__",o="__sync-message-v2__";function s(e){return"string"!=typeof e&&(e=e.request.url),e.includes(n)}function i(){const e={},t={};return n=>{const{url:i}=n.request;return!!s(i)&&(n.respondWith(function(){return r(this,void 0,void 0,(function*(){function r(e){const t={message:e,version:o};return new Response(JSON.stringify(t),{status:200})}if(i.endsWith("/read")){const{messageId:o,timeout:s}=yield n.request.json(),i=e[o];return i?(delete e[o],r(i)):yield new Promise((e=>{t[o]=e,setTimeout((function(){delete t[o],e(new Response("",{status:408}))}),s)}))}if(i.endsWith("/write")){const{message:o,messageId:s}=yield n.request.json(),i=t[s];return i?(i(r(o)),delete t[s]):e[s]=o,r({early:!i})}if(i.endsWith("/version"))return new Response(o,{status:200})}))}()),!0)}}function u(e){return new Promise((t=>setTimeout(t,e)))}class c extends Error{constructor(e,t){super(`Received status ${t} from ${e}. Ensure the service worker is registered and active.`),this.url=e,this.status=t,this.type="ServiceWorkerError",Object.setPrototypeOf(this,c.prototype)}}function a(e,t){const r=(new TextEncoder).encode(JSON.stringify(t)),{data:n,meta:o}=e;if(r.length>n.length)throw new Error("Message is too big, increase bufferSize when making channel.");n.set(r,0),Atomics.store(o,0,r.length),Atomics.store(o,1,1),Atomics.notify(o,1)}function f(e,t,n){return r(this,void 0,void 0,(function*(){yield navigator.serviceWorker.ready;const r=e.baseUrl+"/write",s=Date.now();for(;;){const i={message:t,messageId:n},a=yield fetch(r,{method:"POST",body:JSON.stringify(i)});if(200===a.status&&(yield a.json()).version===o)return;if(!(Date.now()-s<e.timeout))throw new c(r,a.status);yield u(100)}}))}function d(e,t,n){return r(this,void 0,void 0,(function*(){"atomics"===e.type?a(e,t):yield f(e,t,n)}))}function l(e={}){return"undefined"!=typeof SharedArrayBuffer?y(e.atomics):"serviceWorker"in navigator?p(e.serviceWorker):null}function y({bufferSize:e}={}){return{type:"atomics",data:new Uint8Array(new SharedArrayBuffer(e||131072)),meta:new Int32Array(new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT))}}function p(e={}){return{type:"serviceWorker",baseUrl:(e.scope||"/")+n,timeout:e.timeout||5e3}}function m(e,t){return e>0?+e:t}function h(e,t,{checkInterrupt:r,checkTimeout:n,timeout:s}={}){const i=performance.now();n=m(n,r?100:5e3);const u=m(s,Number.POSITIVE_INFINITY);let a;if("atomics"===e.type){const{data:t,meta:r}=e;a=()=>{if("timed-out"===Atomics.wait(r,1,0,n))return null;{const e=Atomics.exchange(r,0,0),n=t.slice(0,e);Atomics.store(r,1,0);const o=(new TextDecoder).decode(n);return JSON.parse(o)}}}else a=()=>{const r=new XMLHttpRequest,s=e.baseUrl+"/read";r.open("POST",s,!1);const u={messageId:t,timeout:n};r.send(JSON.stringify(u));const{status:a}=r;if(408===a)return null;if(200===a){const e=JSON.parse(r.responseText);return e.version!==o?null:e.message}if(performance.now()-i<e.timeout)return null;throw new c(s,a)};for(;;){const e=u-(performance.now()-i);if(e<=0)return null;n=Math.min(n,e);const t=a();if(null!==t)return t;if(null==r?void 0:r())return null}}function v(e,t){if(e=m(e,0))if("undefined"!=typeof SharedArrayBuffer){const t=new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));t[0]=0,Atomics.wait(t,0,0,e)}else h(t,`sleep ${e} ${g()}`,{timeout:e})}let g;return g="randomUUID"in crypto?function(){return crypto.randomUUID()}:function(){return"10000000-1000-4000-8000-100000000000".replace(/[018]/g,(e=>{const t=Number(e);return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)}))},t})()}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var s=t[n]={exports:{}};return e[n](s,s.exports,r),s.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.r(n),r.d(n,{InputWorker:()=>o});var e=r(137),t=function(e,t,r,n){return new(r||(r=Promise))((function(o,s){function i(e){try{c(n.next(e))}catch(e){s(e)}}function u(e){try{c(n.throw(e))}catch(e){s(e)}}function c(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,u)}c((n=n.apply(e,t||[])).next())}))};class o{constructor(t=""){this.hostName=t,this.syncMessageListener=(0,e.serviceWorkerFetchListener)()}handleInputRequest(e){return t(this,void 0,void 0,(function*(){if(this.syncMessageListener(e))return!0;const t=e.request.url;return!(!this.hostName||!t.includes(this.hostName))&&(e.respondWith(fetch(e.request).then((e=>{const t=new Headers(e.headers);t.set("Cross-Origin-Embedder-Policy","require-corp"),t.set("Cross-Origin-Opener-Policy","same-origin"),t.set("Cross-Origin-Resource-Policy","cross-origin");return new Response(e.body,{status:e.status||200,statusText:e.statusText,headers:t})}))),!0)}))}}})(),n})()));
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { serviceWorkerFetchListener } from "sync-message";
11
+ /**
12
+ * Class that is used in a service worker to allow synchronous communication
13
+ * between threads. This is achieved in two different ways.
14
+ * Responses can be modified by attaching headers allowing the use of shared memory.
15
+ * Requests to certain endpoints can be used with synchronous requests
16
+ * to achieve the same goal.
17
+ */
18
+ export class InputWorker {
19
+ /**
20
+ * Create a worker for a specific domain
21
+ * @param {string} hostName Optional name of the host domain
22
+ */
23
+ constructor(hostName = "") {
24
+ this.hostName = hostName;
25
+ this.syncMessageListener = serviceWorkerFetchListener();
26
+ }
27
+ /**
28
+ * Process and potentially handle a fetch request from the application
29
+ * @param {FetchEvent} event The event denoting a request to a url
30
+ * @return {boolean} Whether the event was handled
31
+ */
32
+ handleInputRequest(event) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ // Special requests targeted at getting input from the user
35
+ if (this.syncMessageListener(event)) {
36
+ return true;
37
+ }
38
+ const url = event.request.url;
39
+ if (this.hostName && url.includes(this.hostName)) { // requests to our own domain
40
+ event.respondWith(fetch(event.request)
41
+ .then(response => {
42
+ // Add new headers to be able to use SharedArrayBuffers
43
+ // if the browser supports them
44
+ const newHeaders = new Headers(response.headers);
45
+ newHeaders.set("Cross-Origin-Embedder-Policy", "require-corp");
46
+ newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
47
+ newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
48
+ const moddedResponse = new Response(response.body, {
49
+ status: response.status || 200,
50
+ statusText: response.statusText,
51
+ headers: newHeaders,
52
+ });
53
+ return moddedResponse;
54
+ }));
55
+ return true;
56
+ }
57
+ else {
58
+ return false;
59
+ }
60
+ });
61
+ }
62
+ }
63
+ //# sourceMappingURL=InputWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputWorker.js","sourceRoot":"","sources":["../../../src/workers/input/InputWorker.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,OAAO,WAAW;IAMpB;;;OAGG;IACH,YAAY,QAAQ,GAAG,EAAE;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,mBAAmB,GAAG,0BAA0B,EAAE,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACU,kBAAkB,CAAC,KAAiB;;YAC7C,2DAA2D;YAC3D,IAAI,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAC9B,IAAI,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,6BAA6B;gBAC7E,KAAK,CAAC,WAAW,CACb,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;qBACf,IAAI,CAAC,QAAQ,CAAC,EAAE;oBACb,uDAAuD;oBACvD,+BAA+B;oBAC/B,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBACjD,UAAU,CAAC,GAAG,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;oBAC/D,UAAU,CAAC,GAAG,CAAC,4BAA4B,EAAE,aAAa,CAAC,CAAC;oBAC5D,UAAU,CAAC,GAAG,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;oBAE/D,MAAM,cAAc,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;wBAC/C,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG;wBAC9B,UAAU,EAAE,QAAQ,CAAC,UAAU;wBAC/B,OAAO,EAAE,UAAU;qBACtB,CAAC,CAAC;oBACH,OAAO,cAAc,CAAC;gBAC1B,CAAC,CAAC,CAAC,CAAC;gBACZ,OAAO,IAAI,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACJ,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;KAAA;CACJ"}
@@ -0,0 +1,39 @@
1
+ import { Backend, WorkerDiagnostic } from "../../Backend";
2
+ import { SyncExtras } from "comsync";
3
+ /**
4
+ * Implementation of a JavaScript backend for Papyros
5
+ * by using eval and overriding some builtins
6
+ */
7
+ export declare class JavaScriptWorker extends Backend<SyncExtras> {
8
+ /**
9
+ * Convert varargs to a string, similar to how the console does it
10
+ * @param {any[]} args The values to join into a string
11
+ * @return {string} The string representation
12
+ */
13
+ private static stringify;
14
+ /**
15
+ * Prompt the user for input with a message
16
+ * @param {string} text The message to show when asking for input
17
+ * @return {string} The value the user gave
18
+ */
19
+ private prompt;
20
+ /**
21
+ * Print values to the output screen
22
+ * @param {any[]} args The values to log
23
+ */
24
+ private consoleLog;
25
+ /**
26
+ * Print values to the error screen
27
+ * @param {any[]} args The error values to log
28
+ */
29
+ private consoleError;
30
+ /**
31
+ * Helper method to generate suggestions based on properties in an object
32
+ * @param {number} from Where in the document the autocompletion starts
33
+ * @param {any} object Object with properties that might be relevant
34
+ * @return {CompletionResult} Autocompletion suggestions
35
+ */
36
+ private static completeProperties;
37
+ runCode(extras: SyncExtras, code: string): Promise<any>;
38
+ lintCode(): Promise<Array<WorkerDiagnostic>>;
39
+ }