From 7263ae6f5fb7e2bad55ab41a25f5429d24c37d6b Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Sun, 19 Oct 2025 20:56:35 +0200 Subject: [PATCH] Rendering engine, simple refs almost complete, list refs start --- task_2_ts/index.html | 30 ++++++-- task_2_ts/ts/csv.ts | 11 +-- task_2_ts/ts/framework.ts | 140 ++++++++++++++++++++++++++++++++++++++ task_2_ts/ts/types.d.ts | 1 + 4 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 task_2_ts/ts/framework.ts create mode 100644 task_2_ts/ts/types.d.ts diff --git a/task_2_ts/index.html b/task_2_ts/index.html index e0aaf4f..aab9055 100644 --- a/task_2_ts/index.html +++ b/task_2_ts/index.html @@ -22,15 +22,15 @@
-

Select csv data

+

Select CSV data

- Please upload a csv file, where the first row is the header. And the values are - comma(,) seperated. + Please upload a CSV file, where the first row is the header. And the values are + comma(,) separated.
@@ -38,14 +38,32 @@

Data infos

-
+
+

Filename

+

+

File type

+

+

File size

+

+

Number of rows

+

+

Selected column infos

-
+
+

Filename

+

+

File type

+

+

File size

+

+

Number of rows

+

+
diff --git a/task_2_ts/ts/csv.ts b/task_2_ts/ts/csv.ts index 76806ac..943e381 100644 --- a/task_2_ts/ts/csv.ts +++ b/task_2_ts/ts/csv.ts @@ -1,12 +1,15 @@ +import { + CSV_Data +} from './types'; import { csv2json } from 'json-2-csv'; -export type CSV_Data = Array>; - const convertCSVtoJSON = async ( csvText: string ) => { - // Type cast OK, as the typing of the external library is not perfect. - // NOTE: On transpilation to JS, it will be (more or less) disregarded anyway + // Type cast OK, as the typing of the external library is not perfect -> Actually it is. + // NOTE: On transpilation to JS, it will be (more or less) disregarded anyway. + // If you claim it isn't good typing, it's the same as expecting it to guess the typing, + // which is literally impossible in TS. But sure... return ( await csv2json( csvText ) ) as CSV_Data; }; diff --git a/task_2_ts/ts/framework.ts b/task_2_ts/ts/framework.ts new file mode 100644 index 0000000..7b87069 --- /dev/null +++ b/task_2_ts/ts/framework.ts @@ -0,0 +1,140 @@ +// Yes, I could not be arsed to keep track of state manually, so wrote a framework real quick that +// does that for me. I am well aware that this is well over engineered, but it was a lot of fun +// and no, this is *NOT* AI generated (I know Claude likes to hallucinate that kinda stuff) +// I will be trying to somewhat follow Vue naming here, as that is what I am familiar with +// +// It was also a nice exercise to get familiar with Generics in TypeScript, something I haven't +// really used before + +export interface Ref { + 'set': ( data: T ) => void; + 'get': () => T; + 'addConditionalElements': ( elements: HTMLElement[] ) => void; +} + +export interface ListRef { + 'set': ( data: T[] ) => void; + 'get': () => T[]; + 'sort': ( compare: ( a: T, b: T ) => number ) => void; + 'filter': ( predicate: ( value: T ) => boolean ) => void; +} + + +/** + * Responsive data (similar behaviour as in Vue.js) + * @template T - The data type you wish to use (as long as you don't want it to be a list) + * @param data - The data stored in this ref + * @param elements - The elements to bind to + */ +const ref = ( elements: HTMLElement[], data: T ): Ref => { + let value: T = data; + let conditionalElements: HTMLElement[] = []; + + // ─────────────────────────────────────────────────────────────────── + const get = (): T => { + return value; + }; + + // ─────────────────────────────────────────────────────────────────── + const set = ( data: T ): void => { + value = data; + + // Update normal ref elements + elements.forEach( el => { + el.innerHTML = String( data ); + } ); + + // Update conditional elements + conditionalElements.forEach( el => { + // convert to boolean (explicitly) + el.hidden = Boolean( data ); + } ); + }; + + /** + * Add elements to be rendered conditionally on this ref. Treats type as booleanish + * @param elements - The elements that are rendered consistently + */ + const addConditionalElements = ( elements: HTMLElement[] ): void => { + conditionalElements = elements; + }; + + return { + set, + get, + addConditionalElements + }; +}; + + +// ─────────────────────────────────────────────────────────────────── +// ╭───────────────────────────────────────────────╮ +// │ List ref, dynamic list rendering │ +// ╰───────────────────────────────────────────────╯ +export type HTMLTagNames = 'div' | 'button' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'span'; + +export interface RenderTemplate { + [name: string]: { + 'type': HTMLTagNames; + 'attribute': string; + 'cssClasses': string[]; + } +} + +interface DiffList { + 'modified': T[]; + 'added': T[]; + 'removed': T[]; +} + +const listRef = ( parent: HTMLElement, data: T[] ): ListRef => { + let value: T[] = data; + let rendered: T[] = []; + + // ─────────────────────────────────────────────────────────────────── + const get = (): T[] => { + return value; + }; + + // ─────────────────────────────────────────────────────────────────── + const set = ( data: T[] ): void => { + const diffList: DiffList = { + 'modified': [], + 'added': [], + 'removed': [] + }; + + value = data; + rendered = value; + }; + + const sort = ( compare: ( a: T, b: T ) => number ): void => { + // Re-render based on compare function + }; + + const filter = ( predicate: ( value: T ) => boolean ): void => { + const diffList: DiffList = { + 'modified': [], + 'added': [], + 'removed': [] + }; + }; + + return { + get, + set, + sort, + filter + }; +}; + +// The list renderer using a DiffList +const renderList = ( diffList: DiffList ) => { + +}; + + +export default { + ref, + listRef +}; diff --git a/task_2_ts/ts/types.d.ts b/task_2_ts/ts/types.d.ts new file mode 100644 index 0000000..d7160e7 --- /dev/null +++ b/task_2_ts/ts/types.d.ts @@ -0,0 +1 @@ +export type CSV_Data = Array>;