Skip to content

Commit

Permalink
Add type annotations and Typescript interfaces (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
yoonieaj authored Jun 12, 2024
1 parent 5253853 commit 399a80e
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 30 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 11 additions & 10 deletions memory-viz/src/automate.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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.
Expand All @@ -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 */,
Expand Down Expand Up @@ -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 = [];

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion memory-viz/src/memory_model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
57 changes: 39 additions & 18 deletions memory-viz/src/style.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
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",
"font-size": config.font_size,
};

// 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",
Expand All @@ -33,7 +34,7 @@ const common_style = {
box_type: {},
};

const category_specific_styles = {
const category_specific_styles: Record<string, Style> = {
collection: {
text_value: { fill: config.id_color },
},
Expand All @@ -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<string> = [
"int",
"str",
"tuple",
"None",
"bool",
"float",
"date",
];
const collections: Array<string> = ["list", "set", "tuple", "dict"];

const primitives = ["int", "str", "None", "bool", "float", "date"];
const primitives: Array<string> = [
"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;
Expand All @@ -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<string, Style> = {
highlight: {
text_value: HIGHLIGHT_TEXT,
text_id: HIGHLIGHT_TEXT,
Expand Down
26 changes: 26 additions & 0 deletions memory-viz/src/types.ts
Original file line number Diff line number Diff line change
@@ -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;
}
3 changes: 2 additions & 1 deletion memory-viz/src/user_functions.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down

0 comments on commit 399a80e

Please sign in to comment.