Skip to content

Commit

Permalink
+++
Browse files Browse the repository at this point in the history
  • Loading branch information
Offirmo committed Nov 11, 2024
1 parent 4f6c3ab commit 83c43c4
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { LIB, SCHEMA_VERSION } from '../consts.js'

import {
NodeType,
type BaseHints,
type Hints,
type CheckedNode,
type Node,
type Document,
Expand All @@ -16,39 +16,39 @@ interface CommonOptions {
classes?: string[]
}

interface Builder<Hints = BaseHints> {
addClass(...classes: string[]): Builder<Hints>
addHints(hints: Partial<Hints>): Builder<Hints>
interface Builder {
addClass(...classes: string[]): Builder
addHints(hints: Partial<Hints>): Builder

pushText(str: string): Builder<Hints>
pushText(str: string): Builder

// nothing is added in content
// useful for
// 1. lists
// 2. manual stuff
pushRawNode(node: Node<Hints>, options?: CommonOptions): Builder<Hints>
pushRawNode(node: Node, options?: CommonOptions): Builder

// node ref is auto added into content
pushNode(node: Node<Hints>, options?: CommonOptions): Builder<Hints>
pushNode(node: Node, options?: CommonOptions): Builder

pushInlineFragment(str: string, options?: CommonOptions): Builder<Hints>
pushBlockFragment(str: string, options?: CommonOptions): Builder<Hints>
pushStrong(str: string, options?: CommonOptions): Builder<Hints>
pushWeak(str: string, options?: CommonOptions): Builder<Hints>
pushHeading(str: string, options?: CommonOptions): Builder<Hints>
pushHorizontalRule(): Builder<Hints>
pushLineBreak(): Builder<Hints>
pushInlineFragment(str: string, options?: CommonOptions): Builder
pushBlockFragment(str: string, options?: CommonOptions): Builder
pushStrong(str: string, options?: CommonOptions): Builder
pushWeak(str: string, options?: CommonOptions): Builder
pushHeading(str: string, options?: CommonOptions): Builder
pushHorizontalRule(): Builder
pushLineBreak(): Builder

pushKeyValue(key: Node<Hints> | string, value: Node<Hints> | string | number, options?: CommonOptions): Builder<Hints>
pushKeyValue(key: Node | string, value: Node | string | number, options?: CommonOptions): Builder

done(): CheckedNode<Hints>
done(): CheckedNode
}

/////////////////////////////////////////////////

function create<Hints>($type: NodeType): Builder<Hints> {
function create($type: NodeType): Builder {

const $node: CheckedNode<Hints> = {
const $node: CheckedNode = {
$v: SCHEMA_VERSION,
$type,
$classes: [],
Expand All @@ -57,7 +57,7 @@ function create<Hints>($type: NodeType): Builder<Hints> {
$hints: {} as any,
}

const builder: Builder<Hints> = {
const builder: Builder = {
addClass,
addHints,

Expand All @@ -80,25 +80,25 @@ function create<Hints>($type: NodeType): Builder<Hints> {

let sub_id = 0

function addClass(...classes: string[]): Builder<Hints> {
function addClass(...classes: string[]): Builder {
$node.$classes.push(...classes)
return builder
}

function addHints(hints: { [k: string]: any }): Builder<Hints> {
function addHints(hints: { [k: string]: any }): Builder {
$node.$hints = {
...$node.$hints,
...hints,
}
return builder
}

function pushText(str: string): Builder<Hints> {
function pushText(str: string): Builder {
$node.$content += str
return builder
}

function _buildAndPush(builder: Builder<Hints>, str: string, options: CommonOptions = {}) {
function _buildAndPush(builder: Builder, str: string, options: CommonOptions = {}) {
options = {
classes: [],
...options,
Expand All @@ -113,59 +113,59 @@ function create<Hints>($type: NodeType): Builder<Hints> {
}


function pushRawNode(node: Node<Hints>, options: CommonOptions = {}): Builder<Hints> {
function pushRawNode(node: Node, options: CommonOptions = {}): Builder {
const id = options.id || ('000' + ++sub_id).slice(-4)
$node.$sub[id] = node
if (options.classes)
$node.$classes.push(...options.classes)
return builder
}

function pushNode(node: Node<Hints>, options: CommonOptions = {}): Builder<Hints> {
function pushNode(node: Node, options: CommonOptions = {}): Builder {
const id = options.id || ('000' + ++sub_id).slice(-4)
$node.$content += `⎨⎨${id}⎬⎬`
return pushRawNode(node, { ...options, id })
}

function pushInlineFragment(str: string, options?: CommonOptions): Builder<Hints> {
function pushInlineFragment(str: string, options?: CommonOptions): Builder {
return _buildAndPush(fragmentⵧinline(), str, options)
}

function pushBlockFragment(str: string, options?: CommonOptions): Builder<Hints> {
function pushBlockFragment(str: string, options?: CommonOptions): Builder {
return _buildAndPush(fragmentⵧblock(), str, options)
}

function pushStrong(str: string, options?: CommonOptions): Builder<Hints> {
function pushStrong(str: string, options?: CommonOptions): Builder {
return _buildAndPush(strong(), str, options)
}

function pushWeak(str: string, options?: CommonOptions): Builder<Hints> {
function pushWeak(str: string, options?: CommonOptions): Builder {
return _buildAndPush(weak(), str, options)
}

function pushHeading(str: string, options?: CommonOptions): Builder<Hints> {
function pushHeading(str: string, options?: CommonOptions): Builder {
return _buildAndPush(heading(), str, options)
}

function pushHorizontalRule(): Builder<Hints> {
function pushHorizontalRule(): Builder {
$node.$content += '⎨⎨hr⎬⎬'
return builder
}

function pushLineBreak(): Builder<Hints> {
function pushLineBreak(): Builder {
$node.$content += '⎨⎨br⎬⎬'
return builder
}

function pushKeyValue(key: Node<Hints> | string, value: Node<Hints> | string | number, options: CommonOptions = {}): Builder<Hints> {
function pushKeyValue(key: Node | string, value: Node | string | number, options: CommonOptions = {}): Builder {
if ($node.$type !== NodeType.ol && $node.$type !== NodeType.ul)
throw new Error(`${LIB}: Key/value is intended to be used in a ol/ul only!`)

options = {
classes: [],
...options,
}
const kv_node: Node<Hints> = key_value<Hints>(key, value)
const kv_node: Node = key_value(key, value)
.addClass(...options.classes!)
.done()
delete options.classes // TODO review
Expand All @@ -174,45 +174,45 @@ function create<Hints>($type: NodeType): Builder<Hints> {
}

// TODO rename value() like lodash chain?
function done(): CheckedNode<Hints> {
function done(): CheckedNode {
return $node
}

return builder
}

function fragmentⵧinline<Hints = BaseHints>(): Builder<Hints> {
function fragmentⵧinline(): Builder {
return create(NodeType.fragmentⵧinline)
}
function fragmentⵧblock<Hints = BaseHints>(): Builder<Hints> {
function fragmentⵧblock(): Builder {
return create(NodeType.fragmentⵧblock)
}

function heading<Hints = BaseHints>(): Builder<Hints> {
function heading(): Builder {
return create(NodeType.heading)
}

function strong<Hints = BaseHints>(): Builder<Hints> {
function strong(): Builder {
return create(NodeType.strong)
}

function weak<Hints = BaseHints>(): Builder<Hints> {
function weak(): Builder {
return create(NodeType.weak)
}

function listⵧordered<Hints = BaseHints>(): Builder<Hints> {
function listⵧordered(): Builder {
return create(NodeType.ol)
}
function listⵧunordered<Hints = BaseHints>(): Builder<Hints> {
function listⵧunordered(): Builder {
return create(NodeType.ul)
}

function key_value<Hints = BaseHints>(key: Node<Hints> | string, value: Node<Hints> | string | number): Builder<Hints> {
const key_node: Node<Hints> = promoteꓽto_node<Hints>(key)
function key_value(key: Node | string, value: Node | string | number): Builder {
const key_node: Node = promoteꓽto_node(key)

const value_node: Node<Hints> = promoteꓽto_node<Hints>(value)
const value_node: Node = promoteꓽto_node(value)

return fragmentⵧinline<Hints>()
return fragmentⵧinline()
.pushNode(key_node, { id: 'key' })
.pushText(': ')
.pushNode(value_node, { id: 'value' })
Expand Down
14 changes: 7 additions & 7 deletions stack--current/3-advanced--multi/rich-text-format/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type NodeType = Enum<typeof NodeType> // eslint-disable-line no-redeclare
// hints for progressive enhancement
// - for rendering, hints should be OPTIONAL and any renderer should be able to render decently without them
// - for non-rendering (ex. hypermedia features) hints can be made mandatory
interface BaseHints {
interface Hints {
[k: string]: any

bullets_style?: 'none' // to remove bullets from lists
Expand All @@ -42,35 +42,35 @@ interface BaseHints {

// using type instead of interface to prevent extra properties
// (not supposed to extend this)
type CheckedNode<Hints = BaseHints> = {
type CheckedNode = {
$v: number // schema version
$type: NodeType
$classes: string[]
$content: string
// sub-nodes referenced in she content
$sub: {
[id: string]: Partial<CheckedNode<Hints>>
[id: string]: Partial<CheckedNode>
}
// hints for renderers. May or may not be used.
$hints: Hints
}

type Node<Hints = BaseHints> = Partial<CheckedNode<Hints>>
type Node = Partial<CheckedNode>

// Node + stuff trivial to promote to a Node
type NodeLike<Hints = BaseHints> = Node<Hints> | string | number
type NodeLike = Node | string | number

///////

// aliases
type Document<Hints = {[k: string]: any}> = Node<Hints>
type Document<Hints = {[k: string]: any}> = Node

/////////////////////////////////////////////////

export {
NodeType,

type BaseHints,
type Hints,

type CheckedNode,
type Node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { LIB, SCHEMA_VERSION } from '../consts.js'

import {
NodeType,
type Hints,
type CheckedNode,
type Node,
} from '../types.js'

/////////////////////////////////////////////////

function normalizeꓽnode<Hints>($raw_node: Readonly<Node<Hints>>, default_hints: Hints = {} as any): CheckedNode<Hints> {
function normalizeꓽnode($raw_node: Readonly<Node>, default_hints: Hints = {} as any): CheckedNode {
assert(!!$raw_node, `normalize_node(): undefined or null!`)

const {
Expand All @@ -30,7 +31,7 @@ function normalizeꓽnode<Hints>($raw_node: Readonly<Node<Hints>>, default_hints

// TODO validation

const $node: CheckedNode<Hints> = {
const $node: CheckedNode = {
$v,
$type,
$classes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { assertꓽisꓽNode } from '../type-guards.js'

/////////////////////////////////////////////////

function promoteꓽto_node<Hints>($raw: NodeLike<Hints>): Node<Hints> {
function promoteꓽto_node($raw: NodeLike): Node {
if (typeof $raw === 'number')
$raw = String($raw)

Expand All @@ -24,9 +24,9 @@ function promoteꓽto_node<Hints>($raw: NodeLike<Hints>): Node<Hints> {
return $raw
}

function promoteꓽto_nodeⵧimmutable<Hints>(
$raw: Immutable<NodeLike<Hints>>
): Immutable<Node<Hints>> {
function promoteꓽto_nodeⵧimmutable(
$raw: Immutable<NodeLike>
): Immutable<Node> {
return promoteꓽto_node($raw as any)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"dev": "run-s clean _build:dev:watch",

"demo": "node ./dist/src.es2023.esm/demo/index.js",
"demoh": "node ./dist/src.es2023.esm/hateoas/index.js",
"demoht": "node ./dist/src.es2023.esm/hateoas/terminal/index.js",

"start:parcel": "parcel serve src/hateoas/web/index.html --port 8080 --lazy --no-autoinstall",
"demow": "npm-run-all clean --parallel start:parcel",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
normalizeꓽuri‿SSP,
normalizeꓽuri‿str,
} from './to-migrate.js'
import { resolveꓽrich_text_pending_engagement } from '../to-export-to-own-package/hateoas/utils'
import { resolveꓽrich_text_pending_engagement } from '../to-export-to-own-package/hateoas/utils.js'

/////////////////////////////////////////////////

Expand Down Expand Up @@ -236,7 +236,7 @@ class AppHateoasServer implements HATEOASServer<HypermediaContentType, Action> {
return pending
}

get_pending_engagements(url: Immutable<Hyperlink['href']> = DEFAULT_ROOT_URI): Immutable<Array<HATEOASPendingEngagement<HypermediaContentType>>> {
get_pending_engagements(url: Immutable<Hyperlink['href']> = DEFAULT_ROOT_URI): Immutable<Array<HATEOASPendingEngagement<HypermediaContentType, Action>>> {
if (url === DEFAULT_ROOT_URI || url === '/session') {
// not yet!
return []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class HypermediaBrowserWithChatInterface<ActionType> implements StepIterator<Con

switch(this.status) {
case 'starting': {
// skip the PEF & PENF messages
// skip the engagement messages
// to give a chance for some content
// (hopefully introducing the app)
// to be displayed first
Expand All @@ -120,17 +120,17 @@ class HypermediaBrowserWithChatInterface<ActionType> implements StepIterator<Con
case 'nominal': {
const pes = this.server.get_pending_engagements(this.current_route)
this.pending_steps.unshift(...pes.map(pe => {
const { $doc, ack_action: actionⵧack } = pe
const { content: $doc, ack_action: actionⵧack } = pe
// TODO improve depending on the format!
const step: Step<ContentType> = {
type: StepType.simple_message,
msg: $doc,
callback: () => dispatch(actionⵧack),
msg: $doc as any, // cast away the immutability. TODO one day improve
callback: () => actionⵧack && dispatch(actionⵧack),
}
//console.log(`[gen_next_step()] ...yielding from PEF`)
return step
}))
if (this.pending_steps.length) {
//console.log(`[gen_next_step()] ...yielding from enqueued post-PE`)
return this.pending_steps.pop()!
}
break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ interface HATEOASServer<
// ex. crash or lost connexion and the player lose a very important story development.
// thus we'd rather use "engagement", see next method.
// TODO REVIEW we may want to return trivial, "can-be-lost" feedback, for ex. "ticket created" or "action acknowledged"
dispatch(action: Action, url?: Hyperlink['href']): Promise<void>
dispatch(action: Immutable<Action>, url?: Hyperlink['href']): Promise<void>

// important to separate resource representation from actions feedback
// sync bc we assume the browser awaits dispatches
Expand Down
Loading

0 comments on commit 83c43c4

Please sign in to comment.