FIX: Fixes types for TypeScript manually (#32)

This commit is contained in:
Nicolás Hatcher Andrés
2024-04-12 21:08:03 +02:00
committed by GitHub
parent 196e074ef5
commit b3b7dea930
5 changed files with 332 additions and 3 deletions

View File

@@ -1 +1 @@
target/* target/*

View File

@@ -1,6 +1,8 @@
all: all:
wasm-pack build --target web --scope ironcalc wasm-pack build --target web --scope ironcalc
cp README.pkg.md pkg/README.md cp README.pkg.md pkg/README.md
tsc types.ts --target esnext --module esnext
python fix_types.py
lint: lint:
cargo check cargo check
@@ -10,5 +12,6 @@ lint:
clean: clean:
cargo clean cargo clean
rm -rf pkg rm -rf pkg
rm -f types.js
.PHONY: all web lint .PHONY: all lint clean

View File

@@ -0,0 +1,97 @@
# Regrettably at the time of writing there is not a perfect way to
# generate the TypeScript types from Rust so we basically fix them manually
# Hopefully this will suffice for our needs and one day will be automatic
header = r"""
/* tslint:disable */
/* eslint-disable */
""".strip()
get_tokens_str = r"""
* @returns {any}
*/
export function getTokens(formula: string): any;
""".strip()
get_tokens_str_types = r"""
* @returns {TokenType[]}
*/
export function getTokens(formula: string): TokenType[];
""".strip()
update_style_str = r"""
/**
* @param {any} range
* @param {string} style_path
* @param {string} value
*/
updateRangeStyle(range: any, style_path: string, value: string): void;
""".strip()
update_style_str_types = r"""
/**
* @param {Area} range
* @param {string} style_path
* @param {string} value
*/
updateRangeStyle(range: Area, style_path: string, value: string): void;
""".strip()
properties = r"""
/**
* @returns {any}
*/
getWorksheetsProperties(): any;
""".strip()
properties_types = r"""
/**
* @returns {WorksheetProperties[]}
*/
getWorksheetsProperties(): WorksheetProperties[];
""".strip()
style = r"""
* @returns {any}
*/
getCellStyle(sheet: number, row: number, column: number): any;
""".strip()
style_types = r"""
* @returns {CellStyle}
*/
getCellStyle(sheet: number, row: number, column: number): CellStyle;
""".strip()
def fix_types(text):
text = text.replace(get_tokens_str, get_tokens_str_types)
text = text.replace(update_style_str, update_style_str_types)
text = text.replace(properties, properties_types)
text = text.replace(style, style_types)
with open("types.ts") as f:
types_str = f.read()
header_types = "{}\n\n{}".format(header, types_str)
text = text.replace(header, header_types)
return text
if __name__ == "__main__":
types_file = "pkg/wasm.d.ts"
with open(types_file) as f:
text = f.read()
text = fix_types(text)
with open(types_file, "wb") as f:
f.write(bytes(text, "utf8"))
js_file = "pkg/wasm.js"
with open("types.js") as f:
text_js = f.read()
with open(js_file) as f:
text = f.read()
with open(js_file, "wb") as f:
f.write(bytes("{}\n{}".format(text_js, text), "utf8"))

View File

@@ -3,11 +3,23 @@ use wasm_bindgen::{
JsValue, JsValue,
}; };
use ironcalc_base::{expressions::types::Area, UserModel as BaseModel}; use ironcalc_base::{
expressions::{lexer::util::get_tokens as tokenizer, types::Area},
types::CellType,
UserModel as BaseModel,
};
fn to_js_error(error: String) -> JsError { fn to_js_error(error: String) -> JsError {
JsError::new(&error.to_string()) JsError::new(&error.to_string())
} }
/// Return an array with a list of all the tokens from a formula
/// This is used by the UI to color them according to a theme.
#[wasm_bindgen(js_name = "getTokens")]
pub fn get_tokens(formula: &str) -> Result<JsValue, JsError> {
let tokens = tokenizer(formula);
serde_wasm_bindgen::to_value(&tokens).map_err(JsError::from)
}
#[wasm_bindgen] #[wasm_bindgen]
pub struct Model { pub struct Model {
model: BaseModel, model: BaseModel,
@@ -21,6 +33,11 @@ impl Model {
Ok(Model { model }) Ok(Model { model })
} }
pub fn from_bytes(bytes: &[u8]) -> Result<Model, JsError> {
let model = BaseModel::from_bytes(bytes).map_err(to_js_error)?;
Ok(Model { model })
}
pub fn undo(&mut self) -> Result<(), JsError> { pub fn undo(&mut self) -> Result<(), JsError> {
self.model.undo().map_err(to_js_error) self.model.undo().map_err(to_js_error)
} }
@@ -247,6 +264,24 @@ impl Model {
.map(|x| serde_wasm_bindgen::to_value(&x).unwrap()) .map(|x| serde_wasm_bindgen::to_value(&x).unwrap())
} }
#[wasm_bindgen(js_name = "getCellType")]
pub fn get_cell_type(&self, sheet: u32, row: i32, column: i32) -> Result<i32, JsError> {
Ok(
match self
.model
.get_cell_type(sheet, row, column)
.map_err(to_js_error)?
{
CellType::Number => 1,
CellType::Text => 2,
CellType::LogicalValue => 4,
CellType::ErrorValue => 16,
CellType::Array => 64,
CellType::CompoundData => 128,
},
)
}
#[wasm_bindgen(js_name = "getWorksheetsProperties")] #[wasm_bindgen(js_name = "getWorksheetsProperties")]
pub fn get_worksheets_properties(&self) -> JsValue { pub fn get_worksheets_properties(&self) -> JsValue {
serde_wasm_bindgen::to_value(&self.model.get_worksheets_properties()).unwrap() serde_wasm_bindgen::to_value(&self.model.get_worksheets_properties()).unwrap()

194
bindings/wasm/types.ts Normal file
View File

@@ -0,0 +1,194 @@
export interface Area {
sheet: number;
row: number;
column: number;
width: number;
height: number;
}
type ErrorType =
| "REF"
| "NAME"
| "VALUE"
| "DIV"
| "NA"
| "NUM"
| "ERROR"
| "NIMPL"
| "SPILL"
| "CALC"
| "CIRC";
type OpCompareType =
| "LessThan"
| "GreaterThan"
| "Equal"
| "LessOrEqualThan"
| "GreaterOrEqualThan"
| "NonEqual";
type OpSumType = "Add" | "Minus";
type OpProductType = "Times" | "Divide";
interface ReferenceType {
sheet: string | null;
row: number;
column: number;
absolute_column: boolean;
absolute_row: boolean;
}
interface ParsedReferenceType {
column: number;
row: number;
absolute_column: boolean;
absolute_row: boolean;
}
interface Reference {
Reference: ReferenceType;
}
interface Range {
Range: {
sheet: string | null;
left: ParsedReferenceType;
right: ParsedReferenceType;
};
}
export type TokenType =
| "Illegal"
| "Eof"
| { Ident: string }
| { String: string }
| { Boolean: boolean }
| { Number: number }
| { ERROR: ErrorType }
| { COMPARE: OpCompareType }
| { SUM: OpSumType }
| { PRODUCT: OpProductType }
| "POWER"
| "LPAREN"
| "RPAREN"
| "COLON"
| "SEMICOLON"
| "LBRACKET"
| "RBRACKET"
| "LBRACE"
| "RBRACE"
| "COMMA"
| "BANG"
| "PERCENT"
| "AND"
| Reference
| Range;
export interface MarkedToken {
token: TokenType;
start: number;
end: number;
}
export interface WorksheetProperties {
name: string;
color: string;
sheet_id: number;
}
interface CellStyleFill {
pattern_type: string;
fg_color?: string;
bg_color?: string;
}
interface CellStyleFont {
u: boolean;
b: boolean;
i: boolean;
strike: boolean;
sz: number;
color: string;
name: string;
family: number;
scheme: string;
}
export enum BorderType {
BorderAll,
BorderInner,
BorderCenterH,
BorderCenterV,
BorderOuter,
BorderNone,
BorderTop,
BorderRight,
BorderBottom,
BorderLeft,
None,
}
export interface BorderOptions {
color: string;
style: BorderStyle;
border: BorderType;
}
export enum BorderStyle {
Thin = "thin",
Medium = "medium",
Thick = "thick",
Dashed = "dashed",
Dotted = "dotted",
Double = "double",
None = "none",
}
interface BorderItem {
style: string;
color: string;
}
interface CellStyleBorder {
diagonal_up?: boolean;
diagonal_down?: boolean;
left: BorderItem;
right: BorderItem;
top: BorderItem;
bottom: BorderItem;
diagonal: BorderItem;
}
export type VerticalAlignment =
| "bottom"
| "center"
| "distributed"
| "justify"
| "top";
export type HorizontalAlignment =
| "left"
| "center"
| "right"
| "general"
| "centerContinuous"
| "distributed"
| "fill"
| "justify";
interface Alignment {
horizontal: HorizontalAlignment;
vertical: VerticalAlignment;
wrap_text: boolean;
}
export interface CellStyle {
read_only: boolean;
quote_prefix: boolean;
fill: CellStyleFill;
font: CellStyleFont;
border: CellStyleBorder;
num_fmt: string;
alignment?: Alignment;
}