From 399a80ed05e38e30c7fff52ebb74d8e6917f3f0f Mon Sep 17 00:00:00 2001 From: yoonieaj <144498960+yoonieaj@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:02:29 -0400 Subject: [PATCH] Add type annotations and Typescript interfaces (#41) --- CHANGELOG.md | 2 ++ memory-viz/src/automate.ts | 21 ++++++------ memory-viz/src/memory_model.ts | 3 +- memory-viz/src/style.ts | 57 ++++++++++++++++++++++---------- memory-viz/src/types.ts | 26 +++++++++++++++ memory-viz/src/user_functions.ts | 3 +- 6 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 memory-viz/src/types.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 68f347f3..4cb5f654 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added style and automatic layout tests for the `draw` function. - Updated documentation, tests, and examples to reflect the `isClass` attribute being optional and set to `false` by default. - Removed unused imports in `demo_C.js`. +- Added type interfaces and type annotations to `style.ts`. +- Added `DrawnEntity` type annotations to source code files. ## [0.1.0] - 2024-04-16 diff --git a/memory-viz/src/automate.ts b/memory-viz/src/automate.ts index 6dcf1357..cfb1d928 100644 --- a/memory-viz/src/automate.ts +++ b/memory-viz/src/automate.ts @@ -1,16 +1,17 @@ import { MemoryModel } from "./memory_model"; import { config } from "./config"; +import { DrawnEntity } from "./types"; /** * Draws the objects given in the path in an automated fashion. * - * @param {object[]} objects - The list of objects that will be drawn on the canvas. + * @param {DrawnEntity[]} objects - The list of objects that will be drawn on the canvas. * @param {Object} configuration - The configuration settings defined by the user. * @param {number} width - User-defined width of the canvas. * @returns {MemoryModel} - The memory model that is created according to the objects given in the path (the JSON * file) */ -function drawAutomated(objects, width, configuration) { +function drawAutomated(objects: DrawnEntity[], width, configuration) { const { stack_frames, other_items } = separateObjects(objects); // Assigning the objects with coordinates. @@ -43,14 +44,14 @@ function drawAutomated(objects, width, configuration) { * of the input such that the x and y coordinates of the stack-frames are determined automatically. * * @param {Object} configuration - The configuration set by the user. - * @param {Object[]} stack_frames - The list of stack-frames that will be drawn + * @param {DrawnEntity[]} stack_frames - The list of stack-frames that will be drawn * (without the specified x and y coordinates) * @returns {Object} - Returns the object consisting of three attributes as follows: stack-frames which will be drawn, * the minimum required height of the canvas for drawing stack frames and required width for drawing all the stack * frames. Notably, the last two attributes will be useful in terms of dynamically deciding the width and the height * of the canvas. */ -function drawAutomatedStackFrames(stack_frames, configuration) { +function drawAutomatedStackFrames(stack_frames: DrawnEntity[], configuration) { for (const req_prop of [ "padding", "top_margin", @@ -112,7 +113,7 @@ function drawAutomatedStackFrames(stack_frames, configuration) { * desired canvas width, this function mutates the passed list to equip each object with coordinates (corresponding to * the top-left corner of the object's box in the canvas). * - * @param {[object]} objs - list of objects in the format described in MemoryModel.drawAll + * @param {DrawnEntity[]} objs - list of objects in the format described in MemoryModel.drawAll * @param {number} max_width - the desired width of the canvas * @param {*} sort_by - the sorting criterion; must be "height" or "id", otherwise no sorting takes place. * @param {object} config_aut - additional configuration options, such as margins, paddings, e.t.c. @@ -122,7 +123,7 @@ function drawAutomatedStackFrames(stack_frames, configuration) { * dynamically determined height the canvas will need to be. */ function drawAutomatedOtherItems( - objs, + objs: DrawnEntity[], max_width, sort_by, config_aut: any = {} /* to avoid undefined error */, @@ -244,11 +245,11 @@ function drawAutomatedOtherItems( * The returned object has two attributes as 'stack_frames' and 'other_items'. * Each of these attributes are a list of objects that were originally given by the user. * - * @param {object[]} objects - The list of objects, including stack-frames (if any) and other items, that + * @param {DrawnEntity[]} objects - The list of objects, including stack-frames (if any) and other items, that * will be drawn * @returns {object} an object separating between stack-frames and the rest of the items. */ -function separateObjects(objects) { +function separateObjects(objects: DrawnEntity[]) { let stackFrames = []; let otherItems = []; @@ -278,10 +279,10 @@ function separateObjects(objects) { * Return the dimensions that the passed object will have if drawn on a canvas (in the context of the MemoryModel class). * This function can be used to determine how much space an object box will take on canvas (like a dry-run), given the * implementations of the 'draw' methods in MemoryModel. - * @param {object} obj - an object as specified in MemoryModel.drawAll, except that coordinates are missing. + * @param {DrawnEntity} obj - an object as specified in MemoryModel.drawAll, except that coordinates are missing. * @returns {object} the width and the height the drawn object would have. */ -function getSize(obj) { +function getSize(obj: DrawnEntity) { // The x and y values here are unimportant; 'obj' must simply have these properties for processing by 'drawAll'. obj.x = obj.x || 10; obj.y = obj.y || 10; diff --git a/memory-viz/src/memory_model.ts b/memory-viz/src/memory_model.ts index a9b73d2e..3dcdc16b 100644 --- a/memory-viz/src/memory_model.ts +++ b/memory-viz/src/memory_model.ts @@ -11,6 +11,7 @@ import { } from "./style"; import { config } from "./config"; import { DOMImplementation, XMLSerializer } from "@xmldom/xmldom"; +import { DrawnEntity } from "./types"; // Dynamic import of Node fs module let fs; @@ -758,7 +759,7 @@ export class MemoryModel { /** * Create a MemoryModel given a list of JS objects. * - * @param {object[]} objects - the list of objects (including stack-frames) to be drawn. + * @param {DrawnEntity[]} objects - the list of objects (including stack-frames) to be drawn. * Each object in 'objects' must include the following structure: * @param {number} objects[*].x - Value for x coordinate of top left corner * @param {number} objects[*].y - Value for y coordinate of top left corner diff --git a/memory-viz/src/style.ts b/memory-viz/src/style.ts index d66afd02..a3d6abb3 100644 --- a/memory-viz/src/style.ts +++ b/memory-viz/src/style.ts @@ -1,8 +1,9 @@ import merge from "deepmerge"; import { config } from "./config"; +import { DrawnEntity, AttributeStyle, Style } from "./types"; // Built-in style for drawing text on canvas (if no style is provided by the user). -const default_text_style = { +const default_text_style: AttributeStyle = { fill: config.text_color, "text-anchor": "middle", "font-family": "Consolas, Courier", @@ -10,7 +11,7 @@ const default_text_style = { }; // Default style attributes that apply universally to any type of data. -const common_style = { +const common_style: Style = { text_id: { fill: config.id_color, "text-anchor": "middle", @@ -33,7 +34,7 @@ const common_style = { box_type: {}, }; -const category_specific_styles = { +const category_specific_styles: Record = { collection: { text_value: { fill: config.id_color }, }, @@ -48,22 +49,37 @@ const category_specific_styles = { }, }; -const immutable = ["int", "str", "tuple", "None", "bool", "float", "date"]; -const collections = ["list", "set", "tuple", "dict"]; +const immutable: Array = [ + "int", + "str", + "tuple", + "None", + "bool", + "float", + "date", +]; +const collections: Array = ["list", "set", "tuple", "dict"]; -const primitives = ["int", "str", "None", "bool", "float", "date"]; +const primitives: Array = [ + "int", + "str", + "None", + "bool", + "float", + "date", +]; /** * Populates a user-passed style object --to the extent needed-- with default data (to adhere to the interface of the * style object). Needed to avoid errors of the type "TypeError: Cannot set properties of undefined (setting 'x')", as * well as many more. - * @param {Object} object : the object that represents a Python object the user wants drawn. The style object + * @param {DrawnEntity} object : the object that represents a Python object the user wants drawn. The style object * corresponding to 'object' will be extracted be doing object.style. * @param {Number} seed : a numeric seed. If valued between 1 and 2^31, RoughJS will generate the exact same shape(s) * when provided with the same seed. If valued at 0, RoughJS will generate random shape(s). - * @returns {Object} + * @returns {Style} */ -function populateStyleObject(object, seed) { +function populateStyleObject(object: DrawnEntity, seed: Number) { let style_so_far = common_style; let object_type; @@ -90,26 +106,31 @@ function populateStyleObject(object, seed) { } // Constants employed to establish presets for styles. -const HIGHLIGHT_TEXT = { "font-weight": "bolder", "font-size": "22px" }; -const FADE_TEXT = { /*'font-weight': "normal",*/ "fill-opacity": 0.4 }; -const HIDE_TEXT = { "fill-opacity": 0 }; -const HIGHLIGHT_BOX_LINES = { roughness: 0.2, strokeWidth: 4 }; -const HIGHLIGHT_BOX = { +const HIGHLIGHT_TEXT: AttributeStyle = { + "font-weight": "bolder", + "font-size": "22px", +}; +const FADE_TEXT: AttributeStyle = { + /*'font-weight': "normal",*/ "fill-opacity": 0.4, +}; +const HIDE_TEXT: AttributeStyle = { "fill-opacity": 0 }; +const HIGHLIGHT_BOX_LINES: AttributeStyle = { roughness: 0.2, strokeWidth: 4 }; +const HIGHLIGHT_BOX: AttributeStyle = { roughness: 0.2, strokeWidth: 4, fill: "yellow", fillStyle: "solid", }; -const FADE_BOX_LINES = { roughness: 2.0, strokeWidth: 0.5 }; -const FADE_BOX = { +const FADE_BOX_LINES: AttributeStyle = { roughness: 2.0, strokeWidth: 0.5 }; +const FADE_BOX: AttributeStyle = { roughness: 2.0, strokeWidth: 0.5, fill: "rgb(247, 247, 247)", fillStyle: "solid", }; -const HIDE_BOX = { fill: "white", fillStyle: "solid" }; +const HIDE_BOX: AttributeStyle = { fill: "white", fillStyle: "solid" }; -const presets = { +const presets: Record = { highlight: { text_value: HIGHLIGHT_TEXT, text_id: HIGHLIGHT_TEXT, diff --git a/memory-viz/src/types.ts b/memory-viz/src/types.ts new file mode 100644 index 00000000..5608cb93 --- /dev/null +++ b/memory-viz/src/types.ts @@ -0,0 +1,26 @@ +export interface DrawnEntity { + name?: string; + type?: string; + x?: number; + y?: number; + id: number | string; + value: any; + show_indexes?: boolean; + style?: Style; + height?: number; + width?: number; + rowBreaker?: boolean; +} + +export interface AttributeStyle { + [propName: string]: string | number; +} + +export interface Style { + text_id?: AttributeStyle; + text_type?: AttributeStyle; + text_value?: AttributeStyle; + box_id?: AttributeStyle; + box_type?: AttributeStyle; + box_container?: AttributeStyle; +} diff --git a/memory-viz/src/user_functions.ts b/memory-viz/src/user_functions.ts index dd9d1ee8..e4e97fac 100644 --- a/memory-viz/src/user_functions.ts +++ b/memory-viz/src/user_functions.ts @@ -1,5 +1,6 @@ import { MemoryModel } from "./memory_model"; import { drawAutomated, getSize } from "./automate"; +import { DrawnEntity } from "./types"; // Dynamic import of Node fs module let fs; @@ -12,7 +13,7 @@ if (typeof window === "undefined") { * * The format of the array of objects must adhere to the description provided in MemoryModel.drawAll. * - * @param {string | object[]} objects - The array of objects to be drawn: this could be passed as an actual JavaScript + * @param {string | DrawnEntity[]} objects - The array of objects to be drawn: this could be passed as an actual JavaScript * array of objects, or as a JSON file containing the object array. This array of objects may also include the * user-defined style configuration. See the demo files and style.md file for details. * @param {boolean} automation - Whether the coordinates (of the objects on the canvas) should be automatically