Page MenuHomeSealhub

No OneTemporary

diff --git a/src/component-arguments.test.ts b/src/component-arguments.test.ts
index fcd7d08..8ccf591 100644
--- a/src/component-arguments.test.ts
+++ b/src/component-arguments.test.ts
@@ -1,63 +1,114 @@
import {
ComponentArgument,
Enum,
List,
MarkdownArgument,
+ Image,
ShortText,
Structured,
} from "./component-arguments";
import { Component } from "./component";
import assert from "assert";
describe("component arguments", () => {
it("handles nesting objects and arrays", () => {
new List(new ShortText());
new List(
new Structured({ name: new ShortText(), surname: new ShortText() })
);
});
it("handles enums", () => {
new Enum(<const>["hamster", "dentist"]);
});
it("Gives a nice example", () => {
new MarkdownArgument().getExampleValue();
const args = <const>{
text: new ShortText(),
markdown: new MarkdownArgument(),
};
const component = new (class testComponent extends Component<
typeof args
> {
getArguments() {
return args;
}
toHTML() {
return "";
}
})();
const example = component.getExampleValues();
assert(example.text.length > 0);
assert(example.markdown.length > 0);
});
it("allows for chaining methods when setting example values", () => {
const the_argument = new MarkdownArgument().setExampleValues([
"abc1",
"abc2",
]);
assert((the_argument as any) instanceof ComponentArgument);
});
+ describe("Word counting", () => {
+ it("Image argument", () => {
+ assert.strictEqual(new Image("./image.jpg").countWords(), 0);
+ });
+
+ it("Enum argument", () => {
+ assert.strictEqual(
+ new Enum(<const>["hamster", "dentist"]).countWords(),
+ 0
+ );
+ });
+
+ it("ShortText argument", () => {
+ assert.strictEqual(new ShortText().countWords("Test ShortText"), 2);
+ });
+
+ it("ShortText argument", () => {
+ assert.strictEqual(new ShortText().countWords("Test ShortText"), 2);
+ });
+
+ it("MarkdownArgument argument", () => {
+ assert.strictEqual(
+ new MarkdownArgument().countWords(
+ "*Lorem ipsum* dolor sit amet, **consectetur adipiscing elit**."
+ ),
+ 8
+ );
+ });
+
+ it("List argument", () => {
+ assert.strictEqual(
+ new List(new ShortText()).countWords([
+ "Test ShortText 1",
+ "Test ShortText 2",
+ ]),
+ 6
+ );
+ });
+
+ it("Structured argument", () => {
+ assert.strictEqual(
+ new Structured({
+ fullname: new ShortText(),
+ age: new ShortText(),
+ }).countWords({ fullname: "Joe Done", age: "34" }),
+ 3
+ );
+ });
+ });
+
describe("List argument", () => {
it("Generates example values from provided examples, if they are provided", () => {
const list = new List(new ShortText()).setExampleValues([
["a", "b", "c"],
]);
assert.deepStrictEqual(list.getExampleValue(), ["a", "b", "c"]);
});
});
});
diff --git a/src/component-arguments.ts b/src/component-arguments.ts
index 474bc95..c990ca5 100644
--- a/src/component-arguments.ts
+++ b/src/component-arguments.ts
@@ -1,178 +1,216 @@
export type ExtractComponentArgumentValue<C> = C extends ComponentArgument<
infer T
>
? T
: never;
export type ExtractStructuredComponentArgumentsValues<C> = {
[property in keyof C]: ExtractComponentArgumentValue<C[property]>;
};
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type T = ExtractComponentArgumentValue<Structured<any>>;
-export abstract class ComponentArgument<ARG extends any> {
+export abstract class ComponentArgument<ARG> {
public example_values: ARG[] = [];
abstract getTypeName(): string;
abstract getEmptyValue(): ARG;
+ abstract countWords(value: ARG): number;
+
getExampleValue() {
return this.example_values[
Math.floor(this.example_values.length * Math.random())
];
}
setExampleValues(values: ARG[]): this {
this.example_values = values;
return this;
}
}
export class ShortText extends ComponentArgument<string> {
example_values = [
"Lorem ipsum set doloris",
"Main hippopotomonstrosesquip delos muertos",
"Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore",
"Ipsum",
];
getTypeName() {
return "short-text";
}
getEmptyValue() {
return "";
}
+
+ countWords(value: string): number {
+ return value.toString().split(" ").length;
+ }
}
export class MarkdownArgument extends ComponentArgument<string> {
getTypeName() {
return "markdown";
}
getEmptyValue() {
return "";
}
+ countWords(value: string): number {
+ return value.toString().split(" ").length;
+ }
+
example_values = [
`*Lorem ipsum* dolor sit amet, **consectetur adipiscing elit**, sed [do eiusmod](#) tempor incididunt ut labore et dolore magna aliqua. Posuere lorem ipsum dolor sit amet consectetur adipiscing elit. Porttitor massa id neque aliquam vestibulum. Turpis egestas pretium aenean pharetra.
Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue. Tellus cras adipiscing enim eu turpis egestas. Sagittis id consectetur purus ut faucibus pulvinar elementum. Pulvinar etiam non quam lacus suspendisse. Viverra adipiscing at in tellus integer feugiat scelerisque. Ultricies leo integer malesuada nunc vel risus commodo. Morbi leo urna molestie at elementum. Justo laoreet sit amet cursus sit amet. `,
`**Duis ut diam quam nulla**.
Lectus mauris *ultrices* eros [in cursus turpis massa](#).
Pulvinar neque laoreet suspendisse interdum consectetur. Orci phasellus egestas tellus rutrum tellus.`,
];
}
export class List<
T extends ComponentArgument<unknown>
> extends ComponentArgument<Array<ExtractComponentArgumentValue<T>>> {
constructor(public item_type: T) {
super();
}
getTypeName() {
return "list";
}
getEmptyValue() {
return [];
}
getExampleValue() {
if (this.example_values.length) {
return super.getExampleValue();
} else {
const count = Math.floor(Math.random() * 5);
const result = [] as Array<ExtractComponentArgumentValue<T>>;
for (let i = 0; i < count; i++) {
result.push(
this.item_type.getExampleValue() as ExtractComponentArgumentValue<T>
);
}
return result;
}
}
+
+ countWords(value: ExtractComponentArgumentValue<T>[]): number {
+ return value.reduce(
+ (acc, item) => acc + this.item_type.countWords(item),
+ 0
+ );
+ }
}
export class Structured<
T extends Record<string, ComponentArgument<unknown>>
> extends ComponentArgument<{
[property in keyof T]: ExtractComponentArgumentValue<T[property]>;
}> {
constructor(public structure: T) {
super();
}
getTypeName() {
return "structured";
}
+ countWords(value: {
+ [property in keyof T]: ExtractComponentArgumentValue<T[property]>;
+ }): number {
+ return Object.entries(value).reduce((acc, [key, val]) => {
+ if (!this.structure[key]) {
+ console.warn(`Key ${key} doesn't exist in structured argument`);
+ return acc + 0;
+ }
+ return acc + this.structure[key].countWords(val);
+ }, 0);
+ }
+
getEmptyValue() {
return Object.fromEntries(
Object.entries(this.structure).map(([name, arg]) => [
name,
arg.getEmptyValue(),
])
) as {
[property in keyof T]: ExtractComponentArgumentValue<T[property]>;
};
}
getExampleValue() {
return Object.fromEntries(
Object.entries(this.structure).map(([name, arg]) => [
name,
arg.getExampleValue(),
])
) as {
[property in keyof T]: ExtractComponentArgumentValue<T[property]>;
};
}
}
export class Enum<T extends string> extends ComponentArgument<T> {
public readonly values: Readonly<T[]>;
constructor(values: Readonly<T[]>) {
super();
this.values = values;
}
getTypeName() {
return "enum";
}
getEmptyValue() {
return this.values[0];
}
getExampleValue() {
return this.values[Math.floor(Math.random() * this.values.length)];
}
+
+ countWords(): number {
+ return 0;
+ }
}
export class Image extends ComponentArgument<string> {
constructor(public path_to_image_on_fs: string) {
super();
}
getTypeName() {
return "image";
}
getEmptyValue() {
return "";
}
getExampleValue() {
return "";
}
+
+ countWords(): number {
+ return 0;
+ }
}
export const ComponentArguments = {
Image,
Structured,
List,
Markdown: MarkdownArgument,
ShortText,
Enum,
};
diff --git a/src/component.ts b/src/component.ts
index a126f38..de06f45 100644
--- a/src/component.ts
+++ b/src/component.ts
@@ -1,37 +1,50 @@
import { FlatTemplatable } from "tempstream";
import {
ComponentArgument,
ExtractStructuredComponentArgumentsValues,
} from "./component-arguments";
import { JDDContext } from ".";
export interface ComponentConstructor<
A extends Record<string, ComponentArgument<unknown>> = Record<
string,
ComponentArgument<unknown>
>
> {
new (): Component<A>;
}
export abstract class Component<
ArgumentsT extends Record<string, ComponentArgument<unknown>> = Record<
string,
ComponentArgument<unknown>
>
> {
abstract getArguments(): ArgumentsT;
abstract toHTML(
args: ExtractStructuredComponentArgumentsValues<ArgumentsT>,
context: JDDContext
): FlatTemplatable;
+ countWords(args: Record<string, unknown>): number {
+ return Object.entries(args).reduce((acc, [arg_name, value]) => {
+ const arg = this.getArguments()[arg_name];
+ if (!arg) {
+ console.warn(
+ `Arguemnt ${arg_name} was not found in the component`
+ );
+ return acc + 0;
+ }
+ return acc + arg.countWords(value);
+ }, 0);
+ }
+
getExampleValues(): ExtractStructuredComponentArgumentsValues<ArgumentsT> {
return Object.fromEntries(
Object.entries(this.getArguments()).map(([key, value]) => [
key,
value.getExampleValue(),
])
) as ExtractStructuredComponentArgumentsValues<ArgumentsT>;
}
}
diff --git a/src/index.ts b/src/index.ts
index ca0fbdf..755268d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,48 +1,62 @@
import { FlatTemplatable, tempstream } from "tempstream";
import { Registry } from "./registry";
import { marked } from "marked";
import { insert_nbsp } from "./utils/insert_nbsp";
export * from "./component-arguments";
export * from "./component";
export * from "./registry";
export { insert_nbsp } from "./utils/insert_nbsp";
export type JDDocument = Array<{
component_name: string;
args: Record<string, unknown>;
}>;
export interface JDDContext {
render_image: (path_to_image: string) => FlatTemplatable;
render_markdown: (markdown: string) => FlatTemplatable;
}
export const simpleJDDContext: JDDContext = {
render_image: () => /* HTML */ `<img src="file://path" />`,
render_markdown: (string) =>
string ? marked.parse(insert_nbsp(string)) : "",
};
+export function countWords(registry: Registry, document: JDDocument): number {
+ return document.reduce((acc, { component_name, args }) => {
+ const component = registry.get(component_name);
+ if (!component) {
+ console.warn(
+ "Component not found in the registry: " + component_name
+ );
+ return acc + 0;
+ }
+
+ return acc + component.countWords(args);
+ }, 0);
+}
+
export function render(
registry: Registry,
document: JDDocument,
context: JDDContext
) {
return tempstream`${document.map(({ component_name, args }) => {
const component = registry.get(component_name);
if (!component) {
console.warn(
"Component not found in the registry: " + component_name
);
return "";
}
for (const arg_name in component?.getArguments()) {
if (!Object.prototype.hasOwnProperty.call(args, arg_name)) {
args[arg_name] = component
?.getArguments()
[arg_name]?.getEmptyValue();
}
}
return component.toHTML(args, context);
})}`;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 24, 06:55 (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
557032
Default Alt Text
(11 KB)

Event Timeline