diff options
77 files changed, 2821 insertions, 2689 deletions
diff --git a/src/bindings/constcharp.nim b/src/bindings/constcharp.nim index 057b8acb..f1753147 100644 --- a/src/bindings/constcharp.nim +++ b/src/bindings/constcharp.nim @@ -2,5 +2,5 @@ type cstringConstImpl {.importc: "const char*".} = cstring cstringConst* = distinct cstringConstImpl -proc `[]`*(s: cstringConst, i: int): char = cstring(s)[i] +proc `[]`*(s: cstringConst; i: int): char = cstring(s)[i] proc `$`*(s: cstringConst): string {.borrow.} diff --git a/src/bindings/libregexp.nim b/src/bindings/libregexp.nim index 7f7b37cf..fe603908 100644 --- a/src/bindings/libregexp.nim +++ b/src/bindings/libregexp.nim @@ -18,11 +18,11 @@ func toLREFlags*(flags: cint): LREFlags = {.passc: "-Ilib/".} {.push header: "quickjs/libregexp.h", importc.} -proc lre_compile*(plen: ptr cint, error_msg: cstring, error_msg_size: cint, - buf: cstring, buf_len: csize_t, re_flags: cint, opaque: pointer): ptr uint8 +proc lre_compile*(plen: ptr cint; error_msg: cstring; error_msg_size: cint; + buf: cstring; buf_len: csize_t; re_flags: cint; opaque: pointer): ptr uint8 -proc lre_exec*(capture: ptr ptr uint8, bc_buf: ptr uint8, cbuf: ptr uint8, - cindex: cint, clen: cint, cbuf_type: cint, opaque: pointer): cint +proc lre_exec*(capture: ptr ptr uint8; bc_buf, cbuf: ptr uint8; + cindex, clen, cbuf_type: cint; opaque: pointer): cint proc lre_get_capture_count*(bc_buf: ptr uint8): cint diff --git a/src/bindings/libunicode.nim b/src/bindings/libunicode.nim index cb041e50..f501ae3f 100644 --- a/src/bindings/libunicode.nim +++ b/src/bindings/libunicode.nim @@ -1,5 +1,5 @@ type - DynBufReallocFunc = proc(opaque: pointer, p: pointer, size: csize_t): pointer {.cdecl.} + DynBufReallocFunc = proc(opaque, p: pointer; size: csize_t): pointer {.cdecl.} CharRange* = object len*: cint # in points, always even @@ -15,14 +15,15 @@ type {.push header: "quickjs/libunicode.h", importc.} -proc cr_init*(cr: ptr CharRange, mem_opaque: pointer, - realloc_func: DynBufReallocFunc) {.importc.} +proc cr_init*(cr: ptr CharRange; mem_opaque: pointer; + realloc_func: DynBufReallocFunc) {.importc.} proc cr_free*(cr: ptr CharRange) {.importc.} -proc unicode_normalize*(pdst: ptr ptr uint32, src: ptr uint32, src_len: cint, - n_type: UnicodeNormalizationEnum, opaque: pointer, - realloc_func: DynBufReallocFunc): cint {.importc.} +proc unicode_normalize*(pdst: ptr ptr uint32; src: ptr uint32; src_len: cint; + n_type: UnicodeNormalizationEnum; opaque: pointer; + realloc_func: DynBufReallocFunc): cint {.importc.} -proc unicode_general_category*(cr: ptr CharRange, gc_name: cstring): cint {.importc.} +proc unicode_general_category*(cr: ptr CharRange; gc_name: cstring): cint + {.importc.} {.pop.} diff --git a/src/bindings/quickjs.nim b/src/bindings/quickjs.nim index df4a6868..622cc253 100644 --- a/src/bindings/quickjs.nim +++ b/src/bindings/quickjs.nim @@ -77,25 +77,31 @@ type JSRuntime* = ptr JSRuntimeT JSContext* = ptr JSContextT JSModuleDef* = ptr JSModuleDefT - JSCFunction* = proc(ctx: JSContext, this_val: JSValue, argc: cint, + JSCFunction* = proc(ctx: JSContext; this_val: JSValue; argc: cint; argv: ptr UncheckedArray[JSValue]): JSValue {.cdecl.} - JSCFunctionData* = proc(ctx: JSContext, this_val: JSValue, argc: cint, argv: ptr JSValue, magic: cint, func_data: ptr JSValue): JSValue {.cdecl.} - JSGetterFunction* = proc(ctx: JSContext, this_val: JSValue): JSValue {.cdecl.} - JSSetterFunction* = proc(ctx: JSContext, this_val: JSValue, val: JSValue): JSValue {.cdecl.} - JSGetterMagicFunction* = proc(ctx: JSContext, this_val: JSValue, magic: cint): JSValue {.cdecl.} - JSSetterMagicFunction* = proc(ctx: JSContext, this_val: JSValue, val: JSValue, magic: cint): JSValue {.cdecl.} - JSInterruptHandler* = proc(rt: JSRuntime, opaque: pointer): cint {.cdecl.} + JSCFunctionData* = proc(ctx: JSContext; this_val: JSValue; argc: cint; + argv: ptr JSValue; magic: cint; func_data: ptr JSValue): JSValue {.cdecl.} + JSGetterFunction* = proc(ctx: JSContext; this_val: JSValue): JSValue {.cdecl.} + JSSetterFunction* = proc(ctx: JSContext; this_val, val: JSValue): + JSValue {.cdecl.} + JSGetterMagicFunction* = proc(ctx: JSContext; this_val: JSValue; magic: cint): + JSValue {.cdecl.} + JSSetterMagicFunction* = proc(ctx: JSContext; this_val, val: JSValue; + magic: cint): JSValue {.cdecl.} + JSInterruptHandler* = proc(rt: JSRuntime; opaque: pointer): cint {.cdecl.} JSClassID* = uint32 JSAtom* = uint32 - JSClassFinalizer* = proc(rt: JSRuntime, val: JSValue) {.cdecl.} - JSClassCheckDestroy* = proc(rt: JSRuntime, val: JSValue): JS_BOOL {.cdecl.} - JSClassGCMark* = proc(rt: JSRuntime, val: JSValue, mark_func: JS_MarkFunc) {.cdecl.} - JS_MarkFunc* = proc(rt: JSRuntime, gp: ptr JSGCObjectHeader) {.cdecl.} - JSModuleNormalizeFunc* = proc(ctx: JSContext, module_base_name, - module_name: cstringConst, opaque: pointer): cstring {.cdecl.} - JSModuleLoaderFunc* = proc(ctx: JSContext, module_name: cstringConst, + JSClassFinalizer* = proc(rt: JSRuntime; val: JSValue) {.cdecl.} + JSClassCheckDestroy* = proc(rt: JSRuntime; val: JSValue): JS_BOOL {.cdecl.} + JSClassGCMark* = proc(rt: JSRuntime; val: JSValue; mark_func: JS_MarkFunc) + {.cdecl.} + JS_MarkFunc* = proc(rt: JSRuntime; gp: ptr JSGCObjectHeader) {.cdecl.} + JSModuleNormalizeFunc* = proc(ctx: JSContext; module_base_name, + module_name: cstringConst; opaque: pointer): cstring {.cdecl.} + JSModuleLoaderFunc* = proc(ctx: JSContext; module_name: cstringConst, opaque: pointer): JSModuleDef {.cdecl.} - JSJobFunc* = proc(ctx: JSContext, argc: cint, argv: ptr JSValue): JSValue {.cdecl.} + JSJobFunc* = proc(ctx: JSContext; argc: cint; argv: ptr JSValue): JSValue + {.cdecl.} JSGCObjectHeader* {.importc, header: qjsheader.} = object JSFreeArrayBufferDataFunc* = proc(rt: JSRuntime, opaque, p: pointer) {.cdecl.} @@ -107,22 +113,24 @@ type setter*: JSValue JSClassExoticMethods* {.importc, header: qjsheader.} = object - get_own_property*: proc(ctx: JSContext, desc: ptr JSPropertyDescriptor, - obj: JSValue, prop: JSAtom): cint {.cdecl.} - get_own_property_names*: proc(ctx: JSContext, - ptab: ptr ptr UncheckedArray[JSPropertyEnum], - plen: ptr uint32, obj: JSValue): cint {.cdecl.} - delete_property*: proc(ctx: JSContext, obj: JSValue, prop: JSAtom): cint {.cdecl.} - define_own_property*: proc(ctx: JSContext, this_obj: JSValue, - prop: JSAtom, val, getter, setter: JSValue, - flags: cint): cint {.cdecl.} - has_property*: proc(ctx: JSContext, obj: JSValue, atom: JSAtom): cint {.cdecl.} - get_property*: proc(ctx: JSContext, obj: JSValue, atom: JSAtom, - receiver: JSValue, flags: cint): JSValue {.cdecl.} - set_property*: proc(ctx: JSContext, obj: JSValue, atom: JSAtom, - value, receiver: JSValue, flags: cint): cint {.cdecl.} - - JSClassExoticMethodsConst* {.importc: "const JSClassExoticMethods *", header: qjsheader.} = ptr JSClassExoticMethods + get_own_property*: proc(ctx: JSContext; desc: ptr JSPropertyDescriptor; + obj: JSValue; prop: JSAtom): cint {.cdecl.} + get_own_property_names*: proc(ctx: JSContext; + ptab: ptr ptr UncheckedArray[JSPropertyEnum]; plen: ptr uint32; + obj: JSValue): cint {.cdecl.} + delete_property*: proc(ctx: JSContext; obj: JSValue; prop: JSAtom): cint + {.cdecl.} + define_own_property*: proc(ctx: JSContext; this_obj: JSValue; prop: JSAtom; + val, getter, setter: JSValue; flags: cint): cint {.cdecl.} + has_property*: proc(ctx: JSContext; obj: JSValue; atom: JSAtom): cint + {.cdecl.} + get_property*: proc(ctx: JSContext; obj: JSValue; atom: JSAtom; + receiver: JSValue; flags: cint): JSValue {.cdecl.} + set_property*: proc(ctx: JSContext; obj: JSValue; atom: JSAtom; + value, receiver: JSValue; flags: cint): cint {.cdecl.} + + JSClassExoticMethodsConst* {.importc: "const JSClassExoticMethods *", + header: qjsheader.} = ptr JSClassExoticMethods JSClassDef* {.importc, header: qjsheader.} = object class_name*: cstring @@ -132,7 +140,8 @@ type exotic*: JSClassExoticMethodsConst can_destroy*: JSClassCheckDestroy - JSClassDefConst* {.importc: "const JSClassDef *", header: qjsheader.} = ptr JSClassDef + JSClassDefConst* {.importc: "const JSClassDef *", + header: qjsheader.} = ptr JSClassDef JSMemoryUsage* = object malloc_size*, malloc_limit*, memory_used_size*: int64 @@ -218,9 +227,9 @@ type opaque*: pointer JSMallocFunctions* {.importc.} = object - js_malloc*: proc(s: ptr JSMallocState, size: csize_t): pointer {.cdecl.} - js_free*: proc(s: ptr JSMallocState, p: pointer) {.cdecl.} - js_realloc*: proc(s: ptr JSMallocState, p: pointer, size: csize_t): pointer + js_malloc*: proc(s: ptr JSMallocState; size: csize_t): pointer {.cdecl.} + js_free*: proc(s: ptr JSMallocState; p: pointer) {.cdecl.} + js_realloc*: proc(s: ptr JSMallocState; p: pointer; size: csize_t): pointer {.cdecl.} js_malloc_usable_size*: proc(p: pointer) {.cdecl.} @@ -268,7 +277,8 @@ const JS_PROP_CONFIGURABLE* = (1 shl 0) JS_PROP_WRITABLE* = (1 shl 1) JS_PROP_ENUMERABLE* = (1 shl 2) - JS_PROP_C_W_E* = (JS_PROP_CONFIGURABLE or JS_PROP_WRITABLE or JS_PROP_ENUMERABLE) + JS_PROP_C_W_E* = (JS_PROP_CONFIGURABLE or JS_PROP_WRITABLE or + JS_PROP_ENUMERABLE) JS_PROP_LENGTH* = (1 shl 3) # used internally in Arrays JS_PROP_TMASK* = (3 shl 4) # mask for NORMAL, GETSET, VARREF, AUTOINIT JS_PROP_NORMAL* = (0 shl 4) @@ -287,7 +297,7 @@ const const JS_PARSE_JSON_EXT* = (1 shl 0) -template JS_CFUNC_DEF*(n: string, len: uint8, func1: JSCFunction): +template JS_CFUNC_DEF*(n: string; len: uint8; func1: JSCFunction): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_WRITABLE or JS_PROP_CONFIGURABLE, @@ -298,7 +308,7 @@ template JS_CFUNC_DEF*(n: string, len: uint8, func1: JSCFunction): cproto: JS_CFUNC_generic, cfunc: JSCFunctionType(generic: func1)))) -template JS_CFUNC_DEF_NOCONF*(n: string, len: uint8, func1: JSCFunction): +template JS_CFUNC_DEF_NOCONF*(n: string; len: uint8; func1: JSCFunction): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_ENUMERABLE, @@ -309,7 +319,7 @@ template JS_CFUNC_DEF_NOCONF*(n: string, len: uint8, func1: JSCFunction): cproto: JS_CFUNC_generic, cfunc: JSCFunctionType(generic: func1)))) -template JS_CGETSET_DEF*(n: string, fgetter: JSGetterFunction, +template JS_CGETSET_DEF*(n: string; fgetter: JSGetterFunction; fsetter: JSSetterFunction): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_CONFIGURABLE, @@ -319,7 +329,7 @@ template JS_CGETSET_DEF*(n: string, fgetter: JSGetterFunction, get: JSCFunctionType(getter: fgetter), set: JSCFunctionType(setter: fsetter)))) -template JS_CGETSET_DEF_NOCONF*(n: string, fgetter: JSGetterFunction, +template JS_CGETSET_DEF_NOCONF*(n: string; fgetter: JSGetterFunction; fsetter: JSSetterFunction): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_ENUMERABLE, @@ -329,7 +339,7 @@ template JS_CGETSET_DEF_NOCONF*(n: string, fgetter: JSGetterFunction, get: JSCFunctionType(getter: fgetter), set: JSCFunctionType(setter: fsetter)))) -template JS_CGETSET_MAGIC_DEF*(n: string, fgetter, fsetter: typed, +template JS_CGETSET_MAGIC_DEF*(n: string; fgetter, fsetter: typed; m: int16): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_CONFIGURABLE, @@ -340,15 +350,14 @@ template JS_CGETSET_MAGIC_DEF*(n: string, fgetter, fsetter: typed, get: JSCFunctionType(getter_magic: fgetter), set: JSCFunctionType(setter_magic: fsetter)))) - {.push header: qjsheader, importc, cdecl.} proc JS_NewRuntime*(): JSRuntime -proc JS_NewRuntime2*(mf: ptr JSMallocFunctions, opaque: pointer): JSRuntime +proc JS_NewRuntime2*(mf: ptr JSMallocFunctions; opaque: pointer): JSRuntime proc JS_FreeRuntime*(rt: JSRuntime) proc JS_GetRuntime*(ctx: JSContext): JSRuntime -proc JS_ComputeMemoryUsage*(rt: JSRuntime, s: ptr JSMemoryUsage) +proc JS_ComputeMemoryUsage*(rt: JSRuntime; s: ptr JSMemoryUsage) proc JS_RunGC*(rt: JSRuntime) proc JS_NewContext*(rt: JSRuntime): JSContext @@ -356,125 +365,147 @@ proc JS_NewContextRaw*(rt: JSRuntime): JSContext proc JS_FreeContext*(ctx: JSContext) proc JS_GetGlobalObject*(ctx: JSContext): JSValue -proc JS_IsInstanceOf*(ctx: JSContext, val: JSValue, obj: JSValue): cint +proc JS_IsInstanceOf*(ctx: JSContext; val: JSValue; obj: JSValue): cint proc JS_NewArray*(ctx: JSContext): JSValue proc JS_NewObject*(ctx: JSContext): JSValue -proc JS_NewObjectClass*(ctx: JSContext, class_id: JSClassID): JSValue -proc JS_NewObjectProto*(ctx: JSContext, proto: JSValue): JSValue -proc JS_NewObjectProtoClass*(ctx: JSContext, proto: JSValue, class_id: JSClassID): JSValue -proc JS_NewPromiseCapability*(ctx: JSContext, resolving_funcs: ptr JSValue): JSValue -proc JS_SetOpaque*(obj: JSValue, opaque: pointer) -proc JS_GetOpaque*(obj: JSValue, class_id: JSClassID): pointer -proc JS_GetOpaque2*(ctx: JSContext, obj: JSValue, class_id: JSClassID): pointer +proc JS_NewObjectClass*(ctx: JSContext; class_id: JSClassID): JSValue +proc JS_NewObjectProto*(ctx: JSContext; proto: JSValue): JSValue +proc JS_NewObjectProtoClass*(ctx: JSContext; proto: JSValue; + class_id: JSClassID): JSValue +proc JS_NewPromiseCapability*(ctx: JSContext; resolving_funcs: ptr JSValue): + JSValue +proc JS_SetOpaque*(obj: JSValue; opaque: pointer) +proc JS_GetOpaque*(obj: JSValue; class_id: JSClassID): pointer +proc JS_GetOpaque2*(ctx: JSContext; obj: JSValue; class_id: JSClassID): pointer proc JS_GetClassID*(obj: JSValue): JSClassID -proc JS_ParseJSON*(ctx: JSContext, buf: cstring, buf_len: csize_t, filename: cstring): JSValue -proc JS_ParseJSON2*(ctx: JSContext, buf: cstring, buf_len: csize_t, - filename: cstring, flags: cint): JSValue +proc JS_ParseJSON*(ctx: JSContext; buf: cstring; buf_len: csize_t; + filename: cstring): JSValue +proc JS_ParseJSON2*(ctx: JSContext; buf: cstring; buf_len: csize_t; + filename: cstring; flags: cint): JSValue -proc JS_NewArrayBuffer*(ctx: JSContext, buf: ptr UncheckedArray[uint8], - len: csize_t, free_func: JSFreeArrayBufferDataFunc, opaque: pointer, +proc JS_NewArrayBuffer*(ctx: JSContext; buf: ptr UncheckedArray[uint8]; + len: csize_t; free_func: JSFreeArrayBufferDataFunc; opaque: pointer; is_shared: JS_BOOL): JSValue -proc JS_GetArrayBuffer*(ctx: JSContext, psize: ptr csize_t, obj: JSValue): ptr uint8 -proc JS_GetTypedArrayBuffer*(ctx: JSContext, obj: JSValue, pbyte_offset, - pbyte_length, pbytes_per_element: ptr csize_t): JSValue +proc JS_GetArrayBuffer*(ctx: JSContext; psize: ptr csize_t; obj: JSValue): + ptr uint8 +proc JS_GetTypedArrayBuffer*(ctx: JSContext; obj: JSValue; + pbyte_offset, pbyte_length, pbytes_per_element: ptr csize_t): JSValue proc JS_NewClassID*(pclass_id: ptr JSClassID): JSClassID -proc JS_NewClass*(rt: JSRuntime, class_id: JSClassID, class_def: ptr JSClassDef): cint -proc JS_IsRegisteredClass*(rt: JSRuntime, class_id: JSClassID): cint -proc JS_SetClassProto*(ctx: JSContext, class_id: JSClassID, obj: JSValue) -proc JS_GetClassProto*(ctx: JSContext, class_id: JSClassID): JSValue -proc JS_SetConstructor*(ctx: JSContext, func_obj: JSValue, proto: JSValue) -proc JS_SetPrototype*(ctx: JSContext, obj: JSValue, proto_val: JSValue): cint -proc JS_GetPrototype*(ctx: JSContext, val: JSValue): JSValue - -proc JS_NewBool*(ctx: JSContext, val: JS_BOOL): JSValue -proc JS_NewInt32*(ctx: JSContext, val: int32): JSValue -proc JS_NewCatchOffset*(ctx: JSContext, val: int32): JSValue -proc JS_NewInt64*(ctx: JSContext, val: int64): JSValue -proc JS_NewUint32*(ctx: JSContext, val: uint32): JSValue -proc JS_NewBigInt64*(ctx: JSContext, val: int64): JSValue -proc JS_NewBigUInt64*(ctx: JSContext, val: uint64): JSValue -proc JS_NewFloat64*(ctx: JSContext, val: cdouble): JSValue - -proc JS_NewAtomLen*(ctx: JSContext, str: cstring, len: csize_t): JSAtom -proc JS_NewAtomUInt32*(ctx: JSContext, u: uint32): JSAtom -proc JS_ValueToAtom*(ctx: JSContext, val: JSValue): JSAtom -proc JS_AtomToValue*(ctx: JSContext, atom: JSAtom): JSValue -proc JS_AtomToCString*(ctx: JSContext, atom: JSAtom): cstring -proc JS_FreeAtom*(ctx: JSContext, atom: JSAtom) -proc JS_FreeAtomRT*(rt: JSRuntime, atom: JSAtom) - -proc JS_NewCFunction2*(ctx: JSContext, cfunc: JSCFunction, name: cstring, length: cint, proto: JSCFunctionEnum, magic: cint): JSValue -proc JS_NewCFunctionData*(ctx: JSContext, cfunc: JSCFunctionData, length: cint, magic: cint, data_len: cint, data: ptr JSValue): JSValue -proc JS_NewCFunction*(ctx: JSContext, cfunc: JSCFunction, name: cstring, length: cint): JSValue - -proc JS_NewString*(ctx: JSContext, str: cstring): JSValue -proc JS_NewStringLen*(ctx: JSContext, str: cstring, len1: csize_t): JSValue -proc JS_NewAtomString*(ctx: JSContext, str: cstring): JSValue +proc JS_NewClass*(rt: JSRuntime; class_id: JSClassID; + class_def: ptr JSClassDef): cint +proc JS_IsRegisteredClass*(rt: JSRuntime; class_id: JSClassID): cint +proc JS_SetClassProto*(ctx: JSContext; class_id: JSClassID; obj: JSValue) +proc JS_GetClassProto*(ctx: JSContext; class_id: JSClassID): JSValue +proc JS_SetConstructor*(ctx: JSContext; func_obj: JSValue; proto: JSValue) +proc JS_SetPrototype*(ctx: JSContext; obj: JSValue; proto_val: JSValue): cint +proc JS_GetPrototype*(ctx: JSContext; val: JSValue): JSValue + +proc JS_NewBool*(ctx: JSContext; val: JS_BOOL): JSValue +proc JS_NewInt32*(ctx: JSContext; val: int32): JSValue +proc JS_NewCatchOffset*(ctx: JSContext; val: int32): JSValue +proc JS_NewInt64*(ctx: JSContext; val: int64): JSValue +proc JS_NewUint32*(ctx: JSContext; val: uint32): JSValue +proc JS_NewBigInt64*(ctx: JSContext; val: int64): JSValue +proc JS_NewBigUInt64*(ctx: JSContext; val: uint64): JSValue +proc JS_NewFloat64*(ctx: JSContext; val: cdouble): JSValue + +proc JS_NewAtomLen*(ctx: JSContext; str: cstring; len: csize_t): JSAtom +proc JS_NewAtomUInt32*(ctx: JSContext; u: uint32): JSAtom +proc JS_ValueToAtom*(ctx: JSContext; val: JSValue): JSAtom +proc JS_AtomToValue*(ctx: JSContext; atom: JSAtom): JSValue +proc JS_AtomToCString*(ctx: JSContext; atom: JSAtom): cstring +proc JS_FreeAtom*(ctx: JSContext; atom: JSAtom) +proc JS_FreeAtomRT*(rt: JSRuntime; atom: JSAtom) + +proc JS_NewCFunction2*(ctx: JSContext; cfunc: JSCFunction; name: cstring; + length: cint; proto: JSCFunctionEnum; magic: cint): JSValue +proc JS_NewCFunctionData*(ctx: JSContext; cfunc: JSCFunctionData; + length, magic, data_len: cint; data: ptr JSValue): JSValue +proc JS_NewCFunction*(ctx: JSContext; cfunc: JSCFunction; name: cstring; + length: cint): JSValue + +proc JS_NewString*(ctx: JSContext; str: cstring): JSValue +proc JS_NewStringLen*(ctx: JSContext; str: cstring; len1: csize_t): JSValue +proc JS_NewAtomString*(ctx: JSContext; str: cstring): JSValue proc JS_ToString*(ctx: JSContext; val: JSValue): JSValue -proc JS_SetProperty*(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue): cint -proc JS_SetPropertyUint32*(ctx: JSContext, this_obj: JSValue, idx: uint32, val: JSValue): cint -proc JS_SetPropertyInt64*(ctx: JSContext, this_obj: JSValue, idx: int64, val: JSValue): cint -proc JS_SetPropertyStr*(ctx: JSContext, this_obj: JSValue, prop: cstring, val: JSValue): cint -proc JS_SetPropertyFunctionList*(ctx: JSContext, obj: JSValue, tab: ptr JSCFunctionListEntry, len: cint) -proc JS_GetProperty*(ctx: JSContext, this_obj: JSValue, prop: JSAtom): JSValue -proc JS_GetPropertyStr*(ctx: JSContext, this_obj: JSValue, prop: cstring): JSValue -proc JS_GetPropertyUint32*(ctx: JSContext, this_obj: JSValue, idx: uint32): JSValue -proc JS_GetOwnPropertyNames*(ctx: JSContext, - ptab: ptr ptr UncheckedArray[JSPropertyEnum], plen: ptr uint32, - obj: JSValue, flags: cint): cint - -proc JS_GetOwnProperty*(ctx: JSContext, desc: ptr JSPropertyDescriptor, - obj: JSValue, prop: JSAtom): cint -proc JS_Call*(ctx: JSContext, func_obj, this_obj: JSValue, argc: cint, +proc JS_SetProperty*(ctx: JSContext; this_obj: JSValue; prop: JSAtom; + val: JSValue): cint +proc JS_SetPropertyUint32*(ctx: JSContext; this_obj: JSValue; idx: uint32; + val: JSValue): cint +proc JS_SetPropertyInt64*(ctx: JSContext; this_obj: JSValue; idx: int64; + val: JSValue): cint +proc JS_SetPropertyStr*(ctx: JSContext; this_obj: JSValue; prop: cstring; + val: JSValue): cint +proc JS_SetPropertyFunctionList*(ctx: JSContext; obj: JSValue; + tab: ptr JSCFunctionListEntry; len: cint) +proc JS_GetProperty*(ctx: JSContext; this_obj: JSValue; prop: JSAtom): JSValue +proc JS_GetPropertyStr*(ctx: JSContext; this_obj: JSValue; prop: cstring): + JSValue +proc JS_GetPropertyUint32*(ctx: JSContext; this_obj: JSValue; idx: uint32): + JSValue +proc JS_GetOwnPropertyNames*(ctx: JSContext; + ptab: ptr ptr UncheckedArray[JSPropertyEnum]; plen: ptr uint32; + obj: JSValue; flags: cint): cint + +proc JS_GetOwnProperty*(ctx: JSContext; desc: ptr JSPropertyDescriptor; + obj: JSValue; prop: JSAtom): cint +proc JS_Call*(ctx: JSContext; func_obj, this_obj: JSValue; argc: cint; argv: ptr JSValue): JSValue -proc JS_NewObjectFromCtor*(ctx: JSContext, ctor: JSValue, +proc JS_NewObjectFromCtor*(ctx: JSContext; ctor: JSValue; class_id: JSClassID): JSValue -proc JS_Invoke*(ctx: JSContext, this_obj: JSValue, atom: JSAtom, argc: cint, +proc JS_Invoke*(ctx: JSContext; this_obj: JSValue; atom: JSAtom; argc: cint; argv: ptr JSValue): JSValue -proc JS_CallConstructor*(ctx: JSContext, func_obj: JSValue, argc: cint, +proc JS_CallConstructor*(ctx: JSContext; func_obj: JSValue; argc: cint; argv: ptr JSValue): JSValue -proc JS_DefineProperty*(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue, getter: JSValue, setter: JSValue, flags: cint): cint -proc JS_DefinePropertyValue*(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue, flags: cint): cint -proc JS_DefinePropertyValueUint32*(ctx: JSContext, this_obj: JSValue, idx: uint32, val: JSValue, flags: cint): cint -proc JS_DefinePropertyValueInt64*(ctx: JSContext, this_obj: JSValue, idx: int64, val: JSValue, flags: cint): cint -proc JS_DefinePropertyValueStr*(ctx: JSContext, this_obj: JSValue, prop: cstring, val: JSValue, flags: cint): cint -proc JS_DefinePropertyValueGetSet*(ctx: JSContext, this_obj: JSValue, prop: JSAtom, getter: JSValue, setter: JSValue, flags: cint): cint - -proc JS_FreeValue*(ctx: JSContext, v: JSValue) -proc JS_FreeValueRT*(rt: JSRuntime, v: JSValue) -proc JS_DupValue*(ctx: JSContext, v: JSValue): JSValue - -proc JS_ToBool*(ctx: JSContext, val: JSValue): cint # return -1 for JS_EXCEPTION -proc JS_ToInt32*(ctx: JSContext, pres: ptr int32, val: JSValue): cint -proc JS_ToUint32*(ctx: JSContext, pres: ptr uint32, val: JSValue): cint -proc JS_ToInt64*(ctx: JSContext, pres: ptr int64, val: JSValue): cint -proc JS_ToIndex*(ctx: JSContext, plen: ptr uint64, val: JSValue): cint -proc JS_ToFloat64*(ctx: JSContext, pres: ptr float64, val: JSValue): cint +proc JS_DefineProperty*(ctx: JSContext; this_obj: JSValue; prop: JSAtom; + val, getter, setter: JSValue; flags: cint): cint +proc JS_DefinePropertyValue*(ctx: JSContext; this_obj: JSValue; prop: JSAtom; + val: JSValue; flags: cint): cint +proc JS_DefinePropertyValueUint32*(ctx: JSContext; this_obj: JSValue; + idx: uint32; val: JSValue; flags: cint): cint +proc JS_DefinePropertyValueInt64*(ctx: JSContext; this_obj: JSValue; idx: int64; + val: JSValue; flags: cint): cint +proc JS_DefinePropertyValueStr*(ctx: JSContext; this_obj: JSValue; + prop: cstring; val: JSValue; flags: cint): cint +proc JS_DefinePropertyValueGetSet*(ctx: JSContext; this_obj: JSValue; + prop: JSAtom; getter, setter: JSValue; flags: cint): cint + +proc JS_FreeValue*(ctx: JSContext; v: JSValue) +proc JS_FreeValueRT*(rt: JSRuntime; v: JSValue) +proc JS_DupValue*(ctx: JSContext; v: JSValue): JSValue + +proc JS_ToBool*(ctx: JSContext; val: JSValue): cint # return -1 for JS_EXCEPTION +proc JS_ToInt32*(ctx: JSContext; pres: ptr int32; val: JSValue): cint +proc JS_ToUint32*(ctx: JSContext; pres: ptr uint32; val: JSValue): cint +proc JS_ToInt64*(ctx: JSContext; pres: ptr int64; val: JSValue): cint +proc JS_ToIndex*(ctx: JSContext; plen: ptr uint64; val: JSValue): cint +proc JS_ToFloat64*(ctx: JSContext; pres: ptr float64; val: JSValue): cint # return an exception if 'val' is a Number -proc JS_ToBigInt64*(ctx: JSContext, pres: ptr int64, val: JSValue): cint +proc JS_ToBigInt64*(ctx: JSContext; pres: ptr int64; val: JSValue): cint # same as JS_ToInt64 but allow BigInt -proc JS_ToInt64Ext*(ctx: JSContext, pres: ptr int64, val: JSValue): cint +proc JS_ToInt64Ext*(ctx: JSContext; pres: ptr int64; val: JSValue): cint -proc JS_ToCStringLen*(ctx: JSContext, plen: ptr csize_t, val1: JSValue): cstring -proc JS_ToCString*(ctx: JSContext, val1: JSValue): cstring +proc JS_ToCStringLen*(ctx: JSContext; plen: ptr csize_t; val1: JSValue): cstring +proc JS_ToCString*(ctx: JSContext; val1: JSValue): cstring proc JS_FreeCString*(ctx: JSContext, `ptr`: cstring) -proc JS_NewNarrowStringLen*(ctx: JSContext, s: cstring, len: csize_t): JSValue +proc JS_NewNarrowStringLen*(ctx: JSContext; s: cstring; len: csize_t): JSValue proc JS_IsStringWideChar*(str: JSValue): JS_BOOL proc JS_GetNarrowStringBuffer*(str: JSValue): ptr UncheckedArray[uint8] proc JS_GetStringLength*(str: JSValue): uint32 -proc JS_Eval*(ctx: JSContext, input: cstring, input_len: csize_t, - filename: cstring, eval_flags: cint): JSValue -proc JS_EvalFunction*(ctx: JSContext, val: JSValue): JSValue -proc JS_SetInterruptHandler*(rt: JSRuntime, cb: JSInterruptHandler, opaque: pointer) -proc JS_SetCanBlock*(rt: JSRuntime, can_block: JS_BOOL) -proc JS_SetIsHTMLDDA*(ctx: JSContext, obj: JSValue) +proc JS_Eval*(ctx: JSContext; input: cstring; input_len: csize_t; + filename: cstring; eval_flags: cint): JSValue +proc JS_EvalFunction*(ctx: JSContext; val: JSValue): JSValue +proc JS_SetInterruptHandler*(rt: JSRuntime; cb: JSInterruptHandler; + opaque: pointer) +proc JS_SetCanBlock*(rt: JSRuntime; can_block: JS_BOOL) +proc JS_SetIsHTMLDDA*(ctx: JSContext; obj: JSValue) proc JS_IsNumber*(v: JSValue): JS_BOOL proc JS_IsBigInt*(v: JSValue): JS_BOOL @@ -489,40 +520,46 @@ proc JS_IsString*(v: JSValue): JS_BOOL proc JS_IsSymbol*(v: JSValue): JS_BOOL proc JS_IsObject*(v: JSValue): JS_BOOL -proc JS_IsFunction*(ctx: JSContext, val: JSValue): JS_BOOL -proc JS_IsArray*(ctx: JSContext, v: JSValue): cint +proc JS_IsFunction*(ctx: JSContext; val: JSValue): JS_BOOL +proc JS_IsArray*(ctx: JSContext; v: JSValue): cint -proc JS_Throw*(ctx: JSContext, obj: JSValue): JSValue +proc JS_Throw*(ctx: JSContext; obj: JSValue): JSValue proc JS_GetException*(ctx: JSContext): JSValue -proc JS_IsError*(ctx: JSContext, v: JSValue): JS_BOOL +proc JS_IsError*(ctx: JSContext; v: JSValue): JS_BOOL proc JS_NewError*(ctx: JSContext): JSValue -proc JS_ThrowSyntaxError*(ctx: JSContext, fmt: cstring): JSValue {.varargs, discardable.} -proc JS_ThrowTypeError*(ctx: JSContext, fmt: cstring): JSValue {.varargs, discardable.} -proc JS_ThrowReferenceError*(ctx: JSContext, fmt: cstring): JSValue {.varargs, discardable.} -proc JS_ThrowRangeError*(ctx: JSContext, fmt: cstring): JSValue {.varargs, discardable.} -proc JS_ThrowInternalError*(ctx: JSContext, fmt: cstring): JSValue {.varargs, discardable.} - -proc JS_SetModuleLoaderFunc*(rt: JSRuntime, - module_normalize: JSModuleNormalizeFunc, module_loader: JSModuleLoaderFunc, +proc JS_ThrowSyntaxError*(ctx: JSContext; fmt: cstring): JSValue {.varargs, + discardable.} +proc JS_ThrowTypeError*(ctx: JSContext; fmt: cstring): JSValue {.varargs, + discardable.} +proc JS_ThrowReferenceError*(ctx: JSContext; fmt: cstring): JSValue {.varargs, + discardable.} +proc JS_ThrowRangeError*(ctx: JSContext; fmt: cstring): JSValue {.varargs, + discardable.} +proc JS_ThrowInternalError*(ctx: JSContext; fmt: cstring): JSValue {.varargs, + discardable.} + +proc JS_SetModuleLoaderFunc*(rt: JSRuntime; + module_normalize: JSModuleNormalizeFunc; module_loader: JSModuleLoaderFunc; opaque: pointer) -proc JS_GetImportMeta*(ctx: JSContext, m: JSModuleDef): JSValue -proc JS_GetModuleName*(ctx: JSContext, m: JSModuleDef): JSAtom +proc JS_GetImportMeta*(ctx: JSContext; m: JSModuleDef): JSValue +proc JS_GetModuleName*(ctx: JSContext; m: JSModuleDef): JSAtom -proc JS_EnqueueJob*(ctx: JSContext, job_func: JSJobFunc, argc: cint, argv: ptr JSValue): cint +proc JS_EnqueueJob*(ctx: JSContext; job_func: JSJobFunc; argc: cint; + argv: ptr JSValue): cint proc JS_IsJobPending*(rt: JSRuntime): JS_BOOL -proc JS_ExecutePendingJob*(rt: JSRuntime, pctx: ptr JSContext): cint +proc JS_ExecutePendingJob*(rt: JSRuntime; pctx: ptr JSContext): cint proc JS_GetRuntimeOpaque*(rt: JSRuntime): pointer -proc JS_SetRuntimeOpaque*(rt: JSRuntime, p: pointer) +proc JS_SetRuntimeOpaque*(rt: JSRuntime; p: pointer) -proc JS_SetContextOpaque*(ctx: JSContext, opaque: pointer) +proc JS_SetContextOpaque*(ctx: JSContext; opaque: pointer) proc JS_GetContextOpaque*(ctx: JSContext): pointer -proc js_malloc*(ctx: JSContext, size: csize_t): pointer -proc js_mallocz*(ctx: JSContext, size: csize_t): pointer -proc js_realloc*(ctx: JSContext, p: pointer, size: csize_t): pointer -proc js_free_rt*(rt: JSRuntime, p: pointer) -proc js_free*(ctx: JSContext, p: pointer) +proc js_malloc*(ctx: JSContext; size: csize_t): pointer +proc js_mallocz*(ctx: JSContext; size: csize_t): pointer +proc js_realloc*(ctx: JSContext; p: pointer; size: csize_t): pointer +proc js_free_rt*(rt: JSRuntime; p: pointer) +proc js_free*(ctx: JSContext; p: pointer) -proc js_strdup*(ctx: JSContext, str: cstring): cstring +proc js_strdup*(ctx: JSContext; str: cstring): cstring {.pop.} diff --git a/src/bindings/termcap.nim b/src/bindings/termcap.nim index 4cc3241b..6d3d0e37 100644 --- a/src/bindings/termcap.nim +++ b/src/bindings/termcap.nim @@ -20,12 +20,13 @@ when termlib != "": {.passl: termlib.} {.push importc, cdecl.} const termcap_found* = true - proc tgetent*(bp: cstring, name: cstring): cint + proc tgetent*(bp: cstring; name: cstring): cint proc tgetnum*(id: cstring): cint proc tgetflag*(id: cstring): cint - proc tgetstr*(id: cstring, area: ptr cstring): cstring - proc tgoto*(cap: cstring, x, y: cint): cstring - proc tputs*(str: cstring, len: cint, putc: proc(c: char): cint {.cdecl.}): cint + proc tgetstr*(id: cstring; area: ptr cstring): cstring + proc tgoto*(cap: cstring; x, y: cint): cstring + proc tputs*(str: cstring; len: cint; putc: proc(c: char): cint {.cdecl.}): + cint {.pop.} else: const termcap_found* = false diff --git a/src/bindings/zlib.nim b/src/bindings/zlib.nim index e090bc71..e7e4e94d 100644 --- a/src/bindings/zlib.nim +++ b/src/bindings/zlib.nim @@ -35,11 +35,11 @@ const Z_UNKNOWN* = cint(2) type - alloc_func* {.importc, header: "zlib.h".} = proc (opaque: pointer, - items: cuint, size: cuint): pointer {.cdecl.} + alloc_func* {.importc, header: "zlib.h".} = proc (opaque: pointer; + items, size: cuint): pointer {.cdecl.} - free_func* {.importc, header: "zlib.h".} = proc (opaque: pointer, - address: pointer) {.cdecl.} + free_func* {.importc, header: "zlib.h".} = proc (opaque, address: pointer) + {.cdecl.} internal_state* {.importc, header: "zlib.h".} = object @@ -70,10 +70,10 @@ type proc inflateInit*(strm: z_streamp): cint proc inflate*(strm: z_streamp, flush: cint): cint proc inflateEnd*(strm: z_streamp): cint -proc compress*(dest: ptr uint8, destLen: ptr culong, source: ptr uint8, +proc compress*(dest: ptr uint8; destLen: ptr culong; source: ptr uint8; sourceLen: culong): cint proc compressBound*(sourceLen: culong): culong -proc uncompress*(dest: ptr uint8, destLen: ptr culong, source: ptr uint8, +proc uncompress*(dest: ptr uint8; destLen: ptr culong; source: ptr uint8; sourceLen: culong): cint -proc crc32*(crc: culong, buf: ptr uint8, len: cuint): culong +proc crc32*(crc: culong; buf: ptr uint8; len: cuint): culong {.pop.} diff --git a/src/config/chapath.nim b/src/config/chapath.nim index 57a8a853..8bab5070 100644 --- a/src/config/chapath.nim +++ b/src/config/chapath.nim @@ -28,29 +28,28 @@ type terminal: Option[char] UnquoteState = enum - STATE_NORMAL, STATE_TILDE, STATE_DOLLAR, STATE_IDENT, STATE_BSLASH, - STATE_CURLY_START, STATE_CURLY, STATE_CURLY_HASH, STATE_CURLY_PERC, - STATE_CURLY_COLON, STATE_CURLY_EXPAND, STATE_DONE + usNormal, usTilde, usDollar, usIdent, usBslash, usCurlyStart, usCurly, + usCurlyHash, usCurlyPerc, usCurlyColon, usCurlyExpand, usDone ChaPathError = string ChaPathResult[T] = Result[T, ChaPathError] proc unquote*(p: ChaPath): ChaPathResult[string] -proc unquote(p: string, starti: var int, terminal: Option[char]): +proc unquote(p: string; starti: var int; terminal: Option[char]): ChaPathResult[string] -proc stateNormal(ctx: var UnquoteContext, c: char) = +proc stateNormal(ctx: var UnquoteContext; c: char) = case c - of '$': ctx.state = STATE_DOLLAR - of '\\': ctx.state = STATE_BSLASH + of '$': ctx.state = usDollar + of '\\': ctx.state = usBslash of '~': if ctx.i == 0: - ctx.state = STATE_TILDE + ctx.state = usTilde else: ctx.s &= c elif ctx.terminal.isSome and ctx.terminal.get == c: - ctx.state = STATE_DONE + ctx.state = usDone else: ctx.s &= c @@ -62,9 +61,9 @@ proc flushTilde(ctx: var UnquoteContext) = if p != nil: ctx.s &= $p.pw_dir ctx.identStr = "" - ctx.state = STATE_NORMAL + ctx.state = usNormal -proc stateTilde(ctx: var UnquoteContext, c: char) = +proc stateTilde(ctx: var UnquoteContext; c: char) = if c != '/': ctx.identStr &= c else: @@ -73,30 +72,30 @@ proc stateTilde(ctx: var UnquoteContext, c: char) = # Kind of a hack. We special case `\$' (backslash-dollar) in TOML, so that # it produces itself in dquote strings. # Thus by applying stateBSlash we get '\$' -> "$", but also "\$" -> "$". -proc stateBSlash(ctx: var UnquoteContext, c: char) = +proc stateBSlash(ctx: var UnquoteContext; c: char) = if c != '$': ctx.s &= '\\' ctx.s &= c - ctx.state = STATE_NORMAL + ctx.state = usNormal -proc stateDollar(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateDollar(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # $ case c of '$': ctx.s &= $getCurrentProcessId() - ctx.state = STATE_NORMAL + ctx.state = usNormal of '0': # Note: we intentionally use getAppFileName so that any symbolic links # are resolved. ctx.s &= getAppFileName() - ctx.state = STATE_NORMAL + ctx.state = usNormal of '1'..'9': return err("Parameter substitution is not supported") of AsciiAlpha: ctx.identStr = $c - ctx.state = STATE_IDENT + ctx.state = usIdent of '{': - ctx.state = STATE_CURLY_START + ctx.state = usCurlyStart else: # > If an unquoted '$' is followed by a character that is not one of # > the following: [...] the result is unspecified. @@ -110,35 +109,35 @@ proc flushIdent(ctx: var UnquoteContext) = const BareChars = AsciiAlphaNumeric + {'_'} -proc stateIdent(ctx: var UnquoteContext, c: char) = +proc stateIdent(ctx: var UnquoteContext; c: char) = # $ident if c in BareChars: ctx.identStr &= c else: ctx.flushIdent() dec ctx.i - ctx.state = STATE_NORMAL + ctx.state = usNormal -proc stateCurlyStart(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurlyStart(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${ case c of '#': - ctx.state = STATE_CURLY_HASH + ctx.state = usCurlyHash of '%': - ctx.state = STATE_CURLY_PERC + ctx.state = usCurlyPerc of BareChars: - ctx.state = STATE_CURLY + ctx.state = usCurly dec ctx.i else: return err("unexpected character in substitution: '" & c & "'") return ok() -proc stateCurly(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurly(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${ident case c of '}': ctx.s &= $getEnv(ctx.identStr) - ctx.state = STATE_NORMAL + ctx.state = usNormal return ok() of '$': # allow $ as first char only if ctx.identStr.len > 0: @@ -149,10 +148,10 @@ proc stateCurly(ctx: var UnquoteContext, c: char): ChaPathResult[void] = if ctx.identStr.len > 0: return err("substitution without parameter name") if c == ':': - ctx.state = STATE_CURLY_COLON + ctx.state = usCurlyColon else: ctx.subChar = c - ctx.state = STATE_CURLY_EXPAND + ctx.state = usCurlyExpand return ok() of '1'..'9': return err("Parameter substitution is not supported") @@ -162,13 +161,13 @@ proc stateCurly(ctx: var UnquoteContext, c: char): ChaPathResult[void] = else: return err("unexpected character in substitution: '" & c & "'") -proc stateCurlyHash(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurlyHash(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${#ident if c == '}': let s = getEnv(ctx.identStr) ctx.s &= $s.len ctx.identStr = "" - ctx.state = STATE_NORMAL + ctx.state = usNormal return ok() if c == '$': # allow $ as first char only if ctx.identStr.len > 0: @@ -179,7 +178,7 @@ proc stateCurlyHash(ctx: var UnquoteContext, c: char): ChaPathResult[void] = ctx.identStr &= c return ok() -proc stateCurlyPerc(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurlyPerc(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${%ident if c == '}': if ctx.identStr == "CHA_BIN_DIR": @@ -189,23 +188,23 @@ proc stateCurlyPerc(ctx: var UnquoteContext, c: char): ChaPathResult[void] = else: return err("Unknown internal variable " & ctx.identStr) ctx.identStr = "" - ctx.state = STATE_NORMAL + ctx.state = usNormal return ok() if c notin BareChars: return err("unexpected character in substitution: '" & c & "'") ctx.identStr &= c return ok() -proc stateCurlyColon(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurlyColon(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${ident: if c notin {'-', '?', '+'}: # Note: we don't support `=' (assign) return err("unexpected character after colon: '" & c & "'") ctx.hasColon = true ctx.subChar = c - ctx.state = STATE_CURLY_EXPAND + ctx.state = usCurlyExpand return ok() -proc flushCurlyExpand(ctx: var UnquoteContext, word: string): +proc flushCurlyExpand(ctx: var UnquoteContext; word: string): ChaPathResult[void] = case ctx.subChar of '-': @@ -238,41 +237,40 @@ proc flushCurlyExpand(ctx: var UnquoteContext, word: string): ctx.hasColon = false return ok() -proc stateCurlyExpand(ctx: var UnquoteContext, c: char): ChaPathResult[void] = +proc stateCurlyExpand(ctx: var UnquoteContext; c: char): ChaPathResult[void] = # ${ident:-[word], ${ident:=[word], ${ident:?[word], ${ident:+[word] # word must be unquoted too. let word = ?unquote(ctx.p, ctx.i, some('}')) return ctx.flushCurlyExpand(word) -proc unquote(p: string, starti: var int, terminal: Option[char]): +proc unquote(p: string; starti: var int; terminal: Option[char]): ChaPathResult[string] = var ctx = UnquoteContext(p: p, i: starti, terminal: terminal) while ctx.i < p.len: let c = p[ctx.i] case ctx.state - of STATE_NORMAL: ctx.stateNormal(c) - of STATE_TILDE: ctx.stateTilde(c) - of STATE_BSLASH: ctx.stateBSlash(c) - of STATE_DOLLAR: ?ctx.stateDollar(c) - of STATE_IDENT: ctx.stateIdent(c) - of STATE_CURLY_START: ?ctx.stateCurlyStart(c) - of STATE_CURLY: ?ctx.stateCurly(c) - of STATE_CURLY_HASH: ?ctx.stateCurlyHash(c) - of STATE_CURLY_PERC: ?ctx.stateCurlyPerc(c) - of STATE_CURLY_COLON: ?ctx.stateCurlyColon(c) - of STATE_CURLY_EXPAND: ?ctx.stateCurlyExpand(c) - of STATE_DONE: break + of usNormal: ctx.stateNormal(c) + of usTilde: ctx.stateTilde(c) + of usBslash: ctx.stateBSlash(c) + of usDollar: ?ctx.stateDollar(c) + of usIdent: ctx.stateIdent(c) + of usCurlyStart: ?ctx.stateCurlyStart(c) + of usCurly: ?ctx.stateCurly(c) + of usCurlyHash: ?ctx.stateCurlyHash(c) + of usCurlyPerc: ?ctx.stateCurlyPerc(c) + of usCurlyColon: ?ctx.stateCurlyColon(c) + of usCurlyExpand: ?ctx.stateCurlyExpand(c) + of usDone: break inc ctx.i case ctx.state - of STATE_NORMAL, STATE_DONE: discard - of STATE_TILDE: ctx.flushTilde() - of STATE_BSLASH: ctx.s &= '\\' - of STATE_DOLLAR: ctx.s &= '$' - of STATE_IDENT: ctx.flushIdent() - of STATE_CURLY_START, STATE_CURLY, STATE_CURLY_HASH, STATE_CURLY_PERC, - STATE_CURLY_COLON: + of usNormal, usDone: discard + of usTilde: ctx.flushTilde() + of usBslash: ctx.s &= '\\' + of usDollar: ctx.s &= '$' + of usIdent: ctx.flushIdent() + of usCurlyStart, usCurly, usCurlyHash, usCurlyPerc, usCurlyColon: return err("} expected") - of STATE_CURLY_EXPAND: + of usCurlyExpand: ?ctx.flushCurlyExpand("") starti = ctx.i return ok(ctx.s) @@ -281,7 +279,7 @@ proc unquote(p: string): ChaPathResult[string] = var dummy = 0 return unquote(p, dummy, none(char)) -proc toJS*(ctx: JSContext, p: ChaPath): JSValue = +proc toJS*(ctx: JSContext; p: ChaPath): JSValue = toJS(ctx, $p) proc fromJSChaPath*(ctx: JSContext; val: JSValue): JSResult[ChaPath] = diff --git a/src/config/config.nim b/src/config/config.nim index 4f28f4e5..63bc50ab 100644 --- a/src/config/config.nim +++ b/src/config/config.nim @@ -244,7 +244,7 @@ proc delete(a: ptr ActionMap; k: string): bool {.jsdelprop.} = a[].t.del(k) return ina -func names(ctx: JSContext, a: ptr ActionMap): JSPropertyEnumList +func names(ctx: JSContext; a: ptr ActionMap): JSPropertyEnumList {.jspropnames.} = let L = uint32(a[].t.len) var list = newJSPropertyEnumList(ctx, L) diff --git a/src/config/mimetypes.nim b/src/config/mimetypes.nim index e8a0fd07..f247822e 100644 --- a/src/config/mimetypes.nim +++ b/src/config/mimetypes.nim @@ -12,7 +12,7 @@ proc hasKeyOrPut*(mimeTypes: var MimeTypes; k, v: string): bool {.borrow.} # Add mime types found in stream to mimeTypes. # No error handling for now. -proc parseMimeTypes*(mimeTypes: var MimeTypes, stream: Stream) = +proc parseMimeTypes*(mimeTypes: var MimeTypes; stream: Stream) = var line: string while stream.readLine(line): if line.len == 0: diff --git a/src/config/toml.nim b/src/config/toml.nim index 760f335d..f28c4916 100644 --- a/src/config/toml.nim +++ b/src/config/toml.nim @@ -114,38 +114,38 @@ func `$`*(val: TomlValue): string = result &= ',' result &= ']' -func `[]`*(val: TomlValue, key: string): TomlValue = +func `[]`*(val: TomlValue; key: string): TomlValue = return val.tab.map[key] iterator pairs*(val: TomlValue): (string, TomlValue) {.inline.} = for k, v in val.tab.map: yield (k, v) -func contains*(val: TomlValue, key: string): bool = +func contains*(val: TomlValue; key: string): bool = return key in val.tab.map const ValidBare = AsciiAlphaNumeric + {'-', '_'} -func peek(state: TomlParser, i: int): char = +func peek(state: TomlParser; i: int): char = return state.buf[state.at + i] -template err(state: TomlParser, msg: string): untyped = +template err(state: TomlParser; msg: string): untyped = err(state.filename & "(" & $state.line & "):" & msg) proc consume(state: var TomlParser): char = result = state.buf[state.at] inc state.at -proc seek(state: var TomlParser, n: int) = +proc seek(state: var TomlParser; n: int) = state.at += n proc reconsume(state: var TomlParser) = dec state.at -proc has(state: var TomlParser, i: int = 0): bool = +proc has(state: var TomlParser; i: int = 0): bool = return state.at + i < state.buf.len -proc consumeEscape(state: var TomlParser, c: char): Result[Rune, TomlError] = +proc consumeEscape(state: var TomlParser; c: char): Result[Rune, TomlError] = var len = 4 if c == 'U': len = 8 @@ -171,8 +171,7 @@ proc consumeEscape(state: var TomlParser, c: char): Result[Rune, TomlError] = else: return state.err("invalid escaped codepoint: " & $c) -proc consumeString(state: var TomlParser, first: char): - Result[string, string] = +proc consumeString(state: var TomlParser; first: char): Result[string, string] = var multiline = false if first == '"' and state.has(1) and state.peek(0) == '"' and state.peek(1) == '"': @@ -232,7 +231,7 @@ proc consumeString(state: var TomlParser, first: char): res &= c return ok(res) -proc consumeBare(state: var TomlParser, c: char): Result[string, TomlError] = +proc consumeBare(state: var TomlParser; c: char): Result[string, TomlError] = var res = $c while state.has(): let c = state.consume() @@ -392,7 +391,7 @@ proc consumeNoState(state: var TomlParser): Result[bool, TomlError] = type ParsedNumberType = enum NUMBER_INTEGER, NUMBER_FLOAT, NUMBER_HEX, NUMBER_OCT -proc consumeNumber(state: var TomlParser, c: char): TomlResult = +proc consumeNumber(state: var TomlParser; c: char): TomlResult = var repr = "" var numType = NUMBER_INTEGER if c == '0' and state.has(): @@ -568,7 +567,7 @@ proc consumeValue(state: var TomlParser): TomlResult = return ok(TomlValue(t: tvtString, s: "")) return state.err("unexpected end of file") -proc parseToml*(inputStream: Stream, filename = "<input>", laxnames = false): +proc parseToml*(inputStream: Stream; filename = "<input>"; laxnames = false): TomlResult = var state = TomlParser( buf: inputStream.readAll(), diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 6c56810f..9c3e5803 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -26,7 +26,7 @@ type user: DeclarationList author: seq[DeclarationList] -func appliesLR(feature: MediaFeature, window: Window, +func appliesLR(feature: MediaFeature; window: Window; n: LayoutUnit): bool = let a = px(feature.lengthrange.a, window.attrs, 0) let b = px(feature.lengthrange.b, window.attrs, 0) @@ -40,43 +40,43 @@ func appliesLR(feature: MediaFeature, window: Window, return false return true -func applies(feature: MediaFeature, window: Window): bool = +func applies(feature: MediaFeature; window: Window): bool = case feature.t - of FEATURE_COLOR: + of mftColor: return 8 in feature.range - of FEATURE_GRID: + of mftGrid: return feature.b - of FEATURE_HOVER: + of mftHover: return feature.b - of FEATURE_PREFERS_COLOR_SCHEME: + of mftPrefersColorScheme: return feature.b - of FEATURE_WIDTH: + of mftWidth: return feature.appliesLR(window, toLayoutUnit(window.attrs.width_px)) - of FEATURE_HEIGHT: + of mftHeight: return feature.appliesLR(window, toLayoutUnit(window.attrs.height_px)) - of FEATURE_SCRIPTING: + of mftScripting: return feature.b == window.settings.scripting -func applies(mq: MediaQuery, window: Window): bool = +func applies(mq: MediaQuery; window: Window): bool = case mq.t - of CONDITION_MEDIA: + of mctMedia: case mq.media - of MEDIA_TYPE_ALL: return true - of MEDIA_TYPE_PRINT: return false - of MEDIA_TYPE_SCREEN: return true - of MEDIA_TYPE_SPEECH: return false - of MEDIA_TYPE_TTY: return true - of MEDIA_TYPE_UNKNOWN: return false - of CONDITION_NOT: + of mtAll: return true + of mtPrint: return false + of mtScreen: return true + of mtSpeech: return false + of mtTty: return true + of mtUnknown: return false + of mctNot: return not mq.n.applies(window) - of CONDITION_AND: + of mctAnd: return mq.anda.applies(window) and mq.andb.applies(window) - of CONDITION_OR: + of mctOr: return mq.ora.applies(window) or mq.orb.applies(window) - of CONDITION_FEATURE: + of mctFeature: return mq.feature.applies(window) -func applies*(mqlist: MediaQueryList, window: Window): bool = +func applies*(mqlist: MediaQueryList; window: Window): bool = for mq in mqlist: if mq.applies(window): return true @@ -87,13 +87,13 @@ appliesFwdDecl = applies type ToSorts = array[PseudoElem, seq[(int, seq[CSSDeclaration])]] -proc calcRule(tosorts: var ToSorts, styledNode: StyledNode, rule: CSSRuleDef) = +proc calcRule(tosorts: var ToSorts; styledNode: StyledNode; rule: CSSRuleDef) = for sel in rule.sels: if styledNode.selectorsMatch(sel): let spec = getSpecificity(sel) tosorts[sel.pseudo].add((spec, rule.decls)) -func calcRules(styledNode: StyledNode, sheet: CSSStylesheet): DeclarationList = +func calcRules(styledNode: StyledNode; sheet: CSSStylesheet): DeclarationList = var tosorts: ToSorts let elem = Element(styledNode.node) for rule in sheet.genRules(elem.localName, elem.id, elem.classList.toks): @@ -136,24 +136,28 @@ func calcPresentationalHints(element: Element): CSSComputedValues = template map_size = let s = element.attrul(satSize) if s.isSome: - set_cv "width", CSSLength(num: float64(s.get), unit: UNIT_CH) + set_cv "width", CSSLength(num: float64(s.get), unit: cuCh) template map_valign = case element.attr(satValign).toLowerAscii() - of "top": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_TOP) - of "middle": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_MIDDLE) - of "bottom": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_BOTTOM) - of "baseline": set_cv "vertical-align", CSSVerticalAlign(keyword: VERTICAL_ALIGN_BASELINE) + of "top": + set_cv "vertical-align", CSSVerticalAlign(keyword: VerticalAlignTop) + of "middle": + set_cv "vertical-align", CSSVerticalAlign(keyword: VerticalAlignMiddle) + of "bottom": + set_cv "vertical-align", CSSVerticalAlign(keyword: VerticalAlignBottom) + of "baseline": + set_cv "vertical-align", CSSVerticalAlign(keyword: VerticalAlignBaseline) template map_align = case element.attr(satAlign).toLowerAscii() - of "center", "middle": set_cv "text-align", TEXT_ALIGN_CHA_CENTER - of "left": set_cv "text-align", TEXT_ALIGN_CHA_LEFT - of "right": set_cv "text-align", TEXT_ALIGN_CHA_RIGHT + of "center", "middle": set_cv "text-align", TextAlignChaCenter + of "left": set_cv "text-align", TextAlignChaLeft + of "right": set_cv "text-align", TextAlignChaRight template map_table_align = case element.attr(satAlign).toLowerAscii() of "left": - set_cv "float", FLOAT_LEFT + set_cv "float", FloatLeft of "right": - set_cv "float", FLOAT_RIGHT + set_cv "float", FloatRight of "center": set_cv "margin-left", CSSLengthAuto #TODO should be inline-start set_cv "margin-right", CSSLengthAuto #TODO should be inline-end @@ -185,20 +189,20 @@ func calcPresentationalHints(element: Element): CSSComputedValues = let ctype = element.attr(satType) if ctype.len > 0: case ctype[0] - of '1': set_cv "list-style-type", LIST_STYLE_TYPE_DECIMAL - of 'a': set_cv "list-style-type", LIST_STYLE_TYPE_LOWER_ALPHA - of 'A': set_cv "list-style-type", LIST_STYLE_TYPE_UPPER_ALPHA - of 'i': set_cv "list-style-type", LIST_STYLE_TYPE_LOWER_ROMAN - of 'I': set_cv "list-style-type", LIST_STYLE_TYPE_UPPER_ROMAN + of '1': set_cv "list-style-type", ListStyleTypeDecimal + of 'a': set_cv "list-style-type", ListStyleTypeLowerAlpha + of 'A': set_cv "list-style-type", ListStyleTypeUpperAlpha + of 'i': set_cv "list-style-type", ListStyleTypeLowerRoman + of 'I': set_cv "list-style-type", ListStyleTypeUpperRoman else: discard template map_list_type_ul = let ctype = element.attr(satType) if ctype.len > 0: case ctype.toLowerAscii() - of "none": set_cv "list-style-type", LIST_STYLE_TYPE_NONE - of "disc": set_cv "list-style-type", LIST_STYLE_TYPE_DISC - of "circle": set_cv "list-style-type", LIST_STYLE_TYPE_CIRCLE - of "square": set_cv "list-style-type", LIST_STYLE_TYPE_SQUARE + of "none": set_cv "list-style-type", ListStyleTypeNone + of "disc": set_cv "list-style-type", ListStyleTypeDisc + of "circle": set_cv "list-style-type", ListStyleTypeCircle + of "square": set_cv "list-style-type", ListStyleTypeSquare template set_bgcolor_is_canvas = set_cv "-cha-bgcolor-is-canvas", true @@ -238,8 +242,8 @@ func calcPresentationalHints(element: Element): CSSComputedValues = let textarea = HTMLTextAreaElement(element) let cols = textarea.attrul(satCols).get(20) let rows = textarea.attrul(satRows).get(1) - set_cv "width", CSSLength(unit: UNIT_CH, num: float64(cols)) - set_cv "height", CSSLength(unit: UNIT_EM, num: float64(rows)) + set_cv "width", CSSLength(unit: cuCh, num: float64(cols)) + set_cv "height", CSSLength(unit: cuEm, num: float64(rows)) of TAG_FONT: map_color of TAG_INPUT: @@ -252,35 +256,35 @@ func calcPresentationalHints(element: Element): CSSComputedValues = map_list_type_ul else: discard -proc applyDeclarations(styledNode: StyledNode, parent: CSSComputedValues, +proc applyDeclarations(styledNode: StyledNode; parent: CSSComputedValues; map: DeclarationListMap) = - let pseudo = PSEUDO_NONE + let pseudo = peNone var builder = CSSComputedValuesBuilder(parent: parent) - builder.addValues(map.ua[pseudo], ORIGIN_USER_AGENT) - builder.addValues(map.user[pseudo], ORIGIN_USER) + builder.addValues(map.ua[pseudo], coUserAgent) + builder.addValues(map.user[pseudo], coUser) for rule in map.author: - builder.addValues(rule[pseudo], ORIGIN_AUTHOR) + builder.addValues(rule[pseudo], coAuthor) if styledNode.node != nil: let element = Element(styledNode.node) let style = element.style_cached if style != nil: - builder.addValues(style.decls, ORIGIN_AUTHOR) + builder.addValues(style.decls, coAuthor) builder.preshints = element.calcPresentationalHints() styledNode.computed = builder.buildComputedValues() # Either returns a new styled node or nil. -proc applyDeclarations(pseudo: PseudoElem, styledParent: StyledNode, +proc applyDeclarations(pseudo: PseudoElem; styledParent: StyledNode; map: DeclarationListMap): StyledNode = var builder = CSSComputedValuesBuilder(parent: styledParent.computed) - builder.addValues(map.ua[pseudo], ORIGIN_USER_AGENT) - builder.addValues(map.user[pseudo], ORIGIN_USER) + builder.addValues(map.ua[pseudo], coUserAgent) + builder.addValues(map.user[pseudo], coUser) for rule in map.author: - builder.addValues(rule[pseudo], ORIGIN_AUTHOR) + builder.addValues(rule[pseudo], coAuthor) if builder.hasValues(): let cvals = builder.buildComputedValues() result = styledParent.newStyledElement(pseudo, cvals) -func applyMediaQuery(ss: CSSStylesheet, window: Window): CSSStylesheet = +func applyMediaQuery(ss: CSSStylesheet; window: Window): CSSStylesheet = if ss == nil: return nil new(result) result[] = ss[] @@ -288,7 +292,7 @@ func applyMediaQuery(ss: CSSStylesheet, window: Window): CSSStylesheet = if mq.query.applies(window): result.add(mq.children.applyMediaQuery(window)) -func calcRules(styledNode: StyledNode, ua, user: CSSStylesheet, +func calcRules(styledNode: StyledNode; ua, user: CSSStylesheet; author: seq[CSSStylesheet]): DeclarationListMap = let uadecls = calcRules(styledNode, ua) var userdecls: DeclarationList @@ -303,7 +307,7 @@ func calcRules(styledNode: StyledNode, ua, user: CSSStylesheet, author: authordecls ) -proc applyStyle(parent, styledNode: StyledNode, map: DeclarationListMap) = +proc applyStyle(parent, styledNode: StyledNode; map: DeclarationListMap) = let parentComputed = if parent != nil: parent.computed else: @@ -326,8 +330,8 @@ proc getAuthorSheets(document: Document): seq[CSSStylesheet] = proc applyRulesFrameValid(frame: CascadeFrame): StyledNode = let styledParent = frame.styledParent let cachedChild = frame.cachedChild - let styledChild = if cachedChild.t == STYLED_ELEMENT: - if cachedChild.pseudo != PSEUDO_NONE: + let styledChild = if cachedChild.t == stElement: + if cachedChild.pseudo != peNone: # Pseudo elements can't have invalid children. cachedChild else: @@ -344,15 +348,15 @@ proc applyRulesFrameValid(frame: CascadeFrame): StyledNode = styledParent.children.add(styledChild) return styledChild -proc applyRulesFrameInvalid(frame: CascadeFrame, ua, user: CSSStylesheet, - author: seq[CSSStylesheet], declmap: var DeclarationListMap): StyledNode = +proc applyRulesFrameInvalid(frame: CascadeFrame; ua, user: CSSStylesheet; + author: seq[CSSStylesheet]; declmap: var DeclarationListMap): StyledNode = var styledChild: StyledNode let pseudo = frame.pseudo let styledParent = frame.styledParent let child = frame.child - if frame.pseudo != PSEUDO_NONE: + if frame.pseudo != peNone: case pseudo - of PSEUDO_BEFORE, PSEUDO_AFTER: + of peBefore, peAfter: let declmap = frame.parentDeclMap let styledPseudo = pseudo.applyDeclarations(styledParent, declmap) if styledPseudo != nil: @@ -360,7 +364,7 @@ proc applyRulesFrameInvalid(frame: CascadeFrame, ua, user: CSSStylesheet, for content in contents: styledPseudo.children.add(styledPseudo.newStyledReplacement(content)) styledParent.children.add(styledPseudo) - of PSEUDO_INPUT_TEXT: + of peInputText: let content = HTMLInputElement(styledParent.node).inputString() if content.len > 0: let styledText = styledParent.newStyledText(content) @@ -368,34 +372,34 @@ proc applyRulesFrameInvalid(frame: CascadeFrame, ua, user: CSSStylesheet, # directly, so we have to cache them like this. styledText.pseudo = pseudo styledParent.children.add(styledText) - of PSEUDO_TEXTAREA_TEXT: + of peTextareaText: let content = HTMLTextAreaElement(styledParent.node).textAreaString() if content.len > 0: let styledText = styledParent.newStyledText(content) styledText.pseudo = pseudo styledParent.children.add(styledText) - of PSEUDO_IMAGE: + of peImage: let src = Element(styledParent.node).attr(satSrc) - let content = CSSContent(t: CONTENT_IMAGE, s: src) + let content = CSSContent(t: ContentImage, s: src) let styledText = styledParent.newStyledReplacement(content) styledText.pseudo = pseudo styledParent.children.add(styledText) - of PSEUDO_VIDEO: - let content = CSSContent(t: CONTENT_VIDEO) + of peVideo: + let content = CSSContent(t: ContentVideo) let styledText = styledParent.newStyledReplacement(content) styledText.pseudo = pseudo styledParent.children.add(styledText) - of PSEUDO_AUDIO: - let content = CSSContent(t: CONTENT_AUDIO) + of peAudio: + let content = CSSContent(t: ContentAudio) let styledText = styledParent.newStyledReplacement(content) styledText.pseudo = pseudo styledParent.children.add(styledText) - of PSEUDO_NEWLINE: - let content = CSSContent(t: CONTENT_NEWLINE) + of peNewline: + let content = CSSContent(t: ContentNewline) let styledText = styledParent.newStyledReplacement(content) styledParent.children.add(styledText) styledText.pseudo = pseudo - of PSEUDO_NONE: assert false + of peNone: assert false else: assert child != nil if styledParent != nil: @@ -415,8 +419,8 @@ proc applyRulesFrameInvalid(frame: CascadeFrame, ua, user: CSSStylesheet, applyStyle(styledParent, styledChild, declmap) return styledChild -proc stackAppend(styledStack: var seq[CascadeFrame], frame: CascadeFrame, - styledParent: StyledNode, child: Node, i: var int) = +proc stackAppend(styledStack: var seq[CascadeFrame]; frame: CascadeFrame; + styledParent: StyledNode; child: Node; i: var int) = if frame.cachedChild != nil: var cached: StyledNode while i >= 0: @@ -428,19 +432,19 @@ proc stackAppend(styledStack: var seq[CascadeFrame], frame: CascadeFrame, styledStack.add(CascadeFrame( styledParent: styledParent, child: child, - pseudo: PSEUDO_NONE, + pseudo: peNone, cachedChild: cached )) else: styledStack.add(CascadeFrame( styledParent: styledParent, child: child, - pseudo: PSEUDO_NONE, + pseudo: peNone, cachedChild: nil )) -proc stackAppend(styledStack: var seq[CascadeFrame], frame: CascadeFrame, - styledParent: StyledNode, pseudo: PseudoElem, i: var int, +proc stackAppend(styledStack: var seq[CascadeFrame]; frame: CascadeFrame; + styledParent: StyledNode; pseudo: PseudoElem; i: var int; parentDeclMap: DeclarationListMap = nil) = if frame.cachedChild != nil: var cached: StyledNode @@ -474,42 +478,43 @@ proc stackAppend(styledStack: var seq[CascadeFrame], frame: CascadeFrame, )) # Append children to styledChild. -proc appendChildren(styledStack: var seq[CascadeFrame], frame: CascadeFrame, - styledChild: StyledNode, parentDeclMap: DeclarationListMap) = +proc appendChildren(styledStack: var seq[CascadeFrame]; frame: CascadeFrame; + styledChild: StyledNode; parentDeclMap: DeclarationListMap) = # i points to the child currently being inspected. var idx = if frame.cachedChild != nil: frame.cachedChild.children.len - 1 else: -1 let elem = Element(styledChild.node) - styledStack.stackAppend(frame, styledChild, PSEUDO_AFTER, idx, parentDeclMap) + styledStack.stackAppend(frame, styledChild, peAfter, idx, parentDeclMap) if elem.tagType == TAG_TEXTAREA: - styledStack.stackAppend(frame, styledChild, PSEUDO_TEXTAREA_TEXT, idx) + styledStack.stackAppend(frame, styledChild, peTextareaText, idx) elif elem.tagType == TAG_IMG or elem.tagType == TAG_IMAGE: - styledStack.stackAppend(frame, styledChild, PSEUDO_IMAGE, idx) + styledStack.stackAppend(frame, styledChild, peImage, idx) elif elem.tagType == TAG_VIDEO: - styledStack.stackAppend(frame, styledChild, PSEUDO_VIDEO, idx) + styledStack.stackAppend(frame, styledChild, peVideo, idx) elif elem.tagType == TAG_AUDIO: - styledStack.stackAppend(frame, styledChild, PSEUDO_AUDIO, idx) + styledStack.stackAppend(frame, styledChild, peAudio, idx) elif elem.tagType == TAG_BR: - styledStack.stackAppend(frame, styledChild, PSEUDO_NEWLINE, idx) + styledStack.stackAppend(frame, styledChild, peNewline, idx) else: for i in countdown(elem.childList.high, 0): if elem.childList[i] of Element or elem.childList[i] of Text: styledStack.stackAppend(frame, styledChild, elem.childList[i], idx) if elem.tagType == TAG_INPUT: - styledStack.stackAppend(frame, styledChild, PSEUDO_INPUT_TEXT, idx) - styledStack.stackAppend(frame, styledChild, PSEUDO_BEFORE, idx, parentDeclMap) + styledStack.stackAppend(frame, styledChild, peInputText, idx) + styledStack.stackAppend(frame, styledChild, peBefore, idx, parentDeclMap) # Builds a StyledNode tree, optionally based on a previously cached version. -proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledNode): StyledNode = +proc applyRules(document: Document; ua, user: CSSStylesheet; + cachedTree: StyledNode): StyledNode = let html = document.html if html == nil: return let author = document.getAuthorSheets() var styledStack = @[CascadeFrame( child: html, - pseudo: PSEUDO_NONE, + pseudo: peNone, cachedChild: cachedTree )] var root: StyledNode @@ -529,12 +534,12 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN if styledParent == nil: # Root element root = styledChild - if styledChild.t == STYLED_ELEMENT and styledChild.node != nil: + if styledChild.t == stElement and styledChild.node != nil: styledChild.applyDependValues() styledStack.appendChildren(frame, styledChild, declmap) return root -proc applyStylesheets*(document: Document, uass, userss: CSSStylesheet, +proc applyStylesheets*(document: Document; uass, userss: CSSStylesheet; previousStyled: StyledNode): StyledNode = let uass = uass.applyMediaQuery(document.window) let userss = userss.applyMediaQuery(document.window) diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim index 2463acb2..083ab421 100644 --- a/src/css/cssparser.nim +++ b/src/css/cssparser.nim @@ -8,13 +8,10 @@ import utils/twtstr type CSSTokenType* = enum - CSS_NO_TOKEN, CSS_IDENT_TOKEN, CSS_FUNCTION_TOKEN, CSS_AT_KEYWORD_TOKEN, - CSS_HASH_TOKEN, CSS_STRING_TOKEN, CSS_BAD_STRING_TOKEN, CSS_URL_TOKEN, - CSS_BAD_URL_TOKEN, CSS_DELIM_TOKEN, CSS_NUMBER_TOKEN, CSS_PERCENTAGE_TOKEN, - CSS_DIMENSION_TOKEN, CSS_WHITESPACE_TOKEN, CSS_CDO_TOKEN, CSS_CDC_TOKEN, - CSS_COLON_TOKEN, CSS_SEMICOLON_TOKEN, CSS_COMMA_TOKEN, CSS_RBRACKET_TOKEN, - CSS_LBRACKET_TOKEN, CSS_LPAREN_TOKEN, CSS_RPAREN_TOKEN, CSS_LBRACE_TOKEN, - CSS_RBRACE_TOKEN + cttIdent, cttFunction, cttAtKeyword, cttHash, cttString, cttBadString, + cttUrl, cttBadUrl, cttDelim, cttNumber, cttPercentage, cttDimension, + cttWhitespace, cttCdo, cttCdc, cttColon, cttSemicolon, cttComma, + cttRbracket, cttLbracket, cttLparen, cttRparen, cttLbrace, cttRbrace CSSTokenizerState = object at: int @@ -26,23 +23,24 @@ type tokens: seq[CSSParsedItem] at: int - tflaga* = enum - TFLAGA_UNRESTRICTED, TFLAGA_ID + tflaga = enum + tflagaUnrestricted, tflagaId + tflagb* = enum - TFLAGB_INTEGER, TFLAGB_NUMBER + tflagbInteger, tflagbNumber CSSParsedItem* = ref object of RootObj CSSComponentValue* = ref object of CSSParsedItem CSSToken* = ref object of CSSComponentValue case tokenType*: CSSTokenType - of CSS_IDENT_TOKEN, CSS_FUNCTION_TOKEN, CSS_AT_KEYWORD_TOKEN, - CSS_HASH_TOKEN, CSS_STRING_TOKEN, CSS_URL_TOKEN: + of cttIdent, cttFunction, cttAtKeyword, + cttHash, cttString, cttUrl: value*: string tflaga*: tflaga - of CSS_DELIM_TOKEN: + of cttDelim: cvalue*: char - of CSS_NUMBER_TOKEN, CSS_PERCENTAGE_TOKEN, CSS_DIMENSION_TOKEN: + of cttNumber, cttPercentage, cttDimension: nvalue*: float64 tflagb*: tflagb unit*: string @@ -80,38 +78,38 @@ proc `$`*(c: CSSParsedItem): string = if c of CSSToken: let c = CSSToken(c) case c.tokenType: - of CSS_FUNCTION_TOKEN, CSS_AT_KEYWORD_TOKEN: + of cttFunction, cttAtKeyword: result &= $c.tokenType & c.value & '\n' - of CSS_URL_TOKEN: + of cttUrl: result &= "url(" & c.value & ")" - of CSS_HASH_TOKEN: + of cttHash: result &= '#' & c.value - of CSS_IDENT_TOKEN: + of cttIdent: result &= c.value - of CSS_STRING_TOKEN: + of cttString: result &= ("\"" & c.value & "\"") - of CSS_DELIM_TOKEN: + of cttDelim: if c.cvalue != char(128): result &= c.cvalue else: result &= "<UNICODE>" - of CSS_DIMENSION_TOKEN: + of cttDimension: case c.tflagb - of TFLAGB_NUMBER: + of tflagbNumber: result &= $c.nvalue & c.unit - of TFLAGB_INTEGER: + of tflagbInteger: result &= $int64(c.nvalue) & c.unit - of CSS_NUMBER_TOKEN: + of cttNumber: result &= $c.nvalue & c.unit - of CSS_PERCENTAGE_TOKEN: + of cttPercentage: result &= $c.nvalue & "%" - of CSS_COLON_TOKEN: + of cttColon: result &= ":" - of CSS_WHITESPACE_TOKEN: + of cttWhitespace: result &= " " - of CSS_SEMICOLON_TOKEN: + of cttSemicolon: result &= ";\n" - of CSS_COMMA_TOKEN: + of cttComma: result &= "," else: result &= $c.tokenType & '\n' @@ -131,16 +129,16 @@ proc `$`*(c: CSSParsedItem): string = result &= ")" elif c of CSSSimpleBlock: case CSSSimpleBlock(c).token.tokenType - of CSS_LBRACE_TOKEN: result &= "{\n" - of CSS_LPAREN_TOKEN: result &= "(" - of CSS_LBRACKET_TOKEN: result &= "[" + of cttLbrace: result &= "{\n" + of cttLparen: result &= "(" + of cttLbracket: result &= "[" else: discard for s in CSSSimpleBlock(c).value: result &= $s case CSSSimpleBlock(c).token.tokenType - of CSS_LBRACE_TOKEN: result &= "\n}" - of CSS_LPAREN_TOKEN: result &= ")" - of CSS_LBRACKET_TOKEN: result &= "]" + of cttLbrace: result &= "\n}" + of cttLparen: result &= ")" + of cttLbracket: result &= "]" else: discard elif c of CSSRule: if c of CSSAtRule: @@ -169,10 +167,10 @@ proc consumeRChar(state: var CSSTokenizerState): char = proc reconsume(state: var CSSTokenizerState) = dec state.at -func peek(state: CSSTokenizerState, i: int = 0): char = +func peek(state: CSSTokenizerState; i: int = 0): char = return state.buf[state.at + i] -proc has(state: var CSSTokenizerState, i: int = 0): bool = +proc has(state: var CSSTokenizerState; i: int = 0): bool = if state.at + i >= state.buf.len and not state.stream.atEnd(): try: state.buf &= state.stream.readStr(256) @@ -190,7 +188,8 @@ proc isValidEscape(state: var CSSTokenizerState): bool = proc startsWithIdentSequence(state: var CSSTokenizerState): bool = case state.curr of '-': - return state.has() and state.peek() in IdentStart + {'-'} or state.has(1) and state.isValidEscape() + return state.has() and state.peek() in IdentStart + {'-'} or + state.has(1) and state.isValidEscape() of IdentStart: return true of '\\': @@ -202,7 +201,6 @@ proc startsWithIdentSequence(state: var CSSTokenizerState): bool = proc next3startsWithIdentSequence(state: var CSSTokenizerState): bool = if not state.has(): return false - case state.peek() of '-': return state.has(1) and state.peek(1) in IdentStart + {'-'} or @@ -266,7 +264,7 @@ proc consumeString(state: var CSSTokenizerState): CSSToken = case c of '\n': state.reconsume() - return CSSToken(tokenType: CSS_BAD_STRING_TOKEN) + return CSSToken(tokenType: cttBadString) of '\\': if not state.has(): continue @@ -278,7 +276,7 @@ proc consumeString(state: var CSSTokenizerState): CSSToken = break else: s &= c - return CSSToken(tokenType: CSS_STRING_TOKEN, value: s) + return CSSToken(tokenType: cttString, value: s) proc consumeIdentSequence(state: var CSSTokenizerState): string = while state.has(): @@ -292,7 +290,7 @@ proc consumeIdentSequence(state: var CSSTokenizerState): string = return result proc consumeNumber(state: var CSSTokenizerState): (tflagb, float64) = - var t = TFLAGB_INTEGER + var t = tflagbInteger var repr: string if state.has() and state.peek() in {'+', '-'}: repr &= state.consume() @@ -303,19 +301,21 @@ proc consumeNumber(state: var CSSTokenizerState): (tflagb, float64) = if state.has(1) and state.peek() == '.' and state.peek(1) in AsciiDigit: repr &= state.consume() repr &= state.consume() - t = TFLAGB_NUMBER + t = tflagbNumber while state.has() and state.peek() in AsciiDigit: repr &= state.consume() - if state.has(1) and state.peek() in {'E', 'e'} and state.peek(1) in AsciiDigit or - state.has(2) and state.peek() in {'E', 'e'} and state.peek(1) in {'-', '+'} and state.peek(2) in AsciiDigit: + if state.has(1) and state.peek() in {'E', 'e'} and + state.peek(1) in AsciiDigit or + state.has(2) and state.peek() in {'E', 'e'} and + state.peek(1) in {'-', '+'} and state.peek(2) in AsciiDigit: repr &= state.consume() if state.peek() in {'-', '+'}: repr &= state.consume() repr &= state.consume() else: repr &= state.consume() - t = TFLAGB_NUMBER + t = tflagbNumber while state.has() and state.peek() in AsciiDigit: repr &= state.consume() @@ -325,13 +325,13 @@ proc consumeNumber(state: var CSSTokenizerState): (tflagb, float64) = proc consumeNumericToken(state: var CSSTokenizerState): CSSToken = let (t, val) = state.consumeNumber() if state.next3startsWithIdentSequence(): - result = CSSToken(tokenType: CSS_DIMENSION_TOKEN, nvalue: val, tflagb: t) + result = CSSToken(tokenType: cttDimension, nvalue: val, tflagb: t) result.unit = state.consumeIdentSequence() elif state.has() and state.peek() == '%': discard state.consume() - result = CSSToken(tokenType: CSS_PERCENTAGE_TOKEN, nvalue: val) + result = CSSToken(tokenType: cttPercentage, nvalue: val) else: - result = CSSToken(tokenType: CSS_NUMBER_TOKEN, nvalue: val, tflagb: t) + result = CSSToken(tokenType: cttNumber, nvalue: val, tflagb: t) proc consumeBadURL(state: var CSSTokenizerState) = while state.has(): @@ -343,10 +343,13 @@ proc consumeBadURL(state: var CSSTokenizerState) = discard state.consumeEscape() else: discard -const NonPrintable = {char(0x00)..char(0x08), char(0x0B), char(0x0E)..char(0x1F), char(0x7F)} +const NonPrintable = { + char(0x00)..char(0x08), char(0x0B), + char(0x0E)..char(0x1F), char(0x7F) +} proc consumeURL(state: var CSSTokenizerState): CSSToken = - result = CSSToken(tokenType: CSS_URL_TOKEN) + result = CSSToken(tokenType: cttUrl) while state.has() and state.peek() in AsciiWhitespace: discard state.consume() @@ -357,7 +360,7 @@ proc consumeURL(state: var CSSTokenizerState): CSSToken = return result of '"', '\'', '(', NonPrintable: state.consumeBadURL() - return CSSToken(tokenType: CSS_BAD_URL_TOKEN) + return CSSToken(tokenType: cttBadUrl) of AsciiWhitespace: while state.has() and state.peek() in AsciiWhitespace: discard state.consume() @@ -367,14 +370,14 @@ proc consumeURL(state: var CSSTokenizerState): CSSToken = discard state.consume() return result state.consumeBadURL() - return CSSToken(tokenType: CSS_BAD_URL_TOKEN) + return CSSToken(tokenType: cttBadUrl) of '\\': state.reconsume() if state.isValidEscape(): result.value &= state.consumeEscape() else: state.consumeBadURL() - return CSSToken(tokenType: CSS_BAD_URL_TOKEN) + return CSSToken(tokenType: cttBadUrl) else: result.value &= c @@ -386,21 +389,23 @@ proc consumeIdentLikeToken(state: var CSSTokenizerState): CSSToken = state.peek(1) in AsciiWhitespace: discard state.consume() if state.has() and state.peek() in {'"', '\''} or - state.has(1) and state.peek() in {'"', '\''} + AsciiWhitespace and state.peek(1) in {'"', '\''}: - return CSSToken(tokenType: CSS_FUNCTION_TOKEN, value: s) + state.has(1) and state.peek() in {'"', '\''} + AsciiWhitespace and + state.peek(1) in {'"', '\''}: + return CSSToken(tokenType: cttFunction, value: s) else: return state.consumeURL() elif state.has() and state.peek() == '(': discard state.consume() - return CSSToken(tokenType: CSS_FUNCTION_TOKEN, value: s) + return CSSToken(tokenType: cttFunction, value: s) - return CSSToken(tokenType: CSS_IDENT_TOKEN, value: s) + return CSSToken(tokenType: cttIdent, value: s) proc consumeComments(state: var CSSTokenizerState) = if state.has(1) and state.peek() == '/' and state.peek(1) == '*': discard state.consume() discard state.consume() - while state.has() and not (state.has(1) and state.peek() == '*' and state.peek(1) == '/'): + while state.has() and not (state.has(1) and state.peek() == '*' and + state.peek(1) == '/'): discard state.consume() if state.has(1): discard state.consume() @@ -416,29 +421,29 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = of AsciiWhitespace: while state.has() and state.peek() in AsciiWhitespace: discard state.consume() - return CSSToken(tokenType: CSS_WHITESPACE_TOKEN) + return CSSToken(tokenType: cttWhitespace) of '"', '\'': return consumeString(state) of '#': if state.has() and state.peek() in Ident or state.isValidEscape(): - result = CSSToken(tokenType: CSS_HASH_TOKEN) + result = CSSToken(tokenType: cttHash) if state.startsWithIdentSequence(): - result.tflaga = TFLAGA_ID + result.tflaga = tflagaId result.value = consumeIdentSequence(state) else: state.reconsume() - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: state.consumeRChar()) - of '(': return CSSToken(tokenType: CSS_LPAREN_TOKEN) - of ')': return CSSToken(tokenType: CSS_RPAREN_TOKEN) - of '{': return CSSToken(tokenType: CSS_LBRACE_TOKEN) - of '}': return CSSToken(tokenType: CSS_RBRACE_TOKEN) + return CSSToken(tokenType: cttDelim, cvalue: state.consumeRChar()) + of '(': return CSSToken(tokenType: cttLparen) + of ')': return CSSToken(tokenType: cttRparen) + of '{': return CSSToken(tokenType: cttLbrace) + of '}': return CSSToken(tokenType: cttRbrace) of '+': if state.startsWithNumber(): state.reconsume() return state.consumeNumericToken() else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) - of ',': return CSSToken(tokenType: CSS_COMMA_TOKEN) + return CSSToken(tokenType: cttDelim, cvalue: c) + of ',': return CSSToken(tokenType: cttComma) of '-': if state.startsWithNumber(): state.reconsume() @@ -447,42 +452,43 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = if state.has(1) and state.peek() == '-' and state.peek(1) == '>': discard state.consume() discard state.consume() - return CSSToken(tokenType: CSS_CDC_TOKEN) + return CSSToken(tokenType: cttCdc) elif state.startsWithIdentSequence(): state.reconsume() return state.consumeIdentLikeToken() else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) + return CSSToken(tokenType: cttDelim, cvalue: c) of '.': if state.startsWithNumber(): state.reconsume() return state.consumeNumericToken() else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) - of ':': return CSSToken(tokenType: CSS_COLON_TOKEN) - of ';': return CSSToken(tokenType: CSS_SEMICOLON_TOKEN) + return CSSToken(tokenType: cttDelim, cvalue: c) + of ':': return CSSToken(tokenType: cttColon) + of ';': return CSSToken(tokenType: cttSemicolon) of '<': - if state.has(2) and state.peek() == '!' and state.peek(1) == '-' and state.peek(2) == '-': + if state.has(2) and state.peek() == '!' and state.peek(1) == '-' and + state.peek(2) == '-': discard state.consume() discard state.consume() discard state.consume() - return CSSToken(tokenType: CSS_CDO_TOKEN) + return CSSToken(tokenType: cttCdo) else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) + return CSSToken(tokenType: cttDelim, cvalue: c) of '@': if state.next3startsWithIdentSequence(): let name = state.consumeIdentSequence() - return CSSToken(tokenType: CSS_AT_KEYWORD_TOKEN, value: name) + return CSSToken(tokenType: cttAtKeyword, value: name) else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) - of '[': return CSSToken(tokenType: CSS_LBRACKET_TOKEN) + return CSSToken(tokenType: cttDelim, cvalue: c) + of '[': return CSSToken(tokenType: cttLbracket) of '\\': if state.isValidEscape(): state.reconsume() return state.consumeIdentLikeToken() else: - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: c) - of ']': return CSSToken(tokenType: CSS_RBRACKET_TOKEN) + return CSSToken(tokenType: cttDelim, cvalue: c) + of ']': return CSSToken(tokenType: cttRbracket) of AsciiDigit: state.reconsume() return state.consumeNumericToken() @@ -491,7 +497,7 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = return state.consumeIdentLikeToken() else: state.reconsume() - return CSSToken(tokenType: CSS_DELIM_TOKEN, cvalue: state.consumeRChar()) + return CSSToken(tokenType: cttDelim, cvalue: state.consumeRChar()) proc tokenizeCSS*(inputStream: Stream): seq[CSSParsedItem] = var state: CSSTokenizerState @@ -514,7 +520,7 @@ proc consume(state: var CSSParseState): CSSParsedItem = proc reconsume(state: var CSSParseState) = dec state.at -func has(state: CSSParseState, i: int = 0): bool = +func has(state: CSSParseState; i: int = 0): bool = return state.at + i < state.tokens.len func peek(state: CSSParseState): CSSParsedItem = @@ -527,9 +533,9 @@ proc consumeSimpleBlock(state: var CSSParseState): CSSSimpleBlock = let t = CSSToken(state.consume()) var ending: CSSTokenType case t.tokenType - of CSS_LBRACE_TOKEN: ending = CSS_RBRACE_TOKEN - of CSS_LPAREN_TOKEN: ending = CSS_RPAREN_TOKEN - of CSS_LBRACKET_TOKEN: ending = CSS_RBRACKET_TOKEN + of cttLbrace: ending = cttRbrace + of cttLparen: ending = cttRparen + of cttLbracket: ending = cttRbracket else: doAssert false result = CSSSimpleBlock(token: t) @@ -538,7 +544,7 @@ proc consumeSimpleBlock(state: var CSSParseState): CSSSimpleBlock = if t == ending: return result else: - if t == CSS_LBRACE_TOKEN or t == CSS_LBRACKET_TOKEN or t == CSS_LPAREN_TOKEN: + if t == cttLbrace or t == cttLbracket or t == cttLparen: result.value.add(state.consumeSimpleBlock()) else: state.reconsume() @@ -550,7 +556,7 @@ proc consumeFunction(state: var CSSParseState): CSSFunction = result = CSSFunction(name: t.value) while state.at < state.tokens.len: let t = state.consume() - if t == CSS_RPAREN_TOKEN: + if t == cttRparen: return result else: state.reconsume() @@ -558,9 +564,9 @@ proc consumeFunction(state: var CSSParseState): CSSFunction = proc consumeComponentValue(state: var CSSParseState): CSSComponentValue = let t = state.consume() - if t == CSS_LBRACE_TOKEN or t == CSS_LBRACKET_TOKEN or t == CSS_LPAREN_TOKEN: + if t == cttLbrace or t == cttLbracket or t == cttLparen: return state.consumeSimpleBlock() - elif t == CSS_FUNCTION_TOKEN: + elif t == cttFunction: state.reconsume() return state.consumeFunction() return CSSComponentValue(t) @@ -569,10 +575,10 @@ proc consumeQualifiedRule(state: var CSSParseState): Option[CSSQualifiedRule] = var r = CSSQualifiedRule() while state.has(): let t = state.consume() - if t of CSSSimpleBlock and CSSSimpleBlock(t).token == CSS_LBRACE_TOKEN: + if t of CSSSimpleBlock and CSSSimpleBlock(t).token == cttLbrace: r.oblock = CSSSimpleBlock(t) return some(r) - elif t == CSS_LBRACE_TOKEN: + elif t == cttLbrace: r.oblock = state.consumeSimpleBlock() return some(r) else: @@ -589,9 +595,9 @@ proc consumeAtRule(state: var CSSParseState): CSSAtRule = let t = state.consume() if t of CSSSimpleBlock: result.oblock = CSSSimpleBlock(t) - elif t == CSS_SEMICOLON_TOKEN: + elif t == cttSemicolon: return result - elif t == CSS_LBRACE_TOKEN: + elif t == cttLbrace: result.oblock = state.consumeSimpleBlock() return result else: @@ -601,12 +607,12 @@ proc consumeAtRule(state: var CSSParseState): CSSAtRule = proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = let t = CSSToken(state.consume()) var decl = CSSDeclaration(name: t.value) - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() - if not state.has() or state.peek() != CSS_COLON_TOKEN: + if not state.has() or state.peek() != cttColon: return none(CSSDeclaration) discard state.consume() - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() while state.has(): @@ -617,13 +623,13 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = var k = 0 var l = 0 while i >= 0 and j > 0: - if decl.value[i] != CSS_WHITESPACE_TOKEN: + if decl.value[i] != cttWhitespace: dec j - if decl.value[i] == CSS_IDENT_TOKEN and k == 0: + if decl.value[i] == cttIdent and k == 0: if CSSToken(decl.value[i]).value.equalsIgnoreCase("important"): inc k l = i - elif k == 1 and decl.value[i] == CSS_DELIM_TOKEN: + elif k == 1 and decl.value[i] == cttDelim: if CSSToken(decl.value[i]).cvalue == '!': decl.important = true decl.value.delete(l) @@ -631,7 +637,7 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = break dec i - while decl.value.len > 0 and decl.value[^1] == CSS_WHITESPACE_TOKEN: + while decl.value.len > 0 and decl.value[^1] == cttWhitespace: decl.value.setLen(decl.value.len - 1) return some(decl) @@ -643,15 +649,15 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = proc consumeListOfDeclarations(state: var CSSParseState): seq[CSSParsedItem] = while state.has(): let t = state.consume() - if t == CSS_WHITESPACE_TOKEN or t == CSS_SEMICOLON_TOKEN: + if t == cttWhitespace or t == cttSemicolon: continue - elif t == CSS_AT_KEYWORD_TOKEN: + elif t == cttAtKeyword: state.reconsume() result.add(state.consumeAtRule()) - elif t == CSS_IDENT_TOKEN: + elif t == cttIdent: var tempList: seq[CSSParsedItem] tempList.add(CSSToken(t)) - while state.has() and state.peek() != CSS_SEMICOLON_TOKEN: + while state.has() and state.peek() != cttSemicolon: tempList.add(state.consumeComponentValue()) var tempState = CSSParseState(at: 0, tokens: tempList) @@ -660,22 +666,22 @@ proc consumeListOfDeclarations(state: var CSSParseState): seq[CSSParsedItem] = result.add(decl.get) else: state.reconsume() - if state.peek() != CSS_SEMICOLON_TOKEN: + if state.peek() != cttSemicolon: discard state.consumeComponentValue() proc consumeListOfDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = while state.has(): let t = state.consume() - if t == CSS_WHITESPACE_TOKEN or t == CSS_SEMICOLON_TOKEN: + if t == cttWhitespace or t == cttSemicolon: continue - elif t == CSS_AT_KEYWORD_TOKEN: + elif t == cttAtKeyword: state.reconsume() discard state.consumeAtRule() - elif t == CSS_IDENT_TOKEN: + elif t == cttIdent: var tempList: seq[CSSParsedItem] let tok = CSSToken(t) tempList.add(tok) - while state.has() and state.peek() != CSS_SEMICOLON_TOKEN: + while state.has() and state.peek() != cttSemicolon: tempList.add(state.consumeComponentValue()) var tempState = CSSParseState(at: 0, tokens: tempList) @@ -684,15 +690,16 @@ proc consumeListOfDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = result.add(decl.get) else: state.reconsume() - if state.peek() != CSS_SEMICOLON_TOKEN: + if state.peek() != cttSemicolon: discard state.consumeComponentValue() -proc consumeListOfRules(state: var CSSParseState, topLevel = false): seq[CSSRule] = +proc consumeListOfRules(state: var CSSParseState; topLevel = false): + seq[CSSRule] = while state.at < state.tokens.len: let t = state.consume() - if t == CSS_WHITESPACE_TOKEN: + if t == cttWhitespace: continue - elif t == CSS_CDO_TOKEN or t == CSS_CDC_TOKEN: + elif t == cttCdo or t == cttCdc: if topLevel: continue else: @@ -700,7 +707,7 @@ proc consumeListOfRules(state: var CSSParseState, topLevel = false): seq[CSSRule let q = state.consumeQualifiedRule() if q.isSome: result.add(q.get) - elif t == CSS_AT_KEYWORD_TOKEN: + elif t == cttAtKeyword: state.reconsume() result.add(state.consumeAtRule()) else: @@ -727,13 +734,13 @@ proc parseListOfRules*(cvals: seq[CSSComponentValue]): seq[CSSRule] = return state.parseListOfRules() proc parseRule(state: var CSSParseState): DOMResult[CSSRule] = - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() if not state.has(): return errDOMException("Unexpected EOF", "SyntaxError") var res: CSSRule - if state.peek() == CSS_AT_KEYWORD_TOKEN: + if state.peek() == cttAtKeyword: res = state.consumeAtRule() else: let q = state.consumeQualifiedRule() @@ -742,7 +749,7 @@ proc parseRule(state: var CSSParseState): DOMResult[CSSRule] = else: return errDOMException("No qualified rule found!", "SyntaxError") - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() if state.has(): return errDOMException("EOF not reached", "SyntaxError") @@ -754,10 +761,10 @@ proc parseRule*(inputStream: Stream): DOMResult[CSSRule] = return state.parseRule() proc parseDeclaration(state: var CSSParseState): DOMResult[CSSDeclaration] = - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() - if not state.has() or state.peek() != CSS_IDENT_TOKEN: + if not state.has() or state.peek() != cttIdent: return errDOMException("No ident token found", "SyntaxError") let d = state.consumeDeclaration() @@ -774,7 +781,8 @@ proc parseDeclaration*(inputStream: Stream): DOMResult[CSSDeclaration] = proc parseListOfDeclarations(state: var CSSParseState): seq[CSSParsedItem] = return state.consumeListOfDeclarations() -proc parseListOfDeclarations*(cvals: seq[CSSComponentValue]): seq[CSSParsedItem] = +proc parseListOfDeclarations*(cvals: seq[CSSComponentValue]): + seq[CSSParsedItem] = var state: CSSParseState state.tokens = cast[seq[CSSParsedItem]](cvals) return state.consumeListOfDeclarations() @@ -787,7 +795,8 @@ proc parseListOfDeclarations*(inputStream: Stream): seq[CSSParsedItem] = proc parseListOfDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = return state.consumeListOfDeclarations2() -proc parseListOfDeclarations2*(cvals: seq[CSSComponentValue]): seq[CSSDeclaration] = +proc parseListOfDeclarations2*(cvals: seq[CSSComponentValue]): + seq[CSSDeclaration] = var state: CSSParseState state.tokens = cast[seq[CSSParsedItem]](cvals) return state.consumeListOfDeclarations2() @@ -799,14 +808,14 @@ proc parseListOfDeclarations2*(inputStream: Stream): seq[CSSDeclaration] = proc parseComponentValue(state: var CSSParseState): DOMResult[CSSComponentValue] = - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() if not state.has(): return errDOMException("Unexpected EOF", "SyntaxError") let res = state.consumeComponentValue() - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() if state.has(): return errDOMException("EOF not reached", "SyntaxError") @@ -817,7 +826,8 @@ proc parseComponentValue*(inputStream: Stream): DOMResult[CSSComponentValue] = state.tokens = tokenizeCSS(inputStream) return state.parseComponentValue() -proc parseListOfComponentValues(state: var CSSParseState): seq[CSSComponentValue] = +proc parseListOfComponentValues(state: var CSSParseState): + seq[CSSComponentValue] = while state.has(): result.add(state.consumeComponentValue()) @@ -826,18 +836,19 @@ proc parseListOfComponentValues*(inputStream: Stream): seq[CSSComponentValue] = state.tokens = tokenizeCSS(inputStream) return state.parseListOfComponentValues() -proc parseCommaSeparatedListOfComponentValues(state: var CSSParseState): seq[seq[CSSComponentValue]] = +proc parseCommaSeparatedListOfComponentValues(state: var CSSParseState): + seq[seq[CSSComponentValue]] = if state.has(): result.add(newSeq[CSSComponentValue]()) - while state.has(): let cvl = state.consumeComponentValue() - if cvl != CSS_COMMA_TOKEN: + if cvl != cttComma: result[^1].add(cvl) else: result.add(newSeq[CSSComponentValue]()) -proc parseCommaSeparatedListOfComponentValues*(cvals: seq[CSSComponentValue]): seq[seq[CSSComponentValue]] = +proc parseCommaSeparatedListOfComponentValues*(cvals: seq[CSSComponentValue]): + seq[seq[CSSComponentValue]] = var state: CSSParseState state.tokens = cast[seq[CSSParsedItem]](cvals) return state.parseCommaSeparatedListOfComponentValues() @@ -849,11 +860,11 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = if is_eof: return none(CSSAnB) template skip_whitespace = - while state.has() and state.peek() == CSS_WHITESPACE_TOKEN: + while state.has() and state.peek() == cttWhitespace: discard state.consume() template get_plus: bool = let tok = state.peek() - if tok == CSS_DELIM_TOKEN and CSSToken(tok).cvalue == '+': + if tok == cttDelim and CSSToken(tok).cvalue == '+': discard state.consume() true else: @@ -868,23 +879,23 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = template fail_plus = if is_plus: return none(CSSAnB) - template parse_sub_int(sub: string, skip: int): int = + template parse_sub_int(sub: string; skip: int): int = let s = sub.substr(skip) let x = parseInt32(s) if x.isNone: return none(CSSAnB) x.get - template fail_non_integer(tok: CSSToken, res: Option[CSSAnB]) = - if tok.tokenType != CSS_NUMBER_TOKEN: + template fail_non_integer(tok: CSSToken; res: Option[CSSAnB]) = + if tok.tokenType != cttNumber: state.reconsume() return res - if tok.tflagb != TFLAGB_INTEGER: + if tok.tflagb != tflagbInteger: state.reconsume() return res if int64(tok.nvalue) > high(int): state.reconsume() return res - template fail_non_signless_integer(tok: CSSToken, res: Option[CSSAnB]) = + template fail_non_signless_integer(tok: CSSToken; res: Option[CSSAnB]) = fail_non_integer tok, res #TODO check if signless? fail_eof @@ -893,7 +904,7 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = let is_plus = get_plus let tok = get_tok_nows case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: case tok.value of "odd": fail_plus @@ -906,7 +917,7 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = if is_eof: return some((1, 0)) let tok2 = get_tok_nows - if tok2.tokenType == CSS_DELIM_TOKEN: + if tok2.tokenType == cttDelim: let sign = case tok2.cvalue of '+': 1 of '-': -1 @@ -923,7 +934,7 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = if is_eof: return some((-1, 0)) let tok2 = get_tok_nows - if tok2.tokenType == CSS_DELIM_TOKEN: + if tok2.tokenType == cttDelim: let sign = case tok2.cvalue of '+': 1 of '-': -1 @@ -950,19 +961,19 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = return some((-1, -parse_sub_int(tok.value, "n-".len))) else: return none(CSSAnB) - of CSS_NUMBER_TOKEN: + of cttNumber: fail_plus - if tok.tflagb != TFLAGB_INTEGER: + if tok.tflagb != tflagbInteger: return none(CSSAnB) if int64(tok.nvalue) > high(int): return none(CSSAnB) # <integer> return some((0, int(tok.nvalue))) - of CSS_DIMENSION_TOKEN: + of cttDimension: fail_plus if int64(tok.nvalue) > high(int): return none(CSSAnB) - if tok.tflagb != TFLAGB_INTEGER: + if tok.tflagb != tflagbInteger: return none(CSSAnB) case tok.unit of "n", "N": @@ -971,7 +982,7 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = if is_eof: return some((int(tok.nvalue), 0)) let tok2 = get_tok_nows - if tok2.tokenType == CSS_DELIM_TOKEN: + if tok2.tokenType == cttDelim: let sign = case tok2.cvalue of '+': 1 of '-': -1 diff --git a/src/css/match.nim b/src/css/match.nim index d3e7f526..4f8fc05c 100644 --- a/src/css/match.nim +++ b/src/css/match.nim @@ -12,76 +12,84 @@ import utils/twtstr import chame/tags -#TODO FLAG_NONE should match insensitively for certain properties -func attrSelectorMatches(elem: Element, sel: Selector): bool = +#TODO rfNone should match insensitively for certain properties +func attrSelectorMatches(elem: Element; sel: Selector): bool = case sel.rel.t - of RELATION_EXISTS: return elem.attrb(sel.attr) - of RELATION_EQUALS: + of rtExists: return elem.attrb(sel.attr) + of rtEquals: case sel.rel.flag - of FLAG_NONE: return elem.attr(sel.attr) == sel.value - of FLAG_I: return elem.attr(sel.attr).equalsIgnoreCase(sel.value) - of FLAG_S: return elem.attr(sel.attr) == sel.value - of RELATION_TOKEN: + of rfNone: return elem.attr(sel.attr) == sel.value + of rfI: return elem.attr(sel.attr).equalsIgnoreCase(sel.value) + of rfS: return elem.attr(sel.attr) == sel.value + of rtToken: let val = elem.attr(sel.attr) case sel.rel.flag - of FLAG_NONE: return sel.value in val.split(AsciiWhitespace) - of FLAG_I: + of rfNone: return sel.value in val.split(AsciiWhitespace) + of rfI: let val = val.toLowerAscii() let selval = sel.value.toLowerAscii() return selval in val.split(AsciiWhitespace) - of FLAG_S: return sel.value in val.split(AsciiWhitespace) - of RELATION_BEGIN_DASH: + of rfS: return sel.value in val.split(AsciiWhitespace) + of rtBeginDash: let val = elem.attr(sel.attr) case sel.rel.flag - of FLAG_NONE: return val == sel.value or sel.value.startsWith(val & '-') - of FLAG_I: + of rfNone: + return val == sel.value or sel.value.startsWith(val & '-') + of rfI: return val.equalsIgnoreCase(sel.value) or sel.value.startsWithIgnoreCase(val & '-') - of FLAG_S: return val == sel.value or sel.value.startsWith(val & '-') - of RELATION_STARTS_WITH: + of rfS: + return val == sel.value or sel.value.startsWith(val & '-') + of rtStartsWith: let val = elem.attr(sel.attr) case sel.rel.flag - of FLAG_NONE: return val.startsWith(sel.value) - of FLAG_I: return val.startsWithIgnoreCase(sel.value) - of FLAG_S: return val.startsWith(sel.value) - of RELATION_ENDS_WITH: + of rfNone: return val.startsWith(sel.value) + of rfI: return val.startsWithIgnoreCase(sel.value) + of rfS: return val.startsWith(sel.value) + of rtEndsWith: let val = elem.attr(sel.attr) case sel.rel.flag - of FLAG_NONE: return val.endsWith(sel.value) - of FLAG_I: return val.endsWithIgnoreCase(sel.value) - of FLAG_S: return val.endsWith(sel.value) - of RELATION_CONTAINS: + of rfNone: return val.endsWith(sel.value) + of rfI: return val.endsWithIgnoreCase(sel.value) + of rfS: return val.endsWith(sel.value) + of rtContains: let val = elem.attr(sel.attr) case sel.rel.flag - of FLAG_NONE: return val.contains(sel.value) - of FLAG_I: + of rfNone: return val.contains(sel.value) + of rfI: let val = val.toLowerAscii() let selval = sel.value.toLowerAscii() return val.contains(selval) - of FLAG_S: return val.contains(sel.value) + of rfS: return val.contains(sel.value) -func selectorsMatch*[T: Element|StyledNode](elem: T, cxsel: ComplexSelector, felem: T = nil): bool +func selectorsMatch*[T: Element|StyledNode](elem: T; cxsel: ComplexSelector; + felem: T = nil): bool -func selectorsMatch*[T: Element|StyledNode](elem: T, slist: SelectorList, felem: T = nil): bool = +func selectorsMatch*[T: Element|StyledNode](elem: T; slist: SelectorList; + felem: T = nil): bool = for cxsel in slist: if elem.selectorsMatch(cxsel, felem): return true return false -func pseudoSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T): bool = +func pseudoSelectorMatches[T: Element|StyledNode](elem: T; sel: Selector; + felem: T): bool = let selem = elem when elem is StyledNode: let elem = Element(elem.node) case sel.pseudo.t - of PSEUDO_FIRST_CHILD: return elem.parentNode.firstElementChild == elem - of PSEUDO_LAST_CHILD: return elem.parentNode.lastElementChild == elem - of PSEUDO_ONLY_CHILD: return elem.parentNode.firstElementChild == elem and elem.parentNode.lastElementChild == elem - of PSEUDO_HOVER: - when selem is StyledNode: felem.addDependency(selem, DEPEND_HOVER) + of pcFirstChild: return elem.parentNode.firstElementChild == elem + of pcLastChild: return elem.parentNode.lastElementChild == elem + of pcOnlyChild: + return elem.parentNode.firstElementChild == elem and + elem.parentNode.lastElementChild == elem + of pcHover: + when selem is StyledNode: felem.addDependency(selem, dtHover) return elem.hover - of PSEUDO_ROOT: return elem == elem.document.html - of PSEUDO_NTH_CHILD: - if sel.pseudo.ofsels.len != 0 and not selem.selectorsMatch(sel.pseudo.ofsels, felem): + of pcRoot: return elem == elem.document.html + of pcNthChild: + if sel.pseudo.ofsels.len != 0 and + not selem.selectorsMatch(sel.pseudo.ofsels, felem): return false let A = sel.pseudo.anb.A # step let B = sel.pseudo.anb.B # start @@ -98,11 +106,13 @@ func pseudoSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: if A < 0: return (i - B) <= 0 and (i - B) mod A == 0 return (i - B) >= 0 and (i - B) mod A == 0 - if sel.pseudo.ofsels.len == 0 or child.selectorsMatch(sel.pseudo.ofsels, felem): + if sel.pseudo.ofsels.len == 0 or + child.selectorsMatch(sel.pseudo.ofsels, felem): inc i return false - of PSEUDO_NTH_LAST_CHILD: - if sel.pseudo.ofsels.len == 0 and not selem.selectorsMatch(sel.pseudo.ofsels, felem): + of pcNthLastChild: + if sel.pseudo.ofsels.len == 0 and + not selem.selectorsMatch(sel.pseudo.ofsels, felem): return false let A = sel.pseudo.anb.A # step let B = sel.pseudo.anb.B # start @@ -119,57 +129,61 @@ func pseudoSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: if A < 0: return (i - B) <= 0 and (i - B) mod A == 0 return (i - B) >= 0 and (i - B) mod A == 0 - if sel.pseudo.ofsels.len != 0 or child.selectorsMatch(sel.pseudo.ofsels, felem): + if sel.pseudo.ofsels.len != 0 or + child.selectorsMatch(sel.pseudo.ofsels, felem): inc i return false - of PSEUDO_CHECKED: - when selem is StyledNode: felem.addDependency(selem, DEPEND_CHECKED) + of pcChecked: + when selem is StyledNode: felem.addDependency(selem, dtChecked) if elem.tagType == TAG_INPUT: return HTMLInputElement(elem).checked elif elem.tagType == TAG_OPTION: return HTMLOptionElement(elem).selected return false - of PSEUDO_FOCUS: - when selem is StyledNode: felem.addDependency(selem, DEPEND_FOCUS) + of pcFocus: + when selem is StyledNode: felem.addDependency(selem, dtFocus) return elem.document.focus == elem - of PSEUDO_NOT: + of pcNot: return not selem.selectorsMatch(sel.pseudo.fsels, felem) - of PSEUDO_IS, PSEUDO_WHERE: + of pcIs, pcWhere: return selem.selectorsMatch(sel.pseudo.fsels, felem) - of PSEUDO_LANG: + of pcLang: return sel.pseudo.s == "en" #TODO languages? - of PSEUDO_LINK: + of pcLink: return elem.tagType in {TAG_A, TAG_AREA} and elem.attrb(satHref) - of PSEUDO_VISITED: + of pcVisited: return false -func selectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T = nil): bool = +func selectorMatches[T: Element|StyledNode](elem: T; sel: Selector; + felem: T = nil): bool = let selem = elem when elem is StyledNode: let elem = Element(selem.node) case sel.t - of TYPE_SELECTOR: + of stType: return elem.localName == sel.tag - of CLASS_SELECTOR: + of stClass: return sel.class in elem.classList - of ID_SELECTOR: + of stId: return sel.id == elem.id - of ATTR_SELECTOR: + of stAttr: return elem.attrSelectorMatches(sel) - of PSEUDO_SELECTOR: + of stPseudoClass: return pseudoSelectorMatches(selem, sel, felem) - of PSELEM_SELECTOR: + of stPseudoElement: return true - of UNIVERSAL_SELECTOR: + of stUniversal: return true -func selectorsMatch[T: Element|StyledNode](elem: T, sels: CompoundSelector, felem: T): bool = +func selectorsMatch[T: Element|StyledNode](elem: T; sels: CompoundSelector; + felem: T): bool = for sel in sels: if not selectorMatches(elem, sel, felem): return false return true -func complexSelectorMatches[T: Element|StyledNode](elem: T, cxsel: ComplexSelector, felem: T = nil): bool = +func complexSelectorMatches[T: Element|StyledNode](elem: T; + cxsel: ComplexSelector; felem: T = nil): bool = var e = elem for i in countdown(cxsel.high, 0): let sels = cxsel[i] @@ -177,20 +191,20 @@ func complexSelectorMatches[T: Element|StyledNode](elem: T, cxsel: ComplexSelect return false var match = false case sels.ct - of NO_COMBINATOR: + of ctNone: match = e.selectorsMatch(sels, felem) - of DESCENDANT_COMBINATOR: + of ctDescendant: e = e.parentElement while e != nil: if e.selectorsMatch(sels, felem): match = true break e = e.parentElement - of CHILD_COMBINATOR: + of ctChild: e = e.parentElement if e != nil: match = e.selectorsMatch(sels, felem) - of NEXT_SIBLING_COMBINATOR: + of ctNextSibling: if e.parentElement == nil: return false var found = false for child in e.parentElement.elementList_rev: @@ -203,7 +217,7 @@ func complexSelectorMatches[T: Element|StyledNode](elem: T, cxsel: ComplexSelect e = child match = e.selectorsMatch(sels, felem) break - of SUBSEQ_SIBLING_COMBINATOR: + of ctSubsequentSibling: var found = false if e.parentElement == nil: return false for child in e.parentElement.elementList_rev: @@ -223,21 +237,22 @@ func complexSelectorMatches[T: Element|StyledNode](elem: T, cxsel: ComplexSelect # WARNING for StyledNode, this has the side effect of modifying depends. #TODO make that an explicit flag or something, also get rid of the Element case -func selectorsMatch*[T: Element|StyledNode](elem: T, cxsel: ComplexSelector, felem: T = nil): bool = +func selectorsMatch*[T: Element|StyledNode](elem: T; cxsel: ComplexSelector; + felem: T = nil): bool = var felem = if felem != nil: felem else: elem return elem.complexSelectorMatches(cxsel, felem) -proc querySelectorAll(node: Node, q: string): seq[Element] = +proc querySelectorAll(node: Node; q: string): seq[Element] = let selectors = parseSelectors(newStringStream(q), node.document.factory) for element in node.elements: if element.selectorsMatch(selectors): result.add(element) doqsa = (proc(node: Node, q: string): seq[Element] = querySelectorAll(node, q)) -proc querySelector(node: Node, q: string): Element = +proc querySelector(node: Node; q: string): Element = let selectors = parseSelectors(newStringStream(q), node.document.factory) for element in node.elements: if element.selectorsMatch(selectors): diff --git a/src/css/mediaquery.nim b/src/css/mediaquery.nim index 5d092355..b0e95e28 100644 --- a/src/css/mediaquery.nim +++ b/src/css/mediaquery.nim @@ -12,65 +12,64 @@ type cvals: seq[CSSComponentValue] MediaType* = enum - MEDIA_TYPE_UNKNOWN = "unknown" - MEDIA_TYPE_ALL = "all" - MEDIA_TYPE_PRINT = "print" - MEDIA_TYPE_SCREEN = "screen" - MEDIA_TYPE_SPEECH = "speech" - MEDIA_TYPE_TTY = "tty" + mtUnknown = "unknown" + mtAll = "all" + mtPrint = "print" + mtScreen = "screen" + mtSpeech = "speech" + mtTty = "tty" MediaConditionType* = enum - CONDITION_NOT, CONDITION_AND, CONDITION_OR, CONDITION_FEATURE, - CONDITION_MEDIA + mctNot, mctAnd, mctOr, mctFeature, mctMedia MediaFeatureType* = enum - FEATURE_COLOR, FEATURE_GRID, FEATURE_HOVER, FEATURE_PREFERS_COLOR_SCHEME, - FEATURE_WIDTH, FEATURE_HEIGHT, FEATURE_SCRIPTING + mftColor, mftGrid, mftHover, mftPrefersColorScheme, mftWidth, mftHeight, + mftScripting MediaFeature* = object case t*: MediaFeatureType - of FEATURE_COLOR: + of mftColor: range*: Slice[int] - of FEATURE_GRID, FEATURE_HOVER, FEATURE_PREFERS_COLOR_SCHEME, - FEATURE_SCRIPTING: + of mftGrid, mftHover, mftPrefersColorScheme, + mftScripting: b*: bool - of FEATURE_WIDTH, FEATURE_HEIGHT: + of mftWidth, mftHeight: lengthrange*: Slice[CSSLength] lengthaeq*: bool lengthbeq*: bool MediaQuery* = ref object case t*: MediaConditionType - of CONDITION_MEDIA: + of mctMedia: media*: MediaType - of CONDITION_FEATURE: + of mctFeature: feature*: MediaFeature - of CONDITION_NOT: + of mctNot: n*: MediaQuery - of CONDITION_OR: + of mctOr: ora*: MediaQuery orb*: MediaQuery - of CONDITION_AND: + of mctAnd: anda*: MediaQuery andb*: MediaQuery MediaQueryList* = seq[MediaQuery] MediaQueryComparison = enum - COMPARISON_EQ, COMPARISON_GT, COMPARISON_LT, COMPARISON_GE, COMPARISON_LE + mqcEq, mqcGt, mqcLt, mqcGe, mqcLe # for debugging func `$`*(mf: MediaFeature): string = case mf.t - of FEATURE_COLOR: + of mftColor: return "color: " & $mf.range.a & ".." & $mf.range.b - of FEATURE_GRID: + of mftGrid: return "grid: " & $mf.b - of FEATURE_HOVER: + of mftHover: return "hover: " & $mf.b - of FEATURE_PREFERS_COLOR_SCHEME: + of mftPrefersColorScheme: return "prefers-color-scheme: " & $mf.b - of FEATURE_WIDTH: + of mftWidth: result &= $mf.lengthrange.a result &= " <" if mf.lengthaeq: @@ -80,7 +79,7 @@ func `$`*(mf: MediaFeature): string = result &= "=" result &= " " result &= $mf.lengthrange.b - of FEATURE_HEIGHT: + of mftHeight: result &= $mf.lengthrange.a result &= " <" if mf.lengthaeq: @@ -91,28 +90,28 @@ func `$`*(mf: MediaFeature): string = result &= "=" result &= " " result &= $mf.lengthrange.b - of FEATURE_SCRIPTING: + of mftScripting: return "scripting: " & (if mf.b: "enabled" else: "none") func `$`*(mq: MediaQuery): string = case mq.t - of CONDITION_MEDIA: return $mq.media - of CONDITION_FEATURE: return $mq.feature - of CONDITION_NOT: return "not (" & $mq.n - of CONDITION_OR: return "(" & $mq.ora & ") or (" & $mq.orb & ")" - of CONDITION_AND: return "(" & $mq.anda & ") or (" & $mq.andb & ")" + of mctMedia: return $mq.media + of mctFeature: return $mq.feature + of mctNot: return "not (" & $mq.n + of mctOr: return "(" & $mq.ora & ") or (" & $mq.orb & ")" + of mctAnd: return "(" & $mq.anda & ") or (" & $mq.andb & ")" const MediaTypes = { - "all": MEDIA_TYPE_ALL, - "print": MEDIA_TYPE_PRINT, - "screen": MEDIA_TYPE_SCREEN, - "speech": MEDIA_TYPE_SPEECH, - "tty": MEDIA_TYPE_TTY + "all": mtAll, + "print": mtPrint, + "screen": mtScreen, + "speech": mtSpeech, + "tty": mtTty }.toTable() -const RangeFeatures = {FEATURE_COLOR, FEATURE_WIDTH, FEATURE_HEIGHT} +const RangeFeatures = {mftColor, mftWidth, mftHeight} -proc has(parser: MediaQueryParser, i = 0): bool {.inline.} = +proc has(parser: MediaQueryParser; i = 0): bool {.inline.} = return parser.cvals.len > parser.at + i proc consume(parser: var MediaQueryParser): CSSComponentValue {.inline.} = @@ -122,23 +121,23 @@ proc consume(parser: var MediaQueryParser): CSSComponentValue {.inline.} = proc reconsume(parser: var MediaQueryParser) {.inline.} = dec parser.at -proc peek(parser: MediaQueryParser, i = 0): CSSComponentValue {.inline.} = +proc peek(parser: MediaQueryParser; i = 0): CSSComponentValue {.inline.} = return parser.cvals[parser.at + i] proc skipBlanks(parser: var MediaQueryParser) {.inline.} = while parser.has(): let cval = parser.peek() - if cval of CSSToken and CSSToken(cval).tokenType == CSS_WHITESPACE_TOKEN: + if cval of CSSToken and CSSToken(cval).tokenType == cttWhitespace: inc parser.at else: break proc getBoolFeature(feature: MediaFeatureType): MediaQuery = - result = MediaQuery(t: CONDITION_FEATURE) + result = MediaQuery(t: mctFeature) case feature - of FEATURE_GRID, FEATURE_HOVER, FEATURE_PREFERS_COLOR_SCHEME: + of mftGrid, mftHover, mftPrefersColorScheme: result.feature = MediaFeature(t: feature, b: true) - of FEATURE_COLOR: + of mftColor: result.feature = MediaFeature(t: feature, range: 1..high(int)) else: return nil @@ -153,7 +152,7 @@ template get_tok(tok: untyped) = template get_idtok(tok: untyped) = get_tok(tok) - if tok.tokenType != CSS_IDENT_TOKEN: return nil + if tok.tokenType != cttIdent: return nil template consume_token(): CSSToken = let cval = parser.consume() @@ -168,30 +167,30 @@ template expect_int(i: var int) = let cval = parser.consume() if not (cval of CSSToken): return nil let tok = CSSToken(cval) - if tok.tokenType == CSS_NUMBER_TOKEN and tok.tflagb == TFLAGB_INTEGER: + if tok.tokenType == cttNumber and tok.tflagb == tflagbInteger: i = int(tok.nvalue) else: return nil -template expect_mq_int(b: bool, ifalse: int, itrue: int) = +template expect_mq_int(b: bool; ifalse, itrue: int) = var i: int expect_int(i) if i == ifalse: b = false elif i == itrue: b = true else: return nil -template expect_bool(b: bool, sfalse, strue: string) = +template expect_bool(b: bool; sfalse, strue: string) = let tok = consume_token() - if tok.tokenType != CSS_IDENT_TOKEN: return nil + if tok.tokenType != cttIdent: return nil let s = tok.value case s of strue: b = true of sfalse: b = false else: return nil -template expect_bool(b: bool, sfalse, sfalse2, strue: string) = +template expect_bool(b: bool; sfalse, sfalse2, strue: string) = let tok = consume_token() - if tok.tokenType != CSS_IDENT_TOKEN: return nil + if tok.tokenType != cttIdent: return nil let s = tok.value case s of strue: b = true @@ -200,7 +199,7 @@ template expect_bool(b: bool, sfalse, sfalse2, strue: string) = template expect_comparison(comparison: var MediaQueryComparison) = let tok = consume_token() - if tok != CSS_DELIM_TOKEN: return nil + if tok != cttDelim: return nil let c = tok.cvalue if c notin {'=', '<', '>'}: return nil block parse: @@ -208,24 +207,24 @@ template expect_comparison(comparison: var MediaQueryComparison) = of '<': if parser.has(): let tok = skip_consume() - if tok == CSS_DELIM_TOKEN and tok.cvalue == '=': - comparison = COMPARISON_LE + if tok == cttDelim and tok.cvalue == '=': + comparison = mqcLe break parse parser.reconsume() - comparison = COMPARISON_LT + comparison = mqcLt of '>': if parser.has(): let tok = skip_consume() - if tok == CSS_DELIM_TOKEN and tok.cvalue == '=': - comparison = COMPARISON_GE + if tok == cttDelim and tok.cvalue == '=': + comparison = mqcGe break parse parser.reconsume() - comparison = COMPARISON_GT + comparison = mqcGt of '=': - comparison = COMPARISON_EQ + comparison = mqcEq else: return nil -template expect_int_range(range: var Slice[int], ismin, ismax: bool) = +template expect_int_range(range: var Slice[int]; ismin, ismax: bool) = if ismin: expect_int(range.a) elif ismax: @@ -233,23 +232,23 @@ template expect_int_range(range: var Slice[int], ismin, ismax: bool) = else: let tok = consume_token parser.reconsume() - if tok.tokenType == CSS_DELIM_TOKEN: + if tok.tokenType == cttDelim: var comparison: MediaQueryComparison expect_comparison(comparison) if not skip_has: return nil case comparison - of COMPARISON_EQ: + of mqcEq: expect_int(range.a) #TODO should be >= 0 (for color at least) range.b = range.a - of COMPARISON_GT: + of mqcGt: expect_int(range.a) range.b = high(int) - of COMPARISON_GE: + of mqcGe: expect_int(range.a) range.b = high(int) - of COMPARISON_LT: + of mqcLt: expect_int(range.b) - of COMPARISON_LE: + of mqcLe: expect_int(range.b) else: return nil @@ -261,20 +260,20 @@ template expect_length(length: var CSSLength) = return nil length = r.get -template expect_length_range(range: var Slice[CSSLength], lengthaeq, lengthbeq: - var bool, ismin, ismax: bool) = +template expect_length_range(range: var Slice[CSSLength]; + lengthaeq, lengthbeq: var bool; ismin, ismax: bool) = if ismin: expect_length(range.a) - range.b = CSSLength(num: Inf, unit: UNIT_PX) + range.b = CSSLength(num: Inf, unit: cuPx) lengthaeq = true elif ismax: - range.a = CSSLength(num: 0, unit: UNIT_PX) + range.a = CSSLength(num: 0, unit: cuPx) expect_length(range.b) lengthbeq = true else: let tok = consume_token parser.reconsume() - if tok.tokenType == CSS_DELIM_TOKEN: + if tok.tokenType == cttDelim: var comparison: MediaQueryComparison expect_comparison(comparison) if not skip_has: return nil @@ -282,57 +281,57 @@ template expect_length_range(range: var Slice[CSSLength], lengthaeq, lengthbeq: if not skip_has: return nil expect_length(range.b) case comparison - of COMPARISON_EQ: + of mqcEq: expect_length(range.a) range.b = range.a lengthaeq = true lengthbeq = true - of COMPARISON_GT: + of mqcGt: expect_length(range.a) - range.b = CSSLength(num: Inf, unit: UNIT_PX) - of COMPARISON_GE: + range.b = CSSLength(num: Inf, unit: cuPx) + of mqcGe: expect_length(range.a) - range.b = CSSLength(num: Inf, unit: UNIT_PX) + range.b = CSSLength(num: Inf, unit: cuPx) lengthaeq = true - of COMPARISON_LT: - range.a = CSSLength(num: 0, unit: UNIT_PX) + of mqcLt: + range.a = CSSLength(num: 0, unit: cuPx) expect_length(range.b) - of COMPARISON_LE: - range.a = CSSLength(num: 0, unit: UNIT_PX) + of mqcLe: + range.a = CSSLength(num: 0, unit: cuPx) expect_length(range.b) lengthbeq = true else: return nil -proc parseFeature(parser: var MediaQueryParser, t: MediaFeatureType, +proc parseFeature(parser: var MediaQueryParser; t: MediaFeatureType; ismin, ismax: bool): MediaQuery = if not parser.has(): return getBoolFeature(t) let cval = parser.consume() var tok: CSSToken get_tok(tok) - if tok.tokenType != CSS_COLON_TOKEN: return nil + if tok.tokenType != cttColon: return nil parser.skipBlanks() if (ismin or ismax) and t notin RangeFeatures: return nil if not parser.has(): return nil let feature = case t - of FEATURE_GRID: + of mftGrid: var b: bool expect_mq_int(b, 0, 1) MediaFeature(t: t, b: b) - of FEATURE_HOVER: + of mftHover: var b: bool expect_bool(b, "none", "hover") MediaFeature(t: t, b: b) - of FEATURE_PREFERS_COLOR_SCHEME: + of mftPrefersColorScheme: var b: bool expect_bool(b, "light", "dark") MediaFeature(t: t, b: b) - of FEATURE_COLOR: + of mftColor: var range: Slice[int] expect_int_range(range, ismin, ismax) MediaFeature(t: t, range: range) - of FEATURE_WIDTH, FEATURE_HEIGHT: + of mftWidth, mftHeight: var range: Slice[CSSLength] var lengthaeq: bool var lengthbeq: bool @@ -343,7 +342,7 @@ proc parseFeature(parser: var MediaQueryParser, t: MediaFeatureType, lengthaeq: lengthaeq, lengthbeq: lengthbeq ) - of FEATURE_SCRIPTING: + of mftScripting: if ismin or ismax: return nil var b: bool @@ -352,9 +351,10 @@ proc parseFeature(parser: var MediaQueryParser, t: MediaFeatureType, parser.skipBlanks() if parser.has(): return nil - return MediaQuery(t: CONDITION_FEATURE, feature: feature) + return MediaQuery(t: mctFeature, feature: feature) -proc parseMediaCondition(parser: var MediaQueryParser, non = false, noor = false): MediaQuery +proc parseMediaCondition(parser: var MediaQueryParser; non = false; + noor = false): MediaQuery proc parseMediaInParens(parser: var MediaQueryParser): MediaQuery = var fparser: MediaQueryParser @@ -363,7 +363,7 @@ proc parseMediaInParens(parser: var MediaQueryParser): MediaQuery = if not (cval of CSSSimpleBlock): return nil let sb = CSSSimpleBlock(cval) - if sb.token.tokenType != CSS_LPAREN_TOKEN: return nil + if sb.token.tokenType != cttLparen: return nil fparser.cvals = sb.value fparser.skipBlanks() @@ -373,7 +373,7 @@ proc parseMediaInParens(parser: var MediaQueryParser): MediaQuery = var tok: CSSToken get_tok(tok) fparser.skipBlanks() - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: var tokval = tok.value let ismin = tokval.startsWith("min-") let ismax = tokval.startsWith("max-") @@ -383,37 +383,38 @@ proc parseMediaInParens(parser: var MediaQueryParser): MediaQuery = of "not": return fparser.parseMediaCondition(true) of "color": - return fparser.parseFeature(FEATURE_COLOR, ismin, ismax) + return fparser.parseFeature(mftColor, ismin, ismax) of "width": - return fparser.parseFeature(FEATURE_WIDTH, ismin, ismax) + return fparser.parseFeature(mftWidth, ismin, ismax) of "grid": - return fparser.parseFeature(FEATURE_GRID, ismin, ismax) + return fparser.parseFeature(mftGrid, ismin, ismax) of "hover": - return fparser.parseFeature(FEATURE_HOVER, ismin, ismax) + return fparser.parseFeature(mftHover, ismin, ismax) of "prefers-color-scheme": - return fparser.parseFeature(FEATURE_PREFERS_COLOR_SCHEME, ismin, ismax) + return fparser.parseFeature(mftPrefersColorScheme, ismin, ismax) of "scripting": - return fparser.parseFeature(FEATURE_SCRIPTING, ismin, ismax) + return fparser.parseFeature(mftScripting, ismin, ismax) else: discard return nil -proc parseMediaOr(parser: var MediaQueryParser, left: MediaQuery): MediaQuery = +proc parseMediaOr(parser: var MediaQueryParser; left: MediaQuery): MediaQuery = let right = parser.parseMediaCondition() if right != nil: - return MediaQuery(t: CONDITION_OR, ora: left, orb: right) + return MediaQuery(t: mctOr, ora: left, orb: right) return nil -proc parseMediaAnd(parser: var MediaQueryParser, left: MediaQuery): MediaQuery = +proc parseMediaAnd(parser: var MediaQueryParser; left: MediaQuery): MediaQuery = let right = parser.parseMediaCondition() if right != nil: - return MediaQuery(t: CONDITION_AND, anda: left, andb: right) + return MediaQuery(t: mctAnd, anda: left, andb: right) return nil -proc parseMediaCondition(parser: var MediaQueryParser, non = false, noor = false): MediaQuery = +proc parseMediaCondition(parser: var MediaQueryParser; non = false; + noor = false): MediaQuery = var non = non if not non: let cval = parser.consume() - if cval of CSSToken and CSSToken(cval).tokenType == CSS_IDENT_TOKEN: + if cval of CSSToken and CSSToken(cval).tokenType == cttIdent: if CSSToken(cval).value == "not": non = true else: @@ -429,7 +430,7 @@ proc parseMediaCondition(parser: var MediaQueryParser, non = false, noor = false return nil if non: - result = MediaQuery(t: CONDITION_NOT, n: result) + result = MediaQuery(t: mctNot, n: result) parser.skipBlanks() if not parser.has(): @@ -458,7 +459,7 @@ proc parseMediaQuery(parser: var MediaQueryParser): MediaQuery = let cval = parser.consume() if cval of CSSToken: let tok = CSSToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: let tokval = tok.value case tokval of "not": @@ -466,7 +467,7 @@ proc parseMediaQuery(parser: var MediaQueryParser): MediaQuery = of "only": discard elif tokval in MediaTypes: - result = MediaQuery(t: CONDITION_MEDIA, media: MediaTypes[tokval]) + result = MediaQuery(t: mctMedia, media: MediaTypes[tokval]) else: return nil else: @@ -474,22 +475,20 @@ proc parseMediaQuery(parser: var MediaQueryParser): MediaQuery = else: parser.reconsume() return parser.parseMediaCondition() - parser.skipBlanks() if not parser.has(): return result - block: let cval = parser.consume() if cval of CSSToken: let tok = CSSToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: let tokval = tok.value if result == nil: if tokval in MediaTypes: - let mq = MediaQuery(t: CONDITION_MEDIA, media: MediaTypes[tokval]) + let mq = MediaQuery(t: mctMedia, media: MediaTypes[tokval]) if non: - result = MediaQuery(t: CONDITION_NOT, n: mq) + result = MediaQuery(t: mctNot, n: mq) else: result = mq else: @@ -505,26 +504,18 @@ proc parseMediaQuery(parser: var MediaQueryParser): MediaQuery = else: parser.reconsume() return parser.parseMediaCondition(non) - parser.skipBlanks() if not parser.has(): return result - block: let cval = parser.consume() if cval of CSSToken: let tok = CSSToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: - let tokval = tok.value - if tokval != "and": - return nil - else: + if tok.tokenType != cttIdent or tok.value != "and": return nil - parser.skipBlanks() if not parser.has(): return nil - parser.reconsume() return parser.parseMediaAnd(result) diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim index da74c6ed..5e466ab3 100644 --- a/src/css/selectorparser.nim +++ b/src/css/selectorparser.nim @@ -8,24 +8,20 @@ import utils/twtstr type SelectorType* = enum - TYPE_SELECTOR, ID_SELECTOR, ATTR_SELECTOR, CLASS_SELECTOR, - UNIVERSAL_SELECTOR, PSEUDO_SELECTOR, PSELEM_SELECTOR + stType, stId, stAttr, stClass, stUniversal, stPseudoClass, stPseudoElement PseudoElem* = enum - PSEUDO_NONE, PSEUDO_BEFORE, PSEUDO_AFTER, + peNone, peBefore, peAfter, # internal - PSEUDO_INPUT_TEXT, PSEUDO_TEXTAREA_TEXT, PSEUDO_IMAGE, PSEUDO_NEWLINE, - PSEUDO_VIDEO, PSEUDO_AUDIO + peInputText, peTextareaText, peImage, peNewline, peVideo, peAudio PseudoClass* = enum - PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER, - PSEUDO_ROOT, PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD, PSEUDO_CHECKED, - PSEUDO_FOCUS, PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE, PSEUDO_LANG, - PSEUDO_LINK, PSEUDO_VISITED + pcFirstChild, pcLastChild, pcOnlyChild, pcHover, pcRoot, pcNthChild, + pcNthLastChild, pcChecked, pcFocus, pcIs, pcNot, pcWhere, pcLang, pcLink, + pcVisited CombinatorType* = enum - NO_COMBINATOR, DESCENDANT_COMBINATOR, CHILD_COMBINATOR, - NEXT_SIBLING_COMBINATOR, SUBSEQ_SIBLING_COMBINATOR + ctNone, ctDescendant, ctChild, ctNextSibling, ctSubsequentSibling SelectorParser = object selectors: seq[ComplexSelector] @@ -35,11 +31,11 @@ type factory: CAtomFactory RelationType* {.size: sizeof(int) div 2.} = enum - RELATION_EXISTS, RELATION_EQUALS, RELATION_TOKEN, RELATION_BEGIN_DASH, - RELATION_STARTS_WITH, RELATION_ENDS_WITH, RELATION_CONTAINS + rtExists, rtEquals, rtToken, rtBeginDash, + rtStartsWith, rtEndsWith, rtContains RelationFlag* {.size: sizeof(int) div 2.} = enum - FLAG_NONE, FLAG_I, FLAG_S + rfNone, rfI, rfS SelectorRelation* = object t*: RelationType @@ -47,39 +43,39 @@ type Selector* = ref object # Simple selector case t*: SelectorType - of TYPE_SELECTOR: + of stType: tag*: CAtom when defined(debug): tags: string - of ID_SELECTOR: + of stId: id*: CAtom when defined(debug): ids: string - of CLASS_SELECTOR: + of stClass: class*: CAtom when defined(debug): classs: string - of ATTR_SELECTOR: + of stAttr: attr*: CAtom when defined(debug): attrs: string value*: string rel*: SelectorRelation - of UNIVERSAL_SELECTOR: #TODO namespaces? + of stUniversal: #TODO namespaces? discard - of PSEUDO_SELECTOR: + of stPseudoClass: pseudo*: PseudoData - of PSELEM_SELECTOR: + of stPseudoElement: elem*: PseudoElem PseudoData* = object case t*: PseudoClass - of PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD: + of pcNthChild, pcNthLastChild: anb*: CSSAnB ofsels*: SelectorList - of PSEUDO_IS, PSEUDO_WHERE, PSEUDO_NOT: + of pcIs, pcWhere, pcNot: fsels*: SelectorList - of PSEUDO_LANG: + of pcLang: s*: string else: discard @@ -95,16 +91,16 @@ iterator items*(sels: CompoundSelector): Selector {.inline.} = for it in sels.sels: yield it -func `[]`*(sels: CompoundSelector, i: int): Selector {.inline.} = +func `[]`*(sels: CompoundSelector; i: int): Selector {.inline.} = return sels.sels[i] -func `[]`*(sels: CompoundSelector, i: BackwardsIndex): Selector {.inline.} = +func `[]`*(sels: CompoundSelector; i: BackwardsIndex): Selector {.inline.} = return sels.sels[i] func len*(sels: CompoundSelector): int {.inline.} = return sels.sels.len -proc add*(sels: var CompoundSelector, sel: Selector) {.inline.} = +proc add*(sels: var CompoundSelector; sel: Selector) {.inline.} = sels.sels.add(sel) # For debugging @@ -115,52 +111,52 @@ func `$`*(cxsel: ComplexSelector): string func `$`*(sel: Selector): string = case sel.t - of TYPE_SELECTOR: + of stType: when defined(debug): return sel.tags else: return "ATOM" & $int(sel.tag) - of ID_SELECTOR: + of stId: when defined(debug): return "#" & sel.ids else: return "#ATOM" & $int(sel.id) - of ATTR_SELECTOR: + of stAttr: let rel = case sel.rel.t - of RELATION_EXISTS: "" - of RELATION_EQUALS: "=" - of RELATION_TOKEN: "~=" - of RELATION_BEGIN_DASH: "|=" - of RELATION_STARTS_WITH: "^=" - of RELATION_ENDS_WITH: "$=" - of RELATION_CONTAINS: "*=" + of rtExists: "" + of rtEquals: "=" + of rtToken: "~=" + of rtBeginDash: "|=" + of rtStartsWith: "^=" + of rtEndsWith: "$=" + of rtContains: "*=" let flag = case sel.rel.flag - of FLAG_NONE: "" - of FLAG_I: " i" - of FLAG_S: " s" + of rfNone: "" + of rfI: " i" + of rfS: " s" let attrs = when defined(debug): sel.attrs else: "ATOM" & $int(sel.attr) return '[' & attrs & rel & sel.value & flag & ']' - of CLASS_SELECTOR: + of stClass: when defined(debug): return "." & sel.classs else: return ".ATOM" & $int(sel.id) - of UNIVERSAL_SELECTOR: + of stUniversal: return "*" - of PSEUDO_SELECTOR: + of stPseudoClass: result = ':' & sel.pseudo.t.tostr() case sel.pseudo.t - of PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE: + of pcIs, pcNot, pcWhere: result &= '(' for fsel in sel.pseudo.fsels: result &= $fsel if fsel != sel.pseudo.fsels[^1]: result &= ", " result &= ')' - of PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD: + of pcNthChild, pcNthLastChild: result &= '(' & $sel.pseudo.anb.A & 'n' & $sel.pseudo.anb.B if sel.pseudo.ofsels.len != 0: result &= " of " @@ -170,7 +166,7 @@ func `$`*(sel: Selector): string = result &= ',' result &= ')' else: discard - of PSELEM_SELECTOR: + of stPseudoElement: return "::" & sel.elem.tostr() func `$`*(sels: CompoundSelector): string = @@ -181,11 +177,11 @@ func `$`*(cxsel: ComplexSelector): string = for sels in cxsel: result &= $sels case sels.ct - of DESCENDANT_COMBINATOR: result &= ' ' - of CHILD_COMBINATOR: result &= " > " - of NEXT_SIBLING_COMBINATOR: result &= " + " - of SUBSEQ_SIBLING_COMBINATOR: result &= " ~ " - of NO_COMBINATOR: discard + of ctDescendant: result &= ' ' + of ctChild: result &= " > " + of ctNextSibling: result &= " + " + of ctSubsequentSibling: result &= " ~ " + of ctNone: discard func `$`*(slist: SelectorList): string = var s = false @@ -199,20 +195,20 @@ func getSpecificity*(cxsel: ComplexSelector): int func getSpecificity(sel: Selector): int = case sel.t - of ID_SELECTOR: + of stId: result += 1000000 - of CLASS_SELECTOR, ATTR_SELECTOR: + of stClass, stAttr: result += 1000 - of PSEUDO_SELECTOR: + of stPseudoClass: case sel.pseudo.t - of PSEUDO_IS, PSEUDO_NOT: + of pcIs, pcNot: var best = 0 for child in sel.pseudo.fsels: let s = getSpecificity(child) if s > best: best = s result += best - of PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD: + of pcNthChild, pcNthLastChild: if sel.pseudo.ofsels.len != 0: var best = 0 for child in sel.pseudo.ofsels: @@ -221,11 +217,11 @@ func getSpecificity(sel: Selector): int = best = s result += best result += 1000 - of PSEUDO_WHERE: discard + of pcWhere: discard else: result += 1000 - of TYPE_SELECTOR, PSELEM_SELECTOR: + of stType, stPseudoElement: result += 1 - of UNIVERSAL_SELECTOR: + of stUniversal: discard func getSpecificity*(sels: CompoundSelector): int = @@ -237,18 +233,18 @@ func getSpecificity*(cxsel: ComplexSelector): int = result += getSpecificity(sels) func pseudo*(cxsel: ComplexSelector): PseudoElem = - if cxsel[^1][^1].t == PSELEM_SELECTOR: + if cxsel[^1][^1].t == stPseudoElement: return cxsel[^1][^1].elem - return PSEUDO_NONE + return peNone proc consume(state: var SelectorParser): CSSComponentValue = result = state.cvals[state.at] inc state.at -proc has(state: var SelectorParser, i = 0): bool = +proc has(state: var SelectorParser; i = 0): bool = return not state.failed and state.at + i < state.cvals.len -proc peek(state: var SelectorParser, i = 0): CSSComponentValue = +proc peek(state: var SelectorParser; i = 0): CSSComponentValue = return state.cvals[state.at + i] template fail() = @@ -260,40 +256,41 @@ template get_tok(cval: CSSComponentValue): CSSToken = if not (c of CSSToken): fail CSSToken(c) -proc parseSelectorList(cvals: seq[CSSComponentValue], factory: CAtomFactory): +proc parseSelectorList(cvals: seq[CSSComponentValue]; factory: CAtomFactory): SelectorList # Functions that may contain other selectors, functions, etc. -proc parseRecursiveSelectorFunction(state: var SelectorParser, - class: PseudoClass, body: seq[CSSComponentValue]): Selector = +proc parseRecursiveSelectorFunction(state: var SelectorParser; + class: PseudoClass; body: seq[CSSComponentValue]): Selector = var fun = Selector( - t: PSEUDO_SELECTOR, + t: stPseudoClass, pseudo: PseudoData(t: class), ) fun.pseudo.fsels = parseSelectorList(body, state.factory) if fun.pseudo.fsels.len == 0: fail return fun -proc parseNthChild(state: var SelectorParser, cssfunction: CSSFunction, data: PseudoData): Selector = +proc parseNthChild(state: var SelectorParser; cssfunction: CSSFunction; + data: PseudoData): Selector = var data = data var (anb, i) = parseAnB(cssfunction.value) if anb.isNone: fail data.anb = anb.get - var nthchild = Selector(t: PSEUDO_SELECTOR, pseudo: data) - while i < cssfunction.value.len and cssfunction.value[i] == CSS_WHITESPACE_TOKEN: + var nthchild = Selector(t: stPseudoClass, pseudo: data) + while i < cssfunction.value.len and cssfunction.value[i] == cttWhitespace: inc i if i >= cssfunction.value.len: return nthchild if not (get_tok cssfunction.value[i]).value.equalsIgnoreCase("of"): fail if i == cssfunction.value.len: fail - nthchild.pseudo.ofsels = parseSelectorList(cssfunction.value[i..^1], - state.factory) + nthchild.pseudo.ofsels = cssfunction.value[i..^1] + .parseSelectorList(state.factory) if nthchild.pseudo.ofsels.len == 0: fail return nthchild proc skipWhitespace(state: var SelectorParser) = while state.has() and state.peek() of CSSToken and - CSSToken(state.peek()).tokenType == CSS_WHITESPACE_TOKEN: + CSSToken(state.peek()).tokenType == cttWhitespace: inc state.at proc parseLang(cvals: seq[CSSComponentValue]): Selector = @@ -301,21 +298,22 @@ proc parseLang(cvals: seq[CSSComponentValue]): Selector = state.skipWhitespace() if not state.has(): fail let tok = get_tok state.consume() - if tok.tokenType != CSS_IDENT_TOKEN: fail - return Selector(t: PSEUDO_SELECTOR, pseudo: PseudoData(t: PSEUDO_LANG, s: tok.value)) + if tok.tokenType != cttIdent: fail + return Selector(t: stPseudoClass, pseudo: PseudoData(t: pcLang, s: tok.value)) -proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction): Selector = +proc parseSelectorFunction(state: var SelectorParser; cssfunction: CSSFunction): + Selector = return case cssfunction.name.toLowerAscii() of "not": - state.parseRecursiveSelectorFunction(PSEUDO_NOT, cssfunction.value) + state.parseRecursiveSelectorFunction(pcNot, cssfunction.value) of "is": - state.parseRecursiveSelectorFunction(PSEUDO_IS, cssfunction.value) + state.parseRecursiveSelectorFunction(pcIs, cssfunction.value) of "where": - state.parseRecursiveSelectorFunction(PSEUDO_WHERE, cssfunction.value) + state.parseRecursiveSelectorFunction(pcWhere, cssfunction.value) of "nth-child": - state.parseNthChild(cssfunction, PseudoData(t: PSEUDO_NTH_CHILD)) + state.parseNthChild(cssfunction, PseudoData(t: pcNthChild)) of "nth-last-child": - state.parseNthChild(cssfunction, PseudoData(t: PSEUDO_NTH_LAST_CHILD)) + state.parseNthChild(cssfunction, PseudoData(t: pcNthLastChild)) of "lang": parseLang(cssfunction.value) else: fail @@ -325,32 +323,32 @@ proc parsePseudoSelector(state: var SelectorParser): Selector = let cval = state.consume() if cval of CSSToken: template add_pseudo_element(element: PseudoElem) = - return Selector(t: PSELEM_SELECTOR, elem: element) + return Selector(t: stPseudoElement, elem: element) let tok = CSSToken(cval) case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: template add_pseudo_class(class: PseudoClass) = - return Selector(t: PSEUDO_SELECTOR, pseudo: PseudoData(t: class)) + return Selector(t: stPseudoClass, pseudo: PseudoData(t: class)) case tok.value.toLowerAscii() - of "before": add_pseudo_element PSEUDO_BEFORE - of "after": add_pseudo_element PSEUDO_AFTER - of "first-child": add_pseudo_class PSEUDO_FIRST_CHILD - of "last-child": add_pseudo_class PSEUDO_LAST_CHILD - of "only-child": add_pseudo_class PSEUDO_ONLY_CHILD - of "hover": add_pseudo_class PSEUDO_HOVER - of "root": add_pseudo_class PSEUDO_ROOT - of "checked": add_pseudo_class PSEUDO_CHECKED - of "focus": add_pseudo_class PSEUDO_FOCUS - of "link": add_pseudo_class PSEUDO_LINK - of "visited": add_pseudo_class PSEUDO_VISITED + of "before": add_pseudo_element peBefore + of "after": add_pseudo_element peAfter + of "first-child": add_pseudo_class pcFirstChild + of "last-child": add_pseudo_class pcLastChild + of "only-child": add_pseudo_class pcOnlyChild + of "hover": add_pseudo_class pcHover + of "root": add_pseudo_class pcRoot + of "checked": add_pseudo_class pcChecked + of "focus": add_pseudo_class pcFocus + of "link": add_pseudo_class pcLink + of "visited": add_pseudo_class pcVisited else: fail - of CSS_COLON_TOKEN: + of cttColon: if not state.has(): fail let tok = get_tok state.consume() - if tok.tokenType != CSS_IDENT_TOKEN: fail + if tok.tokenType != cttIdent: fail case tok.value.toLowerAscii() - of "before": add_pseudo_element PSEUDO_BEFORE - of "after": add_pseudo_element PSEUDO_AFTER + of "before": add_pseudo_element peBefore + of "after": add_pseudo_element peAfter else: fail else: fail elif cval of CSSFunction: @@ -359,49 +357,49 @@ proc parsePseudoSelector(state: var SelectorParser): Selector = proc parseComplexSelector(state: var SelectorParser): ComplexSelector -proc parseAttributeSelector(state: var SelectorParser, +proc parseAttributeSelector(state: var SelectorParser; cssblock: CSSSimpleBlock): Selector = - if cssblock.token.tokenType != CSS_LBRACKET_TOKEN: fail + if cssblock.token.tokenType != cttLbracket: fail var state2 = SelectorParser(cvals: cssblock.value) state2.skipWhitespace() if not state2.has(): fail let attr = get_tok state2.consume() - if attr.tokenType != CSS_IDENT_TOKEN: fail + if attr.tokenType != cttIdent: fail state2.skipWhitespace() if not state2.has(): return Selector( - t: ATTR_SELECTOR, + t: stAttr, attr: state.factory.toAtom(attr.value), - rel: SelectorRelation(t: RELATION_EXISTS) + rel: SelectorRelation(t: rtExists) ) let delim = get_tok state2.consume() - if delim.tokenType != CSS_DELIM_TOKEN: fail + if delim.tokenType != cttDelim: fail let rel = case delim.cvalue - of '~': RELATION_TOKEN - of '|': RELATION_BEGIN_DASH - of '^': RELATION_STARTS_WITH - of '$': RELATION_ENDS_WITH - of '*': RELATION_CONTAINS - of '=': RELATION_EQUALS + of '~': rtToken + of '|': rtBeginDash + of '^': rtStartsWith + of '$': rtEndsWith + of '*': rtContains + of '=': rtEquals else: fail - if rel != RELATION_EQUALS: + if rel != rtEquals: let delim = get_tok state2.consume() - if delim.tokenType != CSS_DELIM_TOKEN or delim.cvalue != '=': fail + if delim.tokenType != cttDelim or delim.cvalue != '=': fail state2.skipWhitespace() if not state2.has(): fail let value = get_tok state2.consume() - if value.tokenType notin {CSS_IDENT_TOKEN, CSS_STRING_TOKEN}: fail + if value.tokenType notin {cttIdent, cttString}: fail state2.skipWhitespace() - var flag = FLAG_NONE + var flag = rfNone if state2.has(): let delim = get_tok state2.consume() - if delim.tokenType != CSS_IDENT_TOKEN: fail + if delim.tokenType != cttIdent: fail if delim.value.equalsIgnoreCase("i"): - flag = FLAG_I + flag = rfI elif delim.value.equalsIgnoreCase("s"): - flag = FLAG_S + flag = rfS return Selector( - t: ATTR_SELECTOR, + t: stAttr, attr: state.factory.toAtom(attr.value), value: value.value, rel: SelectorRelation( @@ -413,9 +411,9 @@ proc parseAttributeSelector(state: var SelectorParser, proc parseClassSelector(state: var SelectorParser): Selector = if not state.has(): fail let tok = get_tok state.consume() - if tok.tokenType != CSS_IDENT_TOKEN: fail + if tok.tokenType != cttIdent: fail let class = state.factory.toAtom(tok.value) - result = Selector(t: CLASS_SELECTOR, class: class) + result = Selector(t: stClass, class: class) when defined(debug): result.classs = tok.value @@ -426,39 +424,39 @@ proc parseCompoundSelector(state: var SelectorParser): CompoundSelector = if cval of CSSToken: let tok = CSSToken(cval) case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: inc state.at let s = tok.value.toLowerAscii() let tag = state.factory.toAtom(s) - let sel = Selector(t: TYPE_SELECTOR, tag: tag) + let sel = Selector(t: stType, tag: tag) when defined(debug): sel.tags = s result.add(sel) - of CSS_COLON_TOKEN: + of cttColon: inc state.at result.add(state.parsePseudoSelector()) - of CSS_HASH_TOKEN: + of cttHash: inc state.at let id = state.factory.toAtom(tok.value) - result.add(Selector(t: ID_SELECTOR, id: id)) + result.add(Selector(t: stId, id: id)) when defined(debug): result[^1].ids = tok.value - of CSS_COMMA_TOKEN: break - of CSS_DELIM_TOKEN: + of cttComma: break + of cttDelim: case tok.cvalue of '.': inc state.at result.add(state.parseClassSelector()) of '*': inc state.at - result.add(Selector(t: UNIVERSAL_SELECTOR)) + result.add(Selector(t: stUniversal)) of '>', '+', '~': break else: fail - of CSS_WHITESPACE_TOKEN: + of cttWhitespace: # skip trailing whitespace - if not state.has(1) or state.peek(1) == CSS_COMMA_TOKEN: + if not state.has(1) or state.peek(1) == cttComma: inc state.at - elif state.peek(1) == CSS_DELIM_TOKEN: + elif state.peek(1) == cttDelim: let tok = CSSToken(state.peek(1)) if tok.cvalue in {'>', '+', '~'}: inc state.at @@ -480,21 +478,21 @@ proc parseComplexSelector(state: var SelectorParser): ComplexSelector = break # finish let tok = get_tok state.consume() case tok.tokenType - of CSS_DELIM_TOKEN: + of cttDelim: case tok.cvalue - of '>': result[^1].ct = CHILD_COMBINATOR - of '+': result[^1].ct = NEXT_SIBLING_COMBINATOR - of '~': result[^1].ct = SUBSEQ_SIBLING_COMBINATOR + of '>': result[^1].ct = ctChild + of '+': result[^1].ct = ctNextSibling + of '~': result[^1].ct = ctSubsequentSibling else: fail - of CSS_WHITESPACE_TOKEN: - result[^1].ct = DESCENDANT_COMBINATOR - of CSS_COMMA_TOKEN: + of cttWhitespace: + result[^1].ct = ctDescendant + of cttComma: break # finish else: fail - if result.len == 0 or result[^1].ct != NO_COMBINATOR: + if result.len == 0 or result[^1].ct != ctNone: fail -proc parseSelectorList(cvals: seq[CSSComponentValue], factory: CAtomFactory): +proc parseSelectorList(cvals: seq[CSSComponentValue]; factory: CAtomFactory): SelectorList = var state = SelectorParser(cvals: cvals, factory: factory) var res: SelectorList @@ -503,10 +501,10 @@ proc parseSelectorList(cvals: seq[CSSComponentValue], factory: CAtomFactory): if not state.failed: return res -proc parseSelectors*(cvals: seq[CSSComponentValue], factory: CAtomFactory): +proc parseSelectors*(cvals: seq[CSSComponentValue]; factory: CAtomFactory): seq[ComplexSelector] = return parseSelectorList(cvals, factory) -proc parseSelectors*(stream: Stream, factory: CAtomFactory): +proc parseSelectors*(stream: Stream; factory: CAtomFactory): seq[ComplexSelector] = return parseSelectors(parseListOfComponentValues(stream), factory) diff --git a/src/css/sheet.nim b/src/css/sheet.nim index 14d9b717..b00f3bd0 100644 --- a/src/css/sheet.nim +++ b/src/css/sheet.nim @@ -37,7 +37,7 @@ type SelectorHashes = object id: CAtom class: CAtom -func newStylesheet*(cap: int, factory: CAtomFactory): CSSStylesheet = +func newStylesheet*(cap: int; factory: CAtomFactory): CSSStylesheet = let bucketsize = cap div 2 return CSSStylesheet( tagTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize), @@ -47,31 +47,31 @@ func newStylesheet*(cap: int, factory: CAtomFactory): CSSStylesheet = factory: factory ) -proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool +proc getSelectorIds(hashes: var SelectorHashes; sel: Selector): bool -proc getSelectorIds(hashes: var SelectorHashes, sels: CompoundSelector) = +proc getSelectorIds(hashes: var SelectorHashes; sels: CompoundSelector) = for sel in sels: if hashes.getSelectorIds(sel): break -proc getSelectorIds(hashes: var SelectorHashes, cxsel: ComplexSelector) = +proc getSelectorIds(hashes: var SelectorHashes; cxsel: ComplexSelector) = hashes.getSelectorIds(cxsel[^1]) -proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool = +proc getSelectorIds(hashes: var SelectorHashes; sel: Selector): bool = case sel.t - of TYPE_SELECTOR: + of stType: hashes.tag = sel.tag return true - of CLASS_SELECTOR: + of stClass: hashes.class = sel.class return true - of ID_SELECTOR: + of stId: hashes.id = sel.id return true - of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR: + of stAttr, stPseudoElement, stUniversal: return false - of PSEUDO_SELECTOR: - if sel.pseudo.t notin {PSEUDO_IS, PSEUDO_WHERE}: + of stPseudoClass: + if sel.pseudo.t notin {pcIs, pcWhere}: return false # Basically just hash whatever the selectors have in common: #1. get the hashable values of selector 1 @@ -87,7 +87,6 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool = if i < sel.pseudo.fsels.len: hashes.getSelectorIds(sel.pseudo.fsels[i]) inc i - while i < sel.pseudo.fsels.len: var nhashes: SelectorHashes nhashes.getSelectorIds(sel.pseudo.fsels[i]) @@ -96,35 +95,30 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool = elif not cancelTag and nhashes.tag != CAtomNull and nhashes.tag != hashes.tag: cancelTag = true - if hashes.id == CAtomNull: hashes.id = nhashes.id elif not cancelId and nhashes.id != CAtomNull and nhashes.id != hashes.id: cancelId = true - if hashes.class == CAtomNull: hashes.class = nhashes.class elif not cancelClass and nhashes.class != CAtomNull and nhashes.class != hashes.class: cancelClass = true - inc i - if cancelTag: hashes.tag = CAtomNull if cancelId: hashes.id = CAtomNull if cancelClass: hashes.class = CAtomNull - return hashes.tag != CAtomNull or hashes.id != CAtomNull or hashes.class != CAtomNull proc ruleDefCmp(a, b: CSSRuleDef): int = cmp(a.idx, b.idx) -iterator genRules*(sheet: CSSStylesheet, tag, id: CAtom, classes: seq[CAtom]): +iterator genRules*(sheet: CSSStylesheet; tag, id: CAtom; classes: seq[CAtom]): CSSRuleDef = var rules: seq[CSSRuleDef] sheet.tagTable.withValue(tag, v): @@ -144,7 +138,7 @@ iterator genRules*(sheet: CSSStylesheet, tag, id: CAtom, classes: seq[CAtom]): for rule in rules: yield rule -proc add(sheet: var CSSStylesheet, rule: CSSRuleDef) = +proc add(sheet: var CSSStylesheet; rule: CSSRuleDef) = var hashes: SelectorHashes for cxsel in rule.sels: hashes.getSelectorIds(cxsel) @@ -166,7 +160,7 @@ proc add(sheet: var CSSStylesheet, rule: CSSRuleDef) = else: sheet.generalList.add(rule) -proc add*(sheet: var CSSStylesheet, sheet2: CSSStylesheet) = +proc add*(sheet: var CSSStylesheet; sheet2: CSSStylesheet) = sheet.generalList.add(sheet2.generalList) for key, value in sheet2.tagTable.pairs: sheet.tagTable.withValue(key, p): @@ -184,7 +178,7 @@ proc add*(sheet: var CSSStylesheet, sheet2: CSSStylesheet) = do: sheet.classTable[key] = value -proc addRule(stylesheet: var CSSStylesheet, rule: CSSQualifiedRule) = +proc addRule(stylesheet: var CSSStylesheet; rule: CSSQualifiedRule) = let sels = parseSelectors(rule.prelude, stylesheet.factory) if sels.len > 0: let r = CSSRuleDef( @@ -195,7 +189,7 @@ proc addRule(stylesheet: var CSSStylesheet, rule: CSSQualifiedRule) = stylesheet.add(r) inc stylesheet.len -proc addAtRule(stylesheet: var CSSStylesheet, atrule: CSSAtRule) = +proc addAtRule(stylesheet: var CSSStylesheet; atrule: CSSAtRule) = case atrule.name of "media": if atrule.oblock == nil: @@ -217,7 +211,7 @@ proc addAtRule(stylesheet: var CSSStylesheet, atrule: CSSAtRule) = stylesheet.len = media.children.len else: discard #TODO -proc parseStylesheet*(s: Stream, factory: CAtomFactory): CSSStylesheet = +proc parseStylesheet*(s: Stream; factory: CAtomFactory): CSSStylesheet = let css = parseCSS(s) result = newStylesheet(css.value.len, factory) for v in css.value: @@ -225,5 +219,5 @@ proc parseStylesheet*(s: Stream, factory: CAtomFactory): CSSStylesheet = else: result.addRule(CSSQualifiedRule(v)) s.close() -proc parseStylesheet*(s: string, factory: CAtomFactory): CSSStylesheet = +proc parseStylesheet*(s: string; factory: CAtomFactory): CSSStylesheet = return newStringStream(s).parseStylesheet(factory) diff --git a/src/css/stylednode.nim b/src/css/stylednode.nim index 1af03f30..ea6a9265 100644 --- a/src/css/stylednode.nim +++ b/src/css/stylednode.nim @@ -37,10 +37,10 @@ import chame/tags type StyledType* = enum - STYLED_ELEMENT, STYLED_TEXT, STYLED_REPLACEMENT + stElement, stText, stReplacement DependencyType* = enum - DEPEND_HOVER, DEPEND_CHECKED, DEPEND_FOCUS + dtHover, dtChecked, dtFocus DependencyInfo* = object # All nodes we depend on, for each dependency type d. @@ -54,13 +54,13 @@ type node*: Node pseudo*: PseudoElem case t*: StyledType - of STYLED_TEXT: + of stText: text*: string - of STYLED_ELEMENT: + of stElement: computed*: CSSComputedValues children*: seq[StyledNode] depends*: DependencyInfo - of STYLED_REPLACEMENT: + of stReplacement: # replaced elements: quotes, or (TODO) markers, images content*: CSSContent @@ -69,13 +69,13 @@ func `$`*(node: StyledNode): string = if node == nil: return "nil" case node.t - of STYLED_TEXT: + of stText: return "#text " & node.text - of STYLED_ELEMENT: + of stElement: if node.node != nil: return $node.node return $node.pseudo - of STYLED_REPLACEMENT: + of stReplacement: return "#replacement" iterator branch*(node: StyledNode): StyledNode {.inline.} = @@ -95,7 +95,7 @@ iterator elementList_rev*(node: StyledNode): StyledNode {.inline.} = func findElement*(root: StyledNode; elem: Element): StyledNode = var stack: seq[StyledNode] for child in root.elementList_rev: - if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE: + if child.t == stElement and child.pseudo == peNone: stack.add(child) let en = Node(elem) while stack.len > 0: @@ -103,11 +103,11 @@ func findElement*(root: StyledNode; elem: Element): StyledNode = if node.node == en: return node for child in node.elementList_rev: - if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE: + if child.t == stElement and child.pseudo == peNone: stack.add(child) func isDomElement*(styledNode: StyledNode): bool {.inline.} = - styledNode.t == STYLED_ELEMENT and styledNode.pseudo == PSEUDO_NONE + styledNode.t == stElement and styledNode.pseudo == peNone # DOM-style getters, for Element interoperability... func parentElement*(node: StyledNode): StyledNode {.inline.} = @@ -119,9 +119,9 @@ func checked(element: Element): bool = result = input.checked func isValid*(styledNode: StyledNode): bool = - if styledNode.t == STYLED_TEXT: + if styledNode.t == stText: return true - if styledNode.t == STYLED_REPLACEMENT: + if styledNode.t == stReplacement: return true if styledNode.node != nil and Element(styledNode.node).invalid: return false @@ -130,13 +130,13 @@ func isValid*(styledNode: StyledNode): bool = assert child.node != nil let elem = Element(child.node) case d - of DEPEND_HOVER: + of dtHover: if child.depends.prev[d] != elem.hover: return false - of DEPEND_CHECKED: + of dtChecked: if child.depends.prev[d] != elem.checked: return false - of DEPEND_FOCUS: + of dtFocus: let focus = elem.document.focus == elem if child.depends.prev[d] != focus: return false @@ -144,10 +144,10 @@ func isValid*(styledNode: StyledNode): bool = proc applyDependValues*(styledNode: StyledNode) = let elem = Element(styledNode.node) - styledNode.depends.prev[DEPEND_HOVER] = elem.hover - styledNode.depends.prev[DEPEND_CHECKED] = elem.checked + styledNode.depends.prev[dtHover] = elem.hover + styledNode.depends.prev[dtChecked] = elem.checked let focus = elem.document.focus == elem - styledNode.depends.prev[DEPEND_FOCUS] = focus + styledNode.depends.prev[dtFocus] = focus elem.invalid = false proc addDependency*(styledNode, dep: StyledNode; t: DependencyType) = @@ -157,7 +157,7 @@ proc addDependency*(styledNode, dep: StyledNode; t: DependencyType) = func newStyledElement*(parent: StyledNode; element: Element; computed: CSSComputedValues; reg: DependencyInfo): StyledNode = return StyledNode( - t: STYLED_ELEMENT, + t: stElement, computed: computed, node: element, parent: parent, @@ -165,16 +165,16 @@ func newStyledElement*(parent: StyledNode; element: Element; ) func newStyledElement*(parent: StyledNode; element: Element): StyledNode = - return StyledNode(t: STYLED_ELEMENT, node: element, parent: parent) + return StyledNode(t: stElement, node: element, parent: parent) # Root func newStyledElement*(element: Element): StyledNode = - return StyledNode(t: STYLED_ELEMENT, node: element) + return StyledNode(t: stElement, node: element) func newStyledElement*(parent: StyledNode; pseudo: PseudoElem; computed: CSSComputedValues; reg: sink DependencyInfo): StyledNode = return StyledNode( - t: STYLED_ELEMENT, + t: stElement, computed: computed, pseudo: pseudo, parent: parent, @@ -184,17 +184,18 @@ func newStyledElement*(parent: StyledNode; pseudo: PseudoElem; func newStyledElement*(parent: StyledNode; pseudo: PseudoElem; computed: CSSComputedValues): StyledNode = return StyledNode( - t: STYLED_ELEMENT, + t: stElement, computed: computed, pseudo: pseudo, parent: parent ) func newStyledText*(parent: StyledNode; text: string): StyledNode = - return StyledNode(t: STYLED_TEXT, text: text, parent: parent) + return StyledNode(t: stText, text: text, parent: parent) func newStyledText*(parent: StyledNode; text: Text): StyledNode = - return StyledNode(t: STYLED_TEXT, text: text.data, node: text, parent: parent) + return StyledNode(t: stText, text: text.data, node: text, parent: parent) -func newStyledReplacement*(parent: StyledNode; content: CSSContent): StyledNode = - return StyledNode(t: STYLED_REPLACEMENT, parent: parent, content: content) +func newStyledReplacement*(parent: StyledNode; content: CSSContent): + StyledNode = + return StyledNode(t: stReplacement, parent: parent, content: content) diff --git a/src/css/values.nim b/src/css/values.nim index c473cdee..647e3d67 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -27,9 +27,8 @@ type cstFlexFlow = "flex-flow" CSSUnit* = enum - UNIT_CM, UNIT_MM, UNIT_IN, UNIT_PX, UNIT_PT, UNIT_PC, UNIT_EM, UNIT_EX, - UNIT_CH, UNIT_REM, UNIT_VW, UNIT_VH, UNIT_VMIN, UNIT_VMAX, UNIT_PERC, - UNIT_IC + cuCm, cuMm, cuIn, cuPx, cuPt, cuPc, cuEm, cuEx, cuCh, cuRem, cuVw, cuVh, + cuVmin, cuVmax, cuPerc, cuIc CSSPropertyType* = enum cptNone = "" @@ -123,109 +122,91 @@ type cvtNoglobal, cvtInitial, cvtInherit, cvtRevert, cvtUnset CSSDisplay* = enum - DISPLAY_NONE, DISPLAY_INLINE, DISPLAY_BLOCK, DISPLAY_LIST_ITEM, - DISPLAY_INLINE_BLOCK, DISPLAY_TABLE, DISPLAY_INLINE_TABLE, - DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, - DISPLAY_TABLE_FOOTER_GROUP, DISPLAY_TABLE_COLUMN_GROUP, DISPLAY_TABLE_ROW, - DISPLAY_TABLE_COLUMN, DISPLAY_TABLE_CELL, DISPLAY_TABLE_CAPTION, - DISPLAY_FLOW_ROOT, DISPLAY_FLEX, DISPLAY_INLINE_FLEX + DisplayNone, DisplayInline, DisplayBlock, DisplayListItem, + DisplayInlineBlock, DisplayTable, DisplayInlineTable, DisplayTableRowGroup, + DisplayTableHeaderGroup, DisplayTableFooterGroup, DisplayTableColumnGroup, + DisplayTableRow, DisplayTableColumn, DisplayTableCell, DisplayTableCaption, + DisplayFlowRoot, DisplayFlex, DisplayInlineFlex CSSWhitespace* = enum - WHITESPACE_NORMAL, WHITESPACE_NOWRAP, WHITESPACE_PRE, WHITESPACE_PRE_LINE, - WHITESPACE_PRE_WRAP + WhitespaceNormal, WhitespaceNowrap, WhitespacePre, WhitespacePreLine, + WhitespacePreWrap CSSFontStyle* = enum - FONT_STYLE_NORMAL, FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE + FontStyleNormal, FontStyleItalic, FontStyleOblique CSSPosition* = enum - POSITION_STATIC, POSITION_RELATIVE, POSITION_ABSOLUTE, POSITION_FIXED, - POSITION_STICKY + PositionStatic, PositionRelative, PositionAbsolute, PositionFixed, + PositionSticky CSSTextDecoration* = enum - TEXT_DECORATION_NONE, TEXT_DECORATION_UNDERLINE, TEXT_DECORATION_OVERLINE, - TEXT_DECORATION_LINE_THROUGH, TEXT_DECORATION_BLINK + TextDecorationNone, TextDecorationUnderline, TextDecorationOverline, + TextDecorationLineThrough, TextDecorationBlink CSSWordBreak* = enum - WORD_BREAK_NORMAL, WORD_BREAK_BREAK_ALL, WORD_BREAK_KEEP_ALL + WordBreakNormal, WordBreakBreakAll, WordBreakKeepAll CSSListStyleType* = enum - LIST_STYLE_TYPE_NONE, LIST_STYLE_TYPE_DISC, LIST_STYLE_TYPE_CIRCLE, - LIST_STYLE_TYPE_SQUARE, LIST_STYLE_TYPE_DECIMAL, - LIST_STYLE_TYPE_DISCLOSURE_CLOSED, LIST_STYLE_TYPE_DISCLOSURE_OPEN, - LIST_STYLE_TYPE_CJK_EARTHLY_BRANCH, LIST_STYLE_TYPE_CJK_HEAVENLY_STEM, - LIST_STYLE_TYPE_LOWER_ROMAN, LIST_STYLE_TYPE_UPPER_ROMAN, - LIST_STYLE_TYPE_LOWER_ALPHA, LIST_STYLE_TYPE_UPPER_ALPHA, - LIST_STYLE_TYPE_LOWER_GREEK, - LIST_STYLE_TYPE_HIRAGANA, LIST_STYLE_TYPE_HIRAGANA_IROHA, - LIST_STYLE_TYPE_KATAKANA, LIST_STYLE_TYPE_KATAKANA_IROHA, - LIST_STYLE_TYPE_JAPANESE_INFORMAL + ListStyleTypeNone, ListStyleTypeDisc, ListStyleTypeCircle, + ListStyleTypeSquare, ListStyleTypeDecimal, + ListStyleTypeDisclosureClosed, ListStyleTypeDisclosureOpen, + ListStyleTypeCjkEarthlyBranch, ListStyleTypeCjkHeavenlyStem, + ListStyleTypeLowerRoman, ListStyleTypeUpperRoman, + ListStyleTypeLowerAlpha, ListStyleTypeUpperAlpha, + ListStyleTypeLowerGreek, + ListStyleTypeHiragana, ListStyleTypeHiraganaIroha, + ListStyleTypeKatakana, ListStyleTypeKatakanaIroha, + ListStyleTypeJapaneseInformal CSSVerticalAlign2* = enum - VERTICAL_ALIGN_BASELINE, VERTICAL_ALIGN_SUB, VERTICAL_ALIGN_SUPER, - VERTICAL_ALIGN_TEXT_TOP, VERTICAL_ALIGN_TEXT_BOTTOM, VERTICAL_ALIGN_MIDDLE, - VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM + VerticalAlignBaseline, VerticalAlignSub, VerticalAlignSuper, + VerticalAlignTextTop, VerticalAlignTextBottom, VerticalAlignMiddle, + VerticalAlignTop, VerticalAlignBottom CSSTextAlign* = enum - TEXT_ALIGN_START, TEXT_ALIGN_END, TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, - TEXT_ALIGN_CENTER, TEXT_ALIGN_JUSTIFY, TEXT_ALIGN_CHA_CENTER, - TEXT_ALIGN_CHA_LEFT, TEXT_ALIGN_CHA_RIGHT + TextAlignStart, TextAlignEnd, TextAlignLeft, TextAlignRight, + TextAlignCenter, TextAlignJustify, TextAlignChaCenter, + TextAlignChaLeft, TextAlignChaRight CSSListStylePosition* = enum - LIST_STYLE_POSITION_OUTSIDE, LIST_STYLE_POSITION_INSIDE + ListStylePositionOutside, ListStylePositionInside CSSCaptionSide* = enum - CAPTION_SIDE_TOP, CAPTION_SIDE_BOTTOM, CAPTION_SIDE_BLOCK_START, - CAPTION_SIDE_BLOCK_END, + CaptionSideTop, CaptionSideBottom, CaptionSideBlockStart, + CaptionSideBlockEnd, CSSBorderCollapse* = enum - BORDER_COLLAPSE_SEPARATE, BORDER_COLLAPSE_COLLAPSE + BorderCollapseSeparate, BorderCollapseCollapse CSSContentType* = enum - CONTENT_STRING, CONTENT_OPEN_QUOTE, CONTENT_CLOSE_QUOTE, - CONTENT_NO_OPEN_QUOTE, CONTENT_NO_CLOSE_QUOTE, CONTENT_IMAGE, - CONTENT_VIDEO, CONTENT_AUDIO, CONTENT_NEWLINE + ContentString, ContentOpenQuote, ContentCloseQuote, + ContentNoOpenQuote, ContentNoCloseQuote, ContentImage, + ContentVideo, ContentAudio, ContentNewline CSSFloat* = enum - FLOAT_NONE, FLOAT_LEFT, FLOAT_RIGHT + FloatNone, FloatLeft, FloatRight CSSVisibility* = enum - VISIBILITY_VISIBLE, VISIBILITY_HIDDEN, VISIBILITY_COLLAPSE + VisibilityVisible, VisibilityHidden, VisibilityCollapse CSSBoxSizing* = enum - BOX_SIZING_CONTENT_BOX, BOX_SIZING_BORDER_BOX + BoxSizingContentBox, BoxSizingBorderBox CSSClear* = enum - CLEAR_NONE, CLEAR_LEFT, CLEAR_RIGHT, CLEAR_BOTH, CLEAR_INLINE_START, - CLEAR_INLINE_END + ClearNone, ClearLeft, ClearRight, ClearBoth, ClearInlineStart, + ClearInlineEnd CSSTextTransform* = enum - TEXT_TRANSFORM_NONE, TEXT_TRANSFORM_CAPITALIZE, TEXT_TRANSFORM_UPPERCASE, - TEXT_TRANSFORM_LOWERCASE, TEXT_TRANSFORM_FULL_WIDTH, - TEXT_TRANSFORM_FULL_SIZE_KANA, TEXT_TRANSFORM_CHA_HALF_WIDTH + TextTransformNone, TextTransformCapitalize, TextTransformUppercase, + TextTransformLowercase, TextTransformFullWidth, + TextTransformFullSizeKana, TextTransformChaHalfWidth CSSFlexDirection* = enum - FLEX_DIRECTION_ROW, FLEX_DIRECTION_ROW_REVERSE, FLEX_DIRECTION_COLUMN, - FLEX_DIRECTION_COLUMN_REVERSE + FlexDirectionRow, FlexDirectionRowReverse, FlexDirectionColumn, + FlexDirectionColumnReverse CSSFlexWrap* = enum - FLEX_WRAP_NOWRAP, FLEX_WRAP_WRAP, FLEX_WRAP_WRAP_REVERSE - -const RowGroupBox* = { - DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, - DISPLAY_TABLE_FOOTER_GROUP -} -const ProperTableChild* = RowGroupBox + { - DISPLAY_TABLE_ROW, DISPLAY_TABLE_COLUMN, DISPLAY_TABLE_COLUMN_GROUP, - DISPLAY_TABLE_CAPTION -} -const ProperTableRowParent* = RowGroupBox + { - DISPLAY_TABLE, DISPLAY_INLINE_TABLE -} -const InternalTableBox* = RowGroupBox + { - DISPLAY_TABLE_CELL, DISPLAY_TABLE_ROW, DISPLAY_TABLE_COLUMN, - DISPLAY_TABLE_COLUMN_GROUP -} -const TabularContainer* = {DISPLAY_TABLE_ROW} + ProperTableRowParent + FlexWrapNowrap, FlexWrapWrap, FlexWrapWrapReverse type CSSLength* = object @@ -315,9 +296,9 @@ type CSSComputedValues* = ref array[CSSPropertyType, CSSComputedValue] CSSOrigin* = enum - ORIGIN_USER_AGENT - ORIGIN_USER - ORIGIN_AUTHOR + coUserAgent + coUser + coAuthor CSSComputedEntry = tuple t: CSSPropertyType @@ -460,7 +441,7 @@ macro `{}`*(vals: CSSComputedValues; s: static string): untyped = return quote do: `vals`[CSSPropertyType(`t`)].`vs` -macro `{}=`*(vals: CSSComputedValues, s: static string, val: typed) = +macro `{}=`*(vals: CSSComputedValues; s: static string, val: typed) = let t = propertyType(s) let v = valueType(t) let vs = ident($v) @@ -487,42 +468,42 @@ func ic_to_px(ic: float64, window: WindowAttributes): LayoutUnit = func ex_to_px(ex: float64, window: WindowAttributes): LayoutUnit = ex * float64(window.ppc) / 2 -func px*(l: CSSLength, window: WindowAttributes, p: LayoutUnit): LayoutUnit +func px*(l: CSSLength; window: WindowAttributes; p: LayoutUnit): LayoutUnit {.inline.} = case l.unit - of UNIT_EM, UNIT_REM: em_to_px(l.num, window) - of UNIT_CH: ch_to_px(l.num, window) - of UNIT_IC: ic_to_px(l.num, window) - of UNIT_EX: ex_to_px(l.num, window) - of UNIT_PERC: toLayoutUnit(toFloat64(p) * l.num / 100) - of UNIT_PX: toLayoutUnit(l.num) - of UNIT_CM: toLayoutUnit(l.num * 37.8) - of UNIT_MM: toLayoutUnit(l.num * 3.78) - of UNIT_IN: toLayoutUnit(l.num * 96) - of UNIT_PC: toLayoutUnit(l.num * 16) - of UNIT_PT: toLayoutUnit(l.num * 4 / 3) - of UNIT_VW: toLayoutUnit(float64(window.width_px) * l.num / 100) - of UNIT_VH: toLayoutUnit(float64(window.height_px) * l.num / 100) - of UNIT_VMIN: + of cuEm, cuRem: em_to_px(l.num, window) + of cuCh: ch_to_px(l.num, window) + of cuIc: ic_to_px(l.num, window) + of cuEx: ex_to_px(l.num, window) + of cuPerc: toLayoutUnit(toFloat64(p) * l.num / 100) + of cuPx: toLayoutUnit(l.num) + of cuCm: toLayoutUnit(l.num * 37.8) + of cuMm: toLayoutUnit(l.num * 3.78) + of cuIn: toLayoutUnit(l.num * 96) + of cuPc: toLayoutUnit(l.num * 16) + of cuPt: toLayoutUnit(l.num * 4 / 3) + of cuVw: toLayoutUnit(float64(window.width_px) * l.num / 100) + of cuVh: toLayoutUnit(float64(window.height_px) * l.num / 100) + of cuVmin: toLayoutUnit(min(window.width_px, window.width_px) / 100 * l.num) - of UNIT_VMAX: + of cuVmax: toLayoutUnit(max(window.width_px, window.width_px) / 100 * l.num) func blockify*(display: CSSDisplay): CSSDisplay = case display - of DISPLAY_BLOCK, DISPLAY_TABLE, DISPLAY_LIST_ITEM, DISPLAY_NONE, - DISPLAY_FLOW_ROOT, DISPLAY_FLEX: + of DisplayBlock, DisplayTable, DisplayListItem, DisplayNone, DisplayFlowRoot, + DisplayFlex: #TODO grid return display - of DISPLAY_INLINE, DISPLAY_INLINE_BLOCK, DISPLAY_TABLE_ROW, - DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_COLUMN, - DISPLAY_TABLE_COLUMN_GROUP, DISPLAY_TABLE_CELL, DISPLAY_TABLE_CAPTION, - DISPLAY_TABLE_HEADER_GROUP, DISPLAY_TABLE_FOOTER_GROUP: - return DISPLAY_BLOCK - of DISPLAY_INLINE_TABLE: - return DISPLAY_TABLE - of DISPLAY_INLINE_FLEX: - return DISPLAY_FLEX + of DisplayInline, DisplayInlineBlock, DisplayTableRow, + DisplayTableRowGroup, DisplayTableColumn, + DisplayTableColumnGroup, DisplayTableCell, DisplayTableCaption, + DisplayTableHeaderGroup, DisplayTableFooterGroup: + return DisplayBlock + of DisplayInlineTable: + return DisplayTable + of DisplayInlineFlex: + return DisplayFlex const UpperAlphaMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toRunes() const LowerAlphaMap = "abcdefghijklmnopqrstuvwxyz".toRunes() @@ -538,7 +519,7 @@ const KatakanaIrohaMap = ("イãƒãƒãƒ‹ãƒ›ãƒ˜ãƒˆãƒãƒªãƒŒãƒ«ãƒ²ãƒ¯ã‚«ãƒ¨ã‚¿ãƒ¬ã‚ const EarthlyBranchMap = "å丑寅å¯è¾°å·³åˆæœªç”³é…‰æˆŒäº¥".toRunes() const HeavenlyStemMap = "甲乙丙ä¸æˆŠå·±åºšè¾›å£¬ç™¸".toRunes() -func numToBase(n: int, map: openArray[Rune]): string = +func numToBase(n: int; map: openArray[Rune]): string = if n <= 0: return $n var tmp: seq[Rune] @@ -551,37 +532,37 @@ func numToBase(n: int, map: openArray[Rune]): string = for i in countdown(tmp.high, 0): result &= $tmp[i] -func numToFixed(n: int, map: openArray[Rune]): string = +func numToFixed(n: int; map: openArray[Rune]): string = let n = n - 1 if n notin 0 .. map.high: return $n return $map[n] -func listMarker*(t: CSSListStyleType, i: int): string = +func listMarker*(t: CSSListStyleType; i: int): string = case t - of LIST_STYLE_TYPE_NONE: return "" - of LIST_STYLE_TYPE_DISC: return "• " # U+2022 - of LIST_STYLE_TYPE_CIRCLE: return "â—‹ " # U+25CB - of LIST_STYLE_TYPE_SQUARE: return "â–¡ " # U+25A1 - of LIST_STYLE_TYPE_DISCLOSURE_OPEN: return "â–¶ " # U+25B6 - of LIST_STYLE_TYPE_DISCLOSURE_CLOSED: return "â–¼ " # U+25BC - of LIST_STYLE_TYPE_DECIMAL: return $i & ". " - of LIST_STYLE_TYPE_UPPER_ROMAN: return romanNumber(i) & ". " - of LIST_STYLE_TYPE_LOWER_ROMAN: return romanNumberLower(i) & ". " - of LIST_STYLE_TYPE_UPPER_ALPHA: return numToBase(i, UpperAlphaMap) & ". " - of LIST_STYLE_TYPE_LOWER_ALPHA: return numToBase(i, LowerAlphaMap) & ". " - of LIST_STYLE_TYPE_LOWER_GREEK: return numToBase(i, LowerGreekMap) & ". " - of LIST_STYLE_TYPE_HIRAGANA: return numToBase(i, HiraganaMap) & "ã€" - of LIST_STYLE_TYPE_HIRAGANA_IROHA: + of ListStyleTypeNone: return "" + of ListStyleTypeDisc: return "• " # U+2022 + of ListStyleTypeCircle: return "â—‹ " # U+25CB + of ListStyleTypeSquare: return "â–¡ " # U+25A1 + of ListStyleTypeDisclosureOpen: return "â–¶ " # U+25B6 + of ListStyleTypeDisclosureClosed: return "â–¼ " # U+25BC + of ListStyleTypeDecimal: return $i & ". " + of ListStyleTypeUpperRoman: return romanNumber(i) & ". " + of ListStyleTypeLowerRoman: return romanNumberLower(i) & ". " + of ListStyleTypeUpperAlpha: return numToBase(i, UpperAlphaMap) & ". " + of ListStyleTypeLowerAlpha: return numToBase(i, LowerAlphaMap) & ". " + of ListStyleTypeLowerGreek: return numToBase(i, LowerGreekMap) & ". " + of ListStyleTypeHiragana: return numToBase(i, HiraganaMap) & "ã€" + of ListStyleTypeHiraganaIroha: return numToBase(i, HiraganaIrohaMap) & "ã€" - of LIST_STYLE_TYPE_KATAKANA: return numToBase(i, KatakanaMap) & "ã€" - of LIST_STYLE_TYPE_KATAKANA_IROHA: + of ListStyleTypeKatakana: return numToBase(i, KatakanaMap) & "ã€" + of ListStyleTypeKatakanaIroha: return numToBase(i, KatakanaIrohaMap) & "ã€" - of LIST_STYLE_TYPE_CJK_EARTHLY_BRANCH: + of ListStyleTypeCjkEarthlyBranch: return numToFixed(i, EarthlyBranchMap) & "ã€" - of LIST_STYLE_TYPE_CJK_HEAVENLY_STEM: + of ListStyleTypeCjkHeavenlyStem: return numToFixed(i, HeavenlyStemMap) & "ã€" - of LIST_STYLE_TYPE_JAPANESE_INFORMAL: return japaneseNumber(i) & "ã€" + of ListStyleTypeJapaneseInformal: return japaneseNumber(i) & "ã€" #TODO this should change by language func quoteStart*(level: int): string = @@ -601,22 +582,22 @@ const Colors: Table[string, RGBAColor] = ((func (): Table[string, RGBAColor] = )()) const Units = { - "%": UNIT_PERC, - "cm": UNIT_CM, - "mm": UNIT_MM, - "in": UNIT_IN, - "px": UNIT_PX, - "pt": UNIT_PT, - "pc": UNIT_PC, - "em": UNIT_EM, - "ex": UNIT_EX, - "ch": UNIT_CH, - "ic": UNIT_CH, - "rem": UNIT_REM, - "vw": UNIT_VW, - "vh": UNIT_VH, - "vmin": UNIT_VMIN, - "vmax": UNIT_VMAX, + "%": cuPerc, + "cm": cuCm, + "mm": cuMm, + "in": cuIn, + "px": cuPx, + "pt": cuPt, + "pc": cuPc, + "em": cuEm, + "ex": cuEx, + "ch": cuCh, + "ic": cuCh, + "rem": cuRem, + "vw": cuVw, + "vh": cuVh, + "vmin": cuVmin, + "vmax": cuVmax, }.toTable() func cssLength(val: float64, unit: string): Opt[CSSLength] = @@ -636,22 +617,22 @@ func parseDimensionValues*(s: string): Option[CSSLength] = n *= 10 n += float64(decValue(s[i])) inc i - if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) + if i >= s.len: return some(CSSLength(num: n, unit: cuPx)) if s[i] == '.': inc i - if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) + if i >= s.len: return some(CSSLength(num: n, unit: cuPx)) var d = 1 while i < s.len and s[i] in AsciiDigit: n += float64(decValue(s[i])) / float64(d) inc d inc i - if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) - if s[i] == '%': return some(CSSLength(num: n, unit: UNIT_PERC)) - return some(CSSLength(num: n, unit: UNIT_PX)) + if i >= s.len: return some(CSSLength(num: n, unit: cuPx)) + if s[i] == '%': return some(CSSLength(num: n, unit: cuPerc)) + return some(CSSLength(num: n, unit: cuPx)) -func skipWhitespace(vals: openArray[CSSComponentValue], i: var int) = +func skipWhitespace(vals: openArray[CSSComponentValue]; i: var int) = while i < vals.len: - if vals[i] != CSS_WHITESPACE_TOKEN: + if vals[i] != cttWhitespace: break inc i @@ -661,13 +642,13 @@ func parseRGBA(value: openArray[CSSComponentValue]): Opt[CellColor] = template check_err(slash: bool) = #TODO calc, percentages, etc (cssnumber function or something) if not slash and i >= value.len or i < value.len and - value[i] != CSS_NUMBER_TOKEN: + value[i] != cttNumber: return err() template next_value(first = false, slash = false) = inc i value.skipWhitespace(i) if i < value.len: - if value[i] == CSS_COMMA_TOKEN and (commaMode or first): + if value[i] == cttComma and (commaMode or first): # legacy compatibility inc i value.skipWhitespace(i) @@ -676,7 +657,7 @@ func parseRGBA(value: openArray[CSSComponentValue]): Opt[CellColor] = return err() elif slash: let tok = value[i] - if tok != CSS_DELIM_TOKEN or CSSToken(tok).cvalue != '/': + if tok != cttDelim or CSSToken(tok).cvalue != '/': return err() inc i value.skipWhitespace(i) @@ -708,11 +689,11 @@ func parseANSI(value: openArray[CSSComponentValue]): Opt[CellColor] = #TODO numeric functions return err() let tok = CSSToken(value[i]) - if tok.tokenType == CSS_NUMBER_TOKEN: + if tok.tokenType == cttNumber: if tok.nvalue notin 0..255: return err() # invalid numeric ANSI color return ok(ANSIColor(tok.nvalue).cellColor()) - elif tok.tokenType == CSS_IDENT_TOKEN: + elif tok.tokenType == cttIdent: var name = tok.value if name.equalsIgnoreCase("default"): return ok(defaultColor) @@ -742,11 +723,11 @@ func cssColor*(val: CSSComponentValue): Opt[CellColor] = if val of CSSToken: let tok = CSSToken(val) case tok.tokenType - of CSS_HASH_TOKEN: + of cttHash: let c = parseHexColor(tok.value) if c.isSome: return ok(c.get.cellColor()) - of CSS_IDENT_TOKEN: + of cttIdent: let s = tok.value.toLowerAscii() if s in Colors: return ok(Colors[s].cellColor()) @@ -769,7 +750,7 @@ func cssIdent[T](map: static openArray[(string, T)], cval: CSSComponentValue): Opt[T] = if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: # cmp when len is small enough, otherwise lowercase & hashmap when map.len <= 4: for (k, v) in map: @@ -782,32 +763,32 @@ func cssIdent[T](map: static openArray[(string, T)], cval: CSSComponentValue): return ok(MapTable[val]) return err() -func cssIdentFirst[T](map: static openArray[(string, T)], d: CSSDeclaration): +func cssIdentFirst[T](map: static openArray[(string, T)]; d: CSSDeclaration): Opt[T] = if d.value.len == 1: return cssIdent(map, d.value[0]) return err() -func cssLength*(val: CSSComponentValue, has_auto: static bool = true, +func cssLength*(val: CSSComponentValue; has_auto: static bool = true; allow_negative: static bool = true): Opt[CSSLength] = block nofail: if val of CSSToken: let tok = CSSToken(val) case tok.tokenType - of CSS_NUMBER_TOKEN: + of cttNumber: if tok.nvalue == 0: - return ok(CSSLength(num: 0, unit: UNIT_PX)) - of CSS_PERCENTAGE_TOKEN: + return ok(CSSLength(num: 0, unit: cuPx)) + of cttPercentage: when not allow_negative: if tok.nvalue < 0: break nofail return cssLength(tok.nvalue, "%") - of CSS_DIMENSION_TOKEN: + of cttDimension: when not allow_negative: if tok.nvalue < 0: break nofail return cssLength(tok.nvalue, tok.unit) - of CSS_IDENT_TOKEN: + of cttIdent: when has_auto: if tok.value.equalsIgnoreCase("auto"): return ok(CSSLengthAuto) @@ -818,10 +799,10 @@ func cssAbsoluteLength(val: CSSComponentValue): Opt[CSSLength] = if val of CSSToken: let tok = CSSToken(val) case tok.tokenType - of CSS_NUMBER_TOKEN: + of cttNumber: if tok.nvalue == 0: - return ok(CSSLength(num: 0, unit: UNIT_PX)) - of CSS_DIMENSION_TOKEN: + return ok(CSSLength(num: 0, unit: cuPx)) + of cttDimension: if tok.nvalue >= 0: return cssLength(tok.nvalue, tok.unit) else: discard @@ -831,9 +812,9 @@ func cssWordSpacing(cval: CSSComponentValue): Opt[CSSLength] = if cval of CSSToken: let tok = CSSToken(cval) case tok.tokenType - of CSS_DIMENSION_TOKEN: + of cttDimension: return cssLength(tok.nvalue, tok.unit) - of CSS_IDENT_TOKEN: + of cttIdent: if tok.value.equalsIgnoreCase("normal"): return ok(CSSLengthAuto) else: discard @@ -861,7 +842,7 @@ func cssQuotes(d: CSSDeclaration): Opt[CSSQuotes] = if isToken(cval): let tok = getToken(cval) case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: if res.qs.len > 0: die if tok.value.equalsIgnoreCase("auto"): res.auto = true @@ -869,7 +850,7 @@ func cssQuotes(d: CSSDeclaration): Opt[CSSQuotes] = if d.value.len != 1: die die - of CSS_STRING_TOKEN: + of cttString: if sa: pair.e = tok.value res.qs.add(pair) @@ -877,7 +858,7 @@ func cssQuotes(d: CSSDeclaration): Opt[CSSQuotes] = else: pair.s = tok.value sa = true - of CSS_WHITESPACE_TOKEN: discard + of cttWhitespace: discard else: die if sa: die @@ -888,66 +869,66 @@ func cssContent(d: CSSDeclaration): seq[CSSContent] = if isToken(cval): let tok = getToken(cval) case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: if tok.value == "/": break elif tok.value.equalsIgnoreCase("open-quote"): - result.add(CSSContent(t: CONTENT_OPEN_QUOTE)) + result.add(CSSContent(t: ContentOpenQuote)) elif tok.value.equalsIgnoreCase("no-open-quote"): - result.add(CSSContent(t: CONTENT_NO_OPEN_QUOTE)) + result.add(CSSContent(t: ContentNoOpenQuote)) elif tok.value.equalsIgnoreCase("close-quote"): - result.add(CSSContent(t: CONTENT_CLOSE_QUOTE)) + result.add(CSSContent(t: ContentCloseQuote)) elif tok.value.equalsIgnoreCase("no-close-quote"): - result.add(CSSContent(t: CONTENT_NO_CLOSE_QUOTE)) - of CSS_STRING_TOKEN: - result.add(CSSContent(t: CONTENT_STRING, s: tok.value)) + result.add(CSSContent(t: ContentNoCloseQuote)) + of cttString: + result.add(CSSContent(t: ContentString, s: tok.value)) else: return func cssDisplay(cval: CSSComponentValue): Opt[CSSDisplay] = const DisplayMap = { - "block": DISPLAY_BLOCK, - "inline": DISPLAY_INLINE, - "list-item": DISPLAY_LIST_ITEM, - "inline-block": DISPLAY_INLINE_BLOCK, - "table": DISPLAY_TABLE, - "table-row": DISPLAY_TABLE_ROW, - "table-cell": DISPLAY_TABLE_CELL, - "table-column": DISPLAY_TABLE_COLUMN, - "table-column-group": DISPLAY_TABLE_COLUMN_GROUP, - "inline-table": DISPLAY_INLINE_TABLE, - "table-row-group": DISPLAY_TABLE_ROW_GROUP, - "table-header-group": DISPLAY_TABLE_HEADER_GROUP, - "table-footer-group": DISPLAY_TABLE_FOOTER_GROUP, - "table-caption": DISPLAY_TABLE_CAPTION, - "flow-root": DISPLAY_FLOW_ROOT, - "flex": DISPLAY_FLEX, - "inline-flex": DISPLAY_INLINE_FLEX, - "none": DISPLAY_NONE + "block": DisplayBlock, + "inline": DisplayInline, + "list-item": DisplayListItem, + "inline-block": DisplayInlineBlock, + "table": DisplayTable, + "table-row": DisplayTableRow, + "table-cell": DisplayTableCell, + "table-column": DisplayTableColumn, + "table-column-group": DisplayTableColumnGroup, + "inline-table": DisplayInlineTable, + "table-row-group": DisplayTableRowGroup, + "table-header-group": DisplayTableHeaderGroup, + "table-footer-group": DisplayTableFooterGroup, + "table-caption": DisplayTableCaption, + "flow-root": DisplayFlowRoot, + "flex": DisplayFlex, + "inline-flex": DisplayInlineFlex, + "none": DisplayNone } return cssIdent(DisplayMap, cval) func cssFontStyle(cval: CSSComponentValue): Opt[CSSFontStyle] = const FontStyleMap = { - "normal": FONT_STYLE_NORMAL, - "italic": FONT_STYLE_ITALIC, - "oblique": FONT_STYLE_OBLIQUE + "normal": FontStyleNormal, + "italic": FontStyleItalic, + "oblique": FontStyleOblique } return cssIdent(FontStyleMap, cval) func cssWhiteSpace(cval: CSSComponentValue): Opt[CSSWhitespace] = const WhiteSpaceMap = { - "normal": WHITESPACE_NORMAL, - "nowrap": WHITESPACE_NOWRAP, - "pre": WHITESPACE_PRE, - "pre-line": WHITESPACE_PRE_LINE, - "pre-wrap": WHITESPACE_PRE_WRAP + "normal": WhitespaceNormal, + "nowrap": WhitespaceNowrap, + "pre": WhitespacePre, + "pre-line": WhitespacePreLine, + "pre-wrap": WhitespacePreWrap } return cssIdent(WhiteSpaceMap, cval) func cssFontWeight(cval: CSSComponentValue): Opt[int] = if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: const FontWeightMap = { "normal": 400, "bold": 700, @@ -955,7 +936,7 @@ func cssFontWeight(cval: CSSComponentValue): Opt[int] = "bolder": 700 } return cssIdent(FontWeightMap, cval) - elif tok.tokenType == CSS_NUMBER_TOKEN: + elif tok.tokenType == cttNumber: if tok.nvalue in 1f64..1000f64: return ok(int(tok.nvalue)) return err() @@ -965,69 +946,69 @@ func cssTextDecoration(d: CSSDeclaration): Opt[set[CSSTextDecoration]] = for cval in d.value: if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: if tok.value.equalsIgnoreCase("none"): if d.value.len != 1: return err() return ok(s) elif tok.value.equalsIgnoreCase("underline"): - s.incl(TEXT_DECORATION_UNDERLINE) + s.incl(TextDecorationUnderline) elif tok.value.equalsIgnoreCase("overline"): - s.incl(TEXT_DECORATION_OVERLINE) + s.incl(TextDecorationOverline) elif tok.value.equalsIgnoreCase("line-through"): - s.incl(TEXT_DECORATION_LINE_THROUGH) + s.incl(TextDecorationLineThrough) elif tok.value.equalsIgnoreCase("blink"): - s.incl(TEXT_DECORATION_BLINK) + s.incl(TextDecorationBlink) else: return err() return ok(s) func cssWordBreak(cval: CSSComponentValue): Opt[CSSWordBreak] = const WordBreakMap = { - "normal": WORD_BREAK_NORMAL, - "break-all": WORD_BREAK_BREAK_ALL, - "keep-all": WORD_BREAK_KEEP_ALL + "normal": WordBreakNormal, + "break-all": WordBreakBreakAll, + "keep-all": WordBreakKeepAll } return cssIdent(WordBreakMap, cval) func cssListStyleType(cval: CSSComponentValue): Opt[CSSListStyleType] = const ListStyleMap = { - "none": LIST_STYLE_TYPE_NONE, - "disc": LIST_STYLE_TYPE_DISC, - "circle": LIST_STYLE_TYPE_CIRCLE, - "square": LIST_STYLE_TYPE_SQUARE, - "decimal": LIST_STYLE_TYPE_DECIMAL, - "disclosure-open": LIST_STYLE_TYPE_DISCLOSURE_OPEN, - "disclosure-closed": LIST_STYLE_TYPE_DISCLOSURE_CLOSED, - "cjk-earthly-branch": LIST_STYLE_TYPE_CJK_EARTHLY_BRANCH, - "cjk-heavenly-stem": LIST_STYLE_TYPE_CJK_HEAVENLY_STEM, - "upper-roman": LIST_STYLE_TYPE_UPPER_ROMAN, - "lower-roman": LIST_STYLE_TYPE_LOWER_ROMAN, - "upper-latin": LIST_STYLE_TYPE_UPPER_ALPHA, - "lower-latin": LIST_STYLE_TYPE_LOWER_ALPHA, - "upper-alpha": LIST_STYLE_TYPE_UPPER_ALPHA, - "lower-alpha": LIST_STYLE_TYPE_UPPER_ALPHA, - "lower-greek": LIST_STYLE_TYPE_LOWER_GREEK, - "hiragana": LIST_STYLE_TYPE_HIRAGANA, - "hiragana-iroha": LIST_STYLE_TYPE_HIRAGANA_IROHA, - "katakana": LIST_STYLE_TYPE_KATAKANA, - "katakana-iroha": LIST_STYLE_TYPE_KATAKANA_IROHA, - "japanese-informal": LIST_STYLE_TYPE_JAPANESE_INFORMAL + "none": ListStyleTypeNone, + "disc": ListStyleTypeDisc, + "circle": ListStyleTypeCircle, + "square": ListStyleTypeSquare, + "decimal": ListStyleTypeDecimal, + "disclosure-open": ListStyleTypeDisclosureOpen, + "disclosure-closed": ListStyleTypeDisclosureClosed, + "cjk-earthly-branch": ListStyleTypeCjkEarthlyBranch, + "cjk-heavenly-stem": ListStyleTypeCjkHeavenlyStem, + "upper-roman": ListStyleTypeUpperRoman, + "lower-roman": ListStyleTypeLowerRoman, + "upper-latin": ListStyleTypeUpperAlpha, + "lower-latin": ListStyleTypeLowerAlpha, + "upper-alpha": ListStyleTypeUpperAlpha, + "lower-alpha": ListStyleTypeUpperAlpha, + "lower-greek": ListStyleTypeLowerGreek, + "hiragana": ListStyleTypeHiragana, + "hiragana-iroha": ListStyleTypeHiraganaIroha, + "katakana": ListStyleTypeKatakana, + "katakana-iroha": ListStyleTypeKatakanaIroha, + "japanese-informal": ListStyleTypeJapaneseInformal } return cssIdent(ListStyleMap, cval) func cssVerticalAlign(cval: CSSComponentValue): Opt[CSSVerticalAlign] = if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN: + if tok.tokenType == cttIdent: const VerticalAlignMap = { - "baseline": VERTICAL_ALIGN_BASELINE, - "sub": VERTICAL_ALIGN_SUB, - "super": VERTICAL_ALIGN_SUPER, - "text-top": VERTICAL_ALIGN_TEXT_BOTTOM, - "middle": VERTICAL_ALIGN_MIDDLE, - "top": VERTICAL_ALIGN_TOP, - "bottom": VERTICAL_ALIGN_BOTTOM + "baseline": VerticalAlignBaseline, + "sub": VerticalAlignSub, + "super": VerticalAlignSuper, + "text-top": VerticalAlignTextBottom, + "middle": VerticalAlignMiddle, + "top": VerticalAlignTop, + "bottom": VerticalAlignBottom } let va2 = ?cssIdent(VerticalAlignMap, cval) return ok(CSSVerticalAlign( @@ -1035,7 +1016,7 @@ func cssVerticalAlign(cval: CSSComponentValue): Opt[CSSVerticalAlign] = )) else: return ok(CSSVerticalAlign( - keyword: VERTICAL_ALIGN_BASELINE, + keyword: VerticalAlignBaseline, length: ?cssLength(tok, has_auto = false) )) return err() @@ -1044,9 +1025,9 @@ func cssLineHeight(cval: CSSComponentValue): Opt[CSSLength] = if cval of CSSToken: let tok = CSSToken(cval) case tok.tokenType - of CSS_NUMBER_TOKEN: + of cttNumber: return cssLength(tok.nvalue * 100, "%") - of CSS_IDENT_TOKEN: + of cttIdent: if tok.value == "normal": return ok(CSSLengthAuto) else: @@ -1055,46 +1036,46 @@ func cssLineHeight(cval: CSSComponentValue): Opt[CSSLength] = func cssTextAlign(cval: CSSComponentValue): Opt[CSSTextAlign] = const TextAlignMap = { - "start": TEXT_ALIGN_START, - "end": TEXT_ALIGN_END, - "left": TEXT_ALIGN_LEFT, - "right": TEXT_ALIGN_RIGHT, - "center": TEXT_ALIGN_CENTER, - "justify": TEXT_ALIGN_JUSTIFY, - "-cha-center": TEXT_ALIGN_CHA_CENTER + "start": TextAlignStart, + "end": TextAlignEnd, + "left": TextAlignLeft, + "right": TextAlignRight, + "center": TextAlignCenter, + "justify": TextAlignJustify, + "-cha-center": TextAlignChaCenter } return cssIdent(TextAlignMap, cval) func cssListStylePosition(cval: CSSComponentValue): Opt[CSSListStylePosition] = const ListStylePositionMap = { - "inside": LIST_STYLE_POSITION_INSIDE, - "outside": LIST_STYLE_POSITION_OUTSIDE + "inside": ListStylePositionInside, + "outside": ListStylePositionOutside } return cssIdent(ListStylePositionMap, cval) func cssPosition(cval: CSSComponentValue): Opt[CSSPosition] = const PositionMap = { - "static": POSITION_STATIC, - "relative": POSITION_RELATIVE, - "absolute": POSITION_ABSOLUTE, - "fixed": POSITION_FIXED, - "sticky": POSITION_STICKY + "static": PositionStatic, + "relative": PositionRelative, + "absolute": PositionAbsolute, + "fixed": PositionFixed, + "sticky": PositionSticky } return cssIdent(PositionMap, cval) func cssCaptionSide(cval: CSSComponentValue): Opt[CSSCaptionSide] = const CaptionSideMap = { - "top": CAPTION_SIDE_TOP, - "bottom": CAPTION_SIDE_BOTTOM, - "block-start": CAPTION_SIDE_BLOCK_START, - "block-end": CAPTION_SIDE_BLOCK_END, + "top": CaptionSideTop, + "bottom": CaptionSideBottom, + "block-start": CaptionSideBlockStart, + "block-end": CaptionSideBlockEnd, } return cssIdent(CaptionSideMap, cval) func cssBorderCollapse(cval: CSSComponentValue): Opt[CSSBorderCollapse] = const BorderCollapseMap = { - "collapse": BORDER_COLLAPSE_COLLAPSE, - "separate": BORDER_COLLAPSE_SEPARATE + "collapse": BorderCollapseCollapse, + "separate": BorderCollapseSeparate } return cssIdent(BorderCollapseMap, cval) @@ -1108,13 +1089,13 @@ func cssCounterReset(d: CSSDeclaration): Opt[seq[CSSCounterReset]] = if isToken(cval): let tok = getToken(cval) case tok.tokenType - of CSS_WHITESPACE_TOKEN: discard - of CSS_IDENT_TOKEN: + of cttWhitespace: discard + of cttIdent: if s: die r.name = tok.value s = true - of CSS_NUMBER_TOKEN: + of cttNumber: if not s: die r.num = int(tok.nvalue) @@ -1128,10 +1109,10 @@ func cssMaxMinSize(cval: CSSComponentValue): Opt[CSSLength] = if isToken(cval): let tok = getToken(cval) case tok.tokenType - of CSS_IDENT_TOKEN: + of cttIdent: if tok.value.equalsIgnoreCase("none"): return ok(CSSLengthAuto) - of CSS_NUMBER_TOKEN, CSS_DIMENSION_TOKEN, CSS_PERCENTAGE_TOKEN: + of cttNumber, cttDimension, cttPercentage: return cssLength(tok, allow_negative = false) else: discard return err() @@ -1140,7 +1121,7 @@ func cssMaxMinSize(cval: CSSComponentValue): Opt[CSSLength] = func cssURL(cval: CSSComponentValue): Option[string] = if isToken(cval): let tok = getToken(cval) - if tok == CSS_URL_TOKEN: + if tok == cttUrl: return some(tok.value) elif cval of CSSFunction: let fun = CSSFunction(cval) @@ -1149,9 +1130,9 @@ func cssURL(cval: CSSComponentValue): Option[string] = if not isToken(x): break let x = getToken(x) - if x == CSS_WHITESPACE_TOKEN: + if x == cttWhitespace: discard - elif x == CSS_STRING_TOKEN: + elif x == cttString: return some(x.value) else: break @@ -1161,94 +1142,94 @@ func cssImage(cval: CSSComponentValue): Opt[CSSContent] = if isToken(cval): #TODO bg-image only let tok = getToken(cval) - if tok.tokenType == CSS_IDENT_TOKEN and tok.value == "none": - return ok(CSSContent(t: CONTENT_IMAGE, s: "")) + if tok.tokenType == cttIdent and tok.value == "none": + return ok(CSSContent(t: ContentImage, s: "")) let url = cssURL(cval) if url.isSome: - return ok(CSSContent(t: CONTENT_IMAGE, s: url.get)) + return ok(CSSContent(t: ContentImage, s: url.get)) return err() -func cssInteger(cval: CSSComponentValue, range: Slice[int]): Opt[int] = +func cssInteger(cval: CSSComponentValue; range: Slice[int]): Opt[int] = if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_NUMBER_TOKEN: + if tok.tokenType == cttNumber: if tok.nvalue in float64(range.a)..float64(range.b): return ok(int(tok.nvalue)) return err() func cssFloat(cval: CSSComponentValue): Opt[CSSFloat] = const FloatMap = { - "none": FLOAT_NONE, - "left": FLOAT_LEFT, - "right": FLOAT_RIGHT + "none": FloatNone, + "left": FloatLeft, + "right": FloatRight } return cssIdent(FloatMap, cval) func cssVisibility(cval: CSSComponentValue): Opt[CSSVisibility] = const VisibilityMap = { - "visible": VISIBILITY_VISIBLE, - "hidden": VISIBILITY_HIDDEN, - "collapse": VISIBILITY_COLLAPSE + "visible": VisibilityVisible, + "hidden": VisibilityHidden, + "collapse": VisibilityCollapse } return cssIdent(VisibilityMap, cval) func cssBoxSizing(cval: CSSComponentValue): Opt[CSSBoxSizing] = const BoxSizingMap = { - "border-box": BOX_SIZING_BORDER_BOX, - "content-box": BOX_SIZING_CONTENT_BOX + "border-box": BoxSizingBorderBox, + "content-box": BoxSizingContentBox } return cssIdent(BoxSizingMap, cval) func cssClear(cval: CSSComponentValue): Opt[CSSClear] = const ClearMap = { - "none": CLEAR_NONE, - "left": CLEAR_LEFT, - "right": CLEAR_RIGHT, - "both": CLEAR_BOTH, - "inline-start": CLEAR_INLINE_START, - "inline-end": CLEAR_INLINE_END + "none": ClearNone, + "left": ClearLeft, + "right": ClearRight, + "both": ClearBoth, + "inline-start": ClearInlineStart, + "inline-end": ClearInlineEnd } return cssIdent(ClearMap, cval) func cssTextTransform(cval: CSSComponentValue): Opt[CSSTextTransform] = const TextTransformMap = { - "none": TEXT_TRANSFORM_NONE, - "capitalize": TEXT_TRANSFORM_CAPITALIZE, - "uppercase": TEXT_TRANSFORM_UPPERCASE, - "lowercase": TEXT_TRANSFORM_LOWERCASE, - "full-width": TEXT_TRANSFORM_FULL_WIDTH, - "full-size-kana": TEXT_TRANSFORM_FULL_SIZE_KANA, - "-cha-half-width": TEXT_TRANSFORM_CHA_HALF_WIDTH + "none": TextTransformNone, + "capitalize": TextTransformCapitalize, + "uppercase": TextTransformUppercase, + "lowercase": TextTransformLowercase, + "full-width": TextTransformFullWidth, + "full-size-kana": TextTransformFullSizeKana, + "-cha-half-width": TextTransformChaHalfWidth } return cssIdent(TextTransformMap, cval) func cssFlexDirection(cval: CSSComponentValue): Opt[CSSFlexDirection] = const FlexDirectionMap = { - "row": FLEX_DIRECTION_ROW, - "row-reverse": FLEX_DIRECTION_ROW_REVERSE, - "column": FLEX_DIRECTION_COLUMN, - "column-reverse": FLEX_DIRECTION_COLUMN_REVERSE, + "row": FlexDirectionRow, + "row-reverse": FlexDirectionRowReverse, + "column": FlexDirectionColumn, + "column-reverse": FlexDirectionColumnReverse, } return cssIdent(FlexDirectionMap, cval) func cssNumber(cval: CSSComponentValue; positive: bool): Opt[float64] = if isToken(cval): let tok = getToken(cval) - if tok.tokenType == CSS_NUMBER_TOKEN: + if tok.tokenType == cttNumber: if not positive or tok.nvalue >= 0: return ok(tok.nvalue) return err() func cssFlexWrap(cval: CSSComponentValue): Opt[CSSFlexWrap] = const FlexWrapMap = { - "nowrap": FLEX_WRAP_NOWRAP, - "wrap": FLEX_WRAP_WRAP, - "wrap-reverse": FLEX_WRAP_WRAP_REVERSE + "nowrap": FlexWrapNowrap, + "wrap": FlexWrapWrap, + "wrap-reverse": FlexWrapWrapReverse } return cssIdent(FlexWrapMap, cval) -proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, - vtype: CSSValueType, ptype: CSSPropertyType): Err[void] = +proc getValueFromDecl(val: CSSComputedValue; d: CSSDeclaration; + vtype: CSSValueType; ptype: CSSPropertyType): Err[void] = var i = 0 d.value.skipWhitespace(i) if i >= d.value.len: @@ -1355,7 +1336,7 @@ func getInitialLength(t: CSSPropertyType): CSSLength = cptFlexBasis: return CSSLengthAuto else: - return CSSLength(auto: false, unit: UNIT_PX, num: 0) + return CSSLength(auto: false, unit: cuPx, num: 0) func getInitialInteger(t: CSSPropertyType): int = case t @@ -1378,9 +1359,9 @@ func calcInitial(t: CSSPropertyType): CSSComputedValue = of cvtColor: nv = CSSComputedValue(v: v, color: getInitialColor(t)) of cvtDisplay: - nv = CSSComputedValue(v: v, display: DISPLAY_INLINE) + nv = CSSComputedValue(v: v, display: DisplayInline) of cvtWordBreak: - nv = CSSComputedValue(v: v, wordbreak: WORD_BREAK_NORMAL) + nv = CSSComputedValue(v: v, wordbreak: WordBreakNormal) of cvtLength: nv = CSSComputedValue(v: v, length: getInitialLength(t)) of cvtInteger: @@ -1403,7 +1384,7 @@ template getDefault(t: CSSPropertyType): CSSComputedValue = {.cast(noSideEffect).}: defaultTable[t] -func getComputedValue(d: CSSDeclaration, ptype: CSSPropertyType, +func getComputedValue(d: CSSDeclaration; ptype: CSSPropertyType; vtype: CSSValueType): Opt[CSSComputedEntry] = let global = cssGlobal(d) let val = CSSComputedValue(v: vtype) @@ -1412,12 +1393,12 @@ func getComputedValue(d: CSSDeclaration, ptype: CSSPropertyType, ?val.getValueFromDecl(d, vtype, ptype) return ok((ptype, val, global)) -func lengthShorthand(d: CSSDeclaration, props: array[4, CSSPropertyType]): +func lengthShorthand(d: CSSDeclaration; props: array[4, CSSPropertyType]): Opt[seq[CSSComputedEntry]] = var i = 0 var cvals: seq[CSSComponentValue] while i < d.value.len: - if d.value[i] != CSS_WHITESPACE_TOKEN: + if d.value[i] != cttWhitespace: cvals.add(d.value[i]) inc i var res: seq[CSSComputedEntry] @@ -1459,13 +1440,11 @@ func lengthShorthand(d: CSSDeclaration, props: array[4, CSSPropertyType]): return ok(res) const PropertyMarginSpec = [ - cptMarginTop, cptMarginRight, cptMarginBottom, - cptMarginLeft + cptMarginTop, cptMarginRight, cptMarginBottom, cptMarginLeft ] const PropertyPaddingSpec = [ - cptPaddingTop, cptPaddingRight, cptPaddingBottom, - cptPaddingLeft + cptPaddingTop, cptPaddingRight, cptPaddingBottom, cptPaddingLeft ] proc getComputedValues0(res: var seq[CSSComputedEntry]; d: CSSDeclaration): @@ -1493,7 +1472,7 @@ proc getComputedValues0(res: var seq[CSSComputedEntry]; d: CSSDeclaration): var valid = true if global == cvtNoglobal: for tok in d.value: - if tok == CSS_WHITESPACE_TOKEN: + if tok == cttWhitespace: continue if (let r = cssImage(tok); r.isOk): bgimageval = CSSComputedValue(v: cvtImage, image: r.get) @@ -1513,7 +1492,7 @@ proc getComputedValues0(res: var seq[CSSComputedEntry]; d: CSSDeclaration): var valid = true if global == cvtNoglobal: for tok in d.value: - if tok == CSS_WHITESPACE_TOKEN: + if tok == cttWhitespace: continue if (let r = cssListStylePosition(tok); r.isOk): positionVal = CSSComputedValue( @@ -1567,7 +1546,7 @@ proc getComputedValues0(res: var seq[CSSComputedEntry]; d: CSSDeclaration): else: # omitted, default to 0px let val = CSSComputedValue( v: cvtLength, - length: CSSLength(unit: UNIT_PX, num: 0) + length: CSSLength(unit: cuPx, num: 0) ) res.add((cptFlexBasis, val, global)) else: @@ -1602,17 +1581,17 @@ proc getComputedValues(d: CSSDeclaration): seq[CSSComputedEntry] = return res return @[] -proc addValues*(builder: var CSSComputedValuesBuilder, - decls: seq[CSSDeclaration], origin: CSSOrigin) = +proc addValues*(builder: var CSSComputedValuesBuilder; + decls: seq[CSSDeclaration]; origin: CSSOrigin) = for decl in decls: if decl.important: builder.importantProperties[origin].add(getComputedValues(decl)) else: builder.normalProperties[origin].add(getComputedValues(decl)) -proc applyValue(vals: CSSComputedValues, prop: CSSPropertyType, - val: CSSComputedValue, global: CSSGlobalValueType, - parent: CSSComputedValues, previousOrigin: CSSComputedValues) = +proc applyValue(vals: CSSComputedValues; prop: CSSPropertyType; + val: CSSComputedValue; global: CSSGlobalValueType; + parent: CSSComputedValues; previousOrigin: CSSComputedValues) = let parentVal = if parent != nil: parent[prop] else: @@ -1673,10 +1652,9 @@ func buildComputedValues*(builder: CSSComputedValuesBuilder): new(result) var previousOrigins: array[CSSOrigin, CSSComputedValues] block: - let origin = ORIGIN_USER_AGENT - for build in builder.normalProperties[origin]: + for build in builder.normalProperties[coUserAgent]: result.applyValue(build.t, build.val, build.global, builder.parent, nil) - previousOrigins[origin] = result.copyProperties() + previousOrigins[coUserAgent] = result.copyProperties() # Presentational hints override user agent style, but respect user/author # style. if builder.preshints != nil: @@ -1684,37 +1662,28 @@ func buildComputedValues*(builder: CSSComputedValuesBuilder): if builder.preshints[prop] != nil: result[prop] = builder.preshints[prop] block: - let origin = ORIGIN_USER - let prevOrigin = ORIGIN_USER_AGENT - for build in builder.normalProperties[origin]: + for build in builder.normalProperties[coUser]: result.applyValue(build.t, build.val, build.global, builder.parent, - previousOrigins[prevOrigin]) + previousOrigins[coUserAgent]) # save user origins so author can use them - previousOrigins[origin] = result.copyProperties() + previousOrigins[coUser] = result.copyProperties() block: - let origin = ORIGIN_AUTHOR - let prevOrigin = ORIGIN_USER - for build in builder.normalProperties[origin]: + for build in builder.normalProperties[coAuthor]: result.applyValue(build.t, build.val, build.global, builder.parent, - previousOrigins[prevOrigin]) + previousOrigins[coUser]) # no need to save user origins block: - let origin = ORIGIN_AUTHOR - let prevOrigin = ORIGIN_USER - for build in builder.importantProperties[origin]: + for build in builder.importantProperties[coAuthor]: result.applyValue(build.t, build.val, build.global, builder.parent, - previousOrigins[prevOrigin]) + previousOrigins[coUser]) # important, so no need to save origins block: - let origin = ORIGIN_USER - let prevOrigin = ORIGIN_USER_AGENT - for build in builder.importantProperties[origin]: + for build in builder.importantProperties[coUser]: result.applyValue(build.t, build.val, build.global, builder.parent, - previousOrigins[prevOrigin]) + previousOrigins[coUserAgent]) # important, so no need to save origins block: - let origin = ORIGIN_USER_AGENT - for build in builder.importantProperties[origin]: + for build in builder.importantProperties[coUserAgent]: result.applyValue(build.t, build.val, build.global, builder.parent, nil) # important, so no need to save origins # set defaults @@ -1725,7 +1694,7 @@ func buildComputedValues*(builder: CSSComputedValuesBuilder): result[prop] = builder.parent[prop] else: result[prop] = getDefault(prop) - if result{"float"} != FLOAT_NONE: + if result{"float"} != FloatNone: #TODO it may be better to handle this in layout let display = result{"display"}.blockify() if display != result{"display"}: diff --git a/src/html/catom.nim b/src/html/catom.nim index 40bfd75e..e8252fcd 100644 --- a/src/html/catom.nim +++ b/src/html/catom.nim @@ -90,7 +90,8 @@ macro makeStaticAtom = let tn = $StaticAtom0(i - 1) if tn in seen: continue - decl0.add(newNimNode(nnkEnumFieldDef).add(ident(f.strVal), newStrLitNode(tn))) + decl0.add(newNimNode(nnkEnumFieldDef).add(ident(f.strVal), + newStrLitNode(tn))) decl makeStaticAtom @@ -121,7 +122,7 @@ func hash*(atom: CAtom): Hash {.borrow.} func `$`*(a: CAtom): string {.borrow.} -func toAtom(factory: var CAtomFactoryObj, s: string): CAtom = +func toAtom(factory: var CAtomFactoryObj; s: string): CAtom = let h = s.hash() let i = h and (factory.strMap.len - 1) for atom in factory.strMap[i]: @@ -149,27 +150,27 @@ proc newCAtomFactory*(): CAtomFactory = factory[] = factoryInit.obj return factory -func toAtom*(factory: CAtomFactory, s: string): CAtom = +func toAtom*(factory: CAtomFactory; s: string): CAtom = return factory[].toAtom(s) -func toAtom*(factory: CAtomFactory, tagType: TagType): CAtom = +func toAtom*(factory: CAtomFactory; tagType: TagType): CAtom = assert tagType != TAG_UNKNOWN return CAtom(tagType) -func toAtom*(factory: CAtomFactory, attrType: StaticAtom): CAtom = +func toAtom*(factory: CAtomFactory; attrType: StaticAtom): CAtom = assert attrType != atUnknown return CAtom(attrType) -func toStr*(factory: CAtomFactory, atom: CAtom): string = +func toStr*(factory: CAtomFactory; atom: CAtom): string = return factory.atomMap[int(atom)] -func toTagType*(factory: CAtomFactory, atom: CAtom): TagType = +func toTagType*(factory: CAtomFactory; atom: CAtom): TagType = let i = int(atom) if i <= int(TagType.high): return TagType(i) return TAG_UNKNOWN -func toStaticAtom*(factory: CAtomFactory, atom: CAtom): StaticAtom = +func toStaticAtom*(factory: CAtomFactory; atom: CAtom): StaticAtom = let i = int(atom) if i <= int(StaticAtom.high): return StaticAtom(i) diff --git a/src/html/chadombuilder.nim b/src/html/chadombuilder.nim index 94c0237c..716358d3 100644 --- a/src/html/chadombuilder.nim +++ b/src/html/chadombuilder.nim @@ -49,20 +49,20 @@ type DOMParser = ref object # JS interface jsDestructor(DOMParser) #TODO this is disgusting and should be removed -proc setActiveParser(document: Document, wrapper: HTML5ParserWrapper) = +proc setActiveParser(document: Document; wrapper: HTML5ParserWrapper) = document.parser = cast[pointer](wrapper) wrapper.refs.add(document) proc getDocumentImpl(builder: ChaDOMBuilder): Node = return builder.document -proc atomToTagTypeImpl(builder: ChaDOMBuilder, atom: CAtom): TagType = +proc atomToTagTypeImpl(builder: ChaDOMBuilder; atom: CAtom): TagType = return builder.factory.toTagType(atom) -proc tagTypeToAtomImpl(builder: ChaDOMBuilder, tagType: TagType): CAtom = +proc tagTypeToAtomImpl(builder: ChaDOMBuilder; tagType: TagType): CAtom = return builder.factory.toAtom(tagType) -proc strToAtomImpl(builder: ChaDOMBuilder, s: string): CAtom = +proc strToAtomImpl(builder: ChaDOMBuilder; s: string): CAtom = return builder.factory.toAtom(s) proc finish(builder: ChaDOMBuilder) = @@ -89,11 +89,11 @@ proc restart*(wrapper: HTML5ParserWrapper, charset: Charset) = assert document.factory != nil wrapper.parser = initHTML5Parser(builder, wrapper.opts) -proc setQuirksModeImpl(builder: ChaDOMBuilder, quirksMode: QuirksMode) = +proc setQuirksModeImpl(builder: ChaDOMBuilder; quirksMode: QuirksMode) = if not builder.document.parser_cannot_change_the_mode_flag: builder.document.mode = quirksMode -proc setEncodingImpl(builder: ChaDOMBuilder, encoding: string): +proc setEncodingImpl(builder: ChaDOMBuilder; encoding: string): SetEncodingResult = if builder.confidence != ccTentative: return SET_ENCODING_CONTINUE @@ -112,23 +112,23 @@ proc setEncodingImpl(builder: ChaDOMBuilder, encoding: string): charset return SET_ENCODING_STOP -proc getTemplateContentImpl(builder: ChaDOMBuilder, handle: Node): Node = +proc getTemplateContentImpl(builder: ChaDOMBuilder; handle: Node): Node = return HTMLTemplateElement(handle).content -proc getParentNodeImpl(builder: ChaDOMBuilder, handle: Node): Option[Node] = +proc getParentNodeImpl(builder: ChaDOMBuilder; handle: Node): Option[Node] = return option(handle.parentNode) -proc getLocalNameImpl(builder: ChaDOMBuilder, handle: Node): CAtom = +proc getLocalNameImpl(builder: ChaDOMBuilder; handle: Node): CAtom = return Element(handle).localName -proc getNamespaceImpl(builder: ChaDOMBuilder, handle: Node): Namespace = +proc getNamespaceImpl(builder: ChaDOMBuilder; handle: Node): Namespace = return Element(handle).namespace proc createHTMLElementImpl(builder: ChaDOMBuilder): Node = return builder.document.newHTMLElement(TAG_HTML) -proc createElementForTokenImpl(builder: ChaDOMBuilder, localName: CAtom, - namespace: Namespace, intendedParent: Node, htmlAttrs: Table[CAtom, string], +proc createElementForTokenImpl(builder: ChaDOMBuilder; localName: CAtom; + namespace: Namespace; intendedParent: Node; htmlAttrs: Table[CAtom, string]; xmlAttrs: seq[ParsedAttr[CAtom]]): Node = let document = builder.document let element = document.newHTMLElement(localName, namespace) @@ -146,18 +146,18 @@ proc createElementForTokenImpl(builder: ChaDOMBuilder, localName: CAtom, # are parsing from document.write, but that sounds like a horrible idea. return element -proc createCommentImpl(builder: ChaDOMBuilder, text: string): Node = +proc createCommentImpl(builder: ChaDOMBuilder; text: string): Node = return builder.document.createComment(text) -proc createDocumentTypeImpl(builder: ChaDOMBuilder, name, publicId, +proc createDocumentTypeImpl(builder: ChaDOMBuilder; name, publicId, systemId: string): Node = return builder.document.newDocumentType(name, publicId, systemId) -proc insertBeforeImpl(builder: ChaDOMBuilder, parent, child: Node, +proc insertBeforeImpl(builder: ChaDOMBuilder; parent, child: Node; before: Option[Node]) = discard parent.insertBefore(child, before.get(nil)) -proc insertTextImpl(builder: ChaDOMBuilder, parent: Node, text: string, +proc insertTextImpl(builder: ChaDOMBuilder; parent: Node; text: string; before: Option[Node]) = let prevSibling = if before.isSome: before.get.previousSibling @@ -171,28 +171,28 @@ proc insertTextImpl(builder: ChaDOMBuilder, parent: Node, text: string, let text = builder.document.createTextNode(text) discard parent.insertBefore(text, before.get(nil)) -proc removeImpl(builder: ChaDOMBuilder, child: Node) = +proc removeImpl(builder: ChaDOMBuilder; child: Node) = child.remove(suppressObservers = true) -proc moveChildrenImpl(builder: ChaDOMBuilder, fromNode, toNode: Node) = +proc moveChildrenImpl(builder: ChaDOMBuilder; fromNode, toNode: Node) = var tomove = fromNode.childList for node in tomove: node.remove(suppressObservers = true) for child in tomove: toNode.insert(child, nil) -proc addAttrsIfMissingImpl(builder: ChaDOMBuilder, handle: Node, +proc addAttrsIfMissingImpl(builder: ChaDOMBuilder; handle: Node; attrs: Table[CAtom, string]) = let element = Element(handle) for k, v in attrs: if not element.attrb(k): element.attr(k, v) -proc setScriptAlreadyStartedImpl(builder: ChaDOMBuilder, script: Node) = +proc setScriptAlreadyStartedImpl(builder: ChaDOMBuilder; script: Node) = HTMLScriptElement(script).alreadyStarted = true -proc associateWithFormImpl(builder: ChaDOMBuilder, element, form, - intendedParent: Node) = +proc associateWithFormImpl(builder: ChaDOMBuilder; + element, form, intendedParent: Node) = if form.inSameTree(intendedParent): #TODO remove following test eventually if element of FormAssociatedElement: @@ -200,7 +200,7 @@ proc associateWithFormImpl(builder: ChaDOMBuilder, element, form, element.setForm(HTMLFormElement(form)) element.parserInserted = true -proc elementPoppedImpl(builder: ChaDOMBuilder, element: Node) = +proc elementPoppedImpl(builder: ChaDOMBuilder; element: Node) = let element = Element(element) if element of HTMLTextAreaElement: element.resetElement() @@ -208,8 +208,8 @@ proc elementPoppedImpl(builder: ChaDOMBuilder, element: Node) = assert builder.poppedScript == nil or not builder.document.scriptingEnabled builder.poppedScript = HTMLScriptElement(element) -proc newChaDOMBuilder(url: URL, window: Window, factory: CAtomFactory, - confidence: CharsetConfidence, charset = DefaultCharset): ChaDOMBuilder = +proc newChaDOMBuilder(url: URL; window: Window; factory: CAtomFactory; + confidence: CharsetConfidence; charset = DefaultCharset): ChaDOMBuilder = let document = newDocument(factory) document.contentType = "text/html" document.url = url @@ -224,7 +224,7 @@ proc newChaDOMBuilder(url: URL, window: Window, factory: CAtomFactory, ) # https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments -proc parseHTMLFragment*(element: Element, s: string): seq[Node] = +proc parseHTMLFragment*(element: Element; s: string): seq[Node] = let url = parseURL("about:blank").get let factory = element.document.factory let builder = newChaDOMBuilder(url, nil, factory, ccIrrelevant) @@ -260,8 +260,8 @@ proc parseHTMLFragment*(element: Element, s: string): seq[Node] = builder.finish() return root.childList -proc newHTML5ParserWrapper*(window: Window, url: URL, factory: CAtomFactory, - confidence: CharsetConfidence, charset: Charset): HTML5ParserWrapper = +proc newHTML5ParserWrapper*(window: Window; url: URL; factory: CAtomFactory; + confidence: CharsetConfidence; charset: Charset): HTML5ParserWrapper = let opts = HTML5ParserOpts[Node, CAtom](scripting: window.settings.scripting) let builder = newChaDOMBuilder(url, window, factory, confidence, charset) let wrapper = HTML5ParserWrapper( @@ -272,7 +272,7 @@ proc newHTML5ParserWrapper*(window: Window, url: URL, factory: CAtomFactory, builder.document.setActiveParser(wrapper) return wrapper -proc parseBuffer*(wrapper: HTML5ParserWrapper, buffer: openArray[char]): +proc parseBuffer*(wrapper: HTML5ParserWrapper; buffer: openArray[char]): ParseResult = let builder = wrapper.builder let document = builder.document @@ -347,7 +347,7 @@ proc finish*(wrapper: HTML5ParserWrapper) = proc newDOMParser(): DOMParser {.jsctor.} = return DOMParser() -proc parseFromString(ctx: JSContext, parser: DOMParser, str, t: string): +proc parseFromString(ctx: JSContext; parser: DOMParser; str, t: string): JSResult[Document] {.jsfunc.} = case t of "text/html": diff --git a/src/html/dom.nim b/src/html/dom.nim index e3d62b60..4237ebd3 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -50,12 +50,12 @@ import chame/tags type FormMethod* = enum - FORM_METHOD_GET, FORM_METHOD_POST, FORM_METHOD_DIALOG + fmGet, fmPost, fmDialog FormEncodingType* = enum - FORM_ENCODING_TYPE_URLENCODED = "application/x-www-form-urlencoded", - FORM_ENCODING_TYPE_MULTIPART = "multipart/form-data", - FORM_ENCODING_TYPE_TEXT_PLAIN = "text/plain" + fetUrlencoded = "application/x-www-form-urlencoded", + fetMultipart = "multipart/form-data", + fetTextPlain = "text/plain" type DocumentReadyState* = enum rsLoading = "loading" @@ -428,7 +428,7 @@ jsDestructor(CanvasRenderingContext2D) jsDestructor(TextMetrics) jsDestructor(CSSStyleDeclaration) -proc parseColor(element: Element, s: string): RGBAColor +proc parseColor(element: Element; s: string): RGBAColor proc resetTransform(state: var DrawingState) = state.transformMatrix = newIdentityMatrix(3) @@ -439,7 +439,7 @@ proc resetState(state: var DrawingState) = state.strokeStyle = rgba(0, 0, 0, 255) state.path = newPath() -proc create2DContext*(jctx: JSContext, target: HTMLCanvasElement, +proc create2DContext*(jctx: JSContext; target: HTMLCanvasElement; options: Option[JSValue]): CanvasRenderingContext2D = let ctx = CanvasRenderingContext2D( @@ -465,7 +465,7 @@ proc reset(ctx: CanvasRenderingContext2D) {.jsfunc.} = # CanvasTransform #TODO scale -proc rotate(ctx: CanvasRenderingContext2D, angle: float64) {.jsfunc.} = +proc rotate(ctx: CanvasRenderingContext2D; angle: float64) {.jsfunc.} = if classify(angle) in {fcInf, fcNegInf, fcNan}: return ctx.state.transformMatrix *= newMatrix( @@ -478,7 +478,7 @@ proc rotate(ctx: CanvasRenderingContext2D, angle: float64) {.jsfunc.} = h = 3 ) -proc translate(ctx: CanvasRenderingContext2D, x, y: float64) {.jsfunc.} = +proc translate(ctx: CanvasRenderingContext2D; x, y: float64) {.jsfunc.} = for v in [x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -492,7 +492,7 @@ proc translate(ctx: CanvasRenderingContext2D, x, y: float64) {.jsfunc.} = h = 3 ) -proc transform(ctx: CanvasRenderingContext2D, a, b, c, d, e, f: float64) +proc transform(ctx: CanvasRenderingContext2D; a, b, c, d, e, f: float64) {.jsfunc.} = for v in [a, b, c, d, e, f]: if classify(v) in {fcInf, fcNegInf, fcNan}: @@ -508,7 +508,7 @@ proc transform(ctx: CanvasRenderingContext2D, a, b, c, d, e, f: float64) ) #TODO getTransform, setTransform with DOMMatrix (i.e. we're missing DOMMatrix) -proc setTransform(ctx: CanvasRenderingContext2D, a, b, c, d, e, f: float64) +proc setTransform(ctx: CanvasRenderingContext2D; a, b, c, d, e, f: float64) {.jsfunc.} = for v in [a, b, c, d, e, f]: if classify(v) in {fcInf, fcNegInf, fcNan}: @@ -519,7 +519,7 @@ proc setTransform(ctx: CanvasRenderingContext2D, a, b, c, d, e, f: float64) proc resetTransform(ctx: CanvasRenderingContext2D) {.jsfunc.} = ctx.state.resetTransform() -func transform(ctx: CanvasRenderingContext2D, v: Vector2D): Vector2D = +func transform(ctx: CanvasRenderingContext2D; v: Vector2D): Vector2D = let mul = ctx.state.transformMatrix * newMatrix(@[v.x, v.y, 1], 1, 3) return Vector2D(x: mul.me[0], y: mul.me[1]) @@ -527,19 +527,19 @@ func transform(ctx: CanvasRenderingContext2D, v: Vector2D): Vector2D = proc fillStyle(ctx: CanvasRenderingContext2D): string {.jsfget.} = return ctx.state.fillStyle.serialize() -proc fillStyle(ctx: CanvasRenderingContext2D, s: string) {.jsfset.} = +proc fillStyle(ctx: CanvasRenderingContext2D; s: string) {.jsfset.} = #TODO gradient, pattern ctx.state.fillStyle = ctx.canvas.parseColor(s) proc strokeStyle(ctx: CanvasRenderingContext2D): string {.jsfget.} = return ctx.state.strokeStyle.serialize() -proc strokeStyle(ctx: CanvasRenderingContext2D, s: string) {.jsfset.} = +proc strokeStyle(ctx: CanvasRenderingContext2D; s: string) {.jsfset.} = #TODO gradient, pattern ctx.state.strokeStyle = ctx.canvas.parseColor(s) # CanvasRect -proc clearRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = +proc clearRect(ctx: CanvasRenderingContext2D; x, y, w, h: float64) {.jsfunc.} = for v in [x, y, w, h]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -552,7 +552,7 @@ proc clearRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = let y1 = uint64(min(max(y + h, 0), bh)) ctx.bitmap.clearRect(x0, x1, y0, y1) -proc fillRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = +proc fillRect(ctx: CanvasRenderingContext2D; x, y, w, h: float64) {.jsfunc.} = for v in [x, y, w, h]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -567,7 +567,7 @@ proc fillRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = let y1 = uint64(min(max(y + h, 0), bh)) ctx.bitmap.fillRect(x0, x1, y0, y1, ctx.state.fillStyle) -proc strokeRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = +proc strokeRect(ctx: CanvasRenderingContext2D; x, y, w, h: float64) {.jsfunc.} = for v in [x, y, w, h]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -586,8 +586,8 @@ proc strokeRect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = proc beginPath(ctx: CanvasRenderingContext2D) {.jsfunc.} = ctx.state.path.beginPath() -proc fill(ctx: CanvasRenderingContext2D, - fillRule = CanvasFillRule.NON_ZERO) {.jsfunc.} = #TODO path +proc fill(ctx: CanvasRenderingContext2D; fillRule = cfrNonZero) {.jsfunc.} = + #TODO path ctx.state.path.tempClosePath() ctx.bitmap.fillPath(ctx.state.path, ctx.state.fillStyle, fillRule) ctx.state.path.tempOpenPath() @@ -595,10 +595,9 @@ proc fill(ctx: CanvasRenderingContext2D, proc stroke(ctx: CanvasRenderingContext2D) {.jsfunc.} = #TODO path ctx.bitmap.strokePath(ctx.state.path, ctx.state.strokeStyle) -proc clip(ctx: CanvasRenderingContext2D, - fillRule = CanvasFillRule.NON_ZERO) {.jsfunc.} = #TODO path - #TODO implement - discard +proc clip(ctx: CanvasRenderingContext2D; fillRule = cfrNonZero) {.jsfunc.} = + #TODO path + discard #TODO implement #TODO clip, ... @@ -606,22 +605,26 @@ proc clip(ctx: CanvasRenderingContext2D, # CanvasText #TODO maxwidth -proc fillText(ctx: CanvasRenderingContext2D, text: string, x, y: float64) {.jsfunc.} = +proc fillText(ctx: CanvasRenderingContext2D; text: string; x, y: float64) + {.jsfunc.} = for v in [x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return let vec = ctx.transform(Vector2D(x: x, y: y)) - ctx.bitmap.fillText(text, vec.x, vec.y, ctx.state.fillStyle, ctx.state.textAlign) + ctx.bitmap.fillText(text, vec.x, vec.y, ctx.state.fillStyle, + ctx.state.textAlign) #TODO maxwidth -proc strokeText(ctx: CanvasRenderingContext2D, text: string, x, y: float64) {.jsfunc.} = +proc strokeText(ctx: CanvasRenderingContext2D; text: string; x, y: float64) + {.jsfunc.} = for v in [x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return let vec = ctx.transform(Vector2D(x: x, y: y)) - ctx.bitmap.strokeText(text, vec.x, vec.y, ctx.state.strokeStyle, ctx.state.textAlign) + ctx.bitmap.strokeText(text, vec.x, vec.y, ctx.state.strokeStyle, + ctx.state.textAlign) -proc measureText(ctx: CanvasRenderingContext2D, text: string): TextMetrics +proc measureText(ctx: CanvasRenderingContext2D; text: string): TextMetrics {.jsfunc.} = let tw = text.width() return TextMetrics( @@ -639,12 +642,12 @@ proc measureText(ctx: CanvasRenderingContext2D, text: string): TextMetrics proc lineWidth(ctx: CanvasRenderingContext2D): float64 {.jsfget.} = return ctx.state.lineWidth -proc lineWidth(ctx: CanvasRenderingContext2D, f: float64) {.jsfset.} = +proc lineWidth(ctx: CanvasRenderingContext2D; f: float64) {.jsfset.} = if classify(f) in {fcZero, fcNegZero, fcInf, fcNegInf, fcNan}: return ctx.state.lineWidth = f -proc setLineDash(ctx: CanvasRenderingContext2D, segments: seq[float64]) +proc setLineDash(ctx: CanvasRenderingContext2D; segments: seq[float64]) {.jsfunc.} = discard #TODO implement @@ -654,56 +657,57 @@ proc getLineDash(ctx: CanvasRenderingContext2D): seq[float64] {.jsfunc.} = # CanvasTextDrawingStyles proc textAlign(ctx: CanvasRenderingContext2D): string {.jsfget.} = case ctx.state.textAlign - of TEXT_ALIGN_START: return "start" - of TEXT_ALIGN_END: return "end" - of TEXT_ALIGN_LEFT: return "left" - of TEXT_ALIGN_RIGHT: return "right" - of TEXT_ALIGN_CENTER: return "center" + of TextAlignStart: return "start" + of TextAlignEnd: return "end" + of TextAlignLeft: return "left" + of TextAlignRight: return "right" + of TextAlignCenter: return "center" else: doAssert false -proc textAlign(ctx: CanvasRenderingContext2D, s: string) {.jsfset.} = +proc textAlign(ctx: CanvasRenderingContext2D; s: string) {.jsfset.} = ctx.state.textAlign = case s - of "start": TEXT_ALIGN_START - of "end": TEXT_ALIGN_END - of "left": TEXT_ALIGN_LEFT - of "right": TEXT_ALIGN_RIGHT - of "center": TEXT_ALIGN_CENTER + of "start": TextAlignStart + of "end": TextAlignEnd + of "left": TextAlignLeft + of "right": TextAlignRight + of "center": TextAlignCenter else: ctx.state.textAlign # CanvasPath proc closePath(ctx: CanvasRenderingContext2D) {.jsfunc.} = ctx.state.path.closePath() -proc moveTo(ctx: CanvasRenderingContext2D, x, y: float64) {.jsfunc.} = +proc moveTo(ctx: CanvasRenderingContext2D; x, y: float64) {.jsfunc.} = ctx.state.path.moveTo(x, y) -proc lineTo(ctx: CanvasRenderingContext2D, x, y: float64) {.jsfunc.} = +proc lineTo(ctx: CanvasRenderingContext2D; x, y: float64) {.jsfunc.} = ctx.state.path.lineTo(x, y) -proc quadraticCurveTo(ctx: CanvasRenderingContext2D, cpx, cpy, x, +proc quadraticCurveTo(ctx: CanvasRenderingContext2D; cpx, cpy, x, y: float64) {.jsfunc.} = ctx.state.path.quadraticCurveTo(cpx, cpy, x, y) -proc arcTo(ctx: CanvasRenderingContext2D, x1, y1, x2, y2, radius: float64): +proc arcTo(ctx: CanvasRenderingContext2D; x1, y1, x2, y2, radius: float64): Err[DOMException] {.jsfunc.} = return ctx.state.path.arcTo(x1, y1, x2, y2, radius) -proc arc(ctx: CanvasRenderingContext2D, x, y, radius, startAngle, - endAngle: float64, counterclockwise = false): Err[DOMException] +proc arc(ctx: CanvasRenderingContext2D; x, y, radius, startAngle, + endAngle: float64; counterclockwise = false): Err[DOMException] {.jsfunc.} = return ctx.state.path.arc(x, y, radius, startAngle, endAngle, counterclockwise) -proc ellipse(ctx: CanvasRenderingContext2D, x, y, radiusX, radiusY, rotation, - startAngle, endAngle: float64, counterclockwise = false): Err[DOMException] +proc ellipse(ctx: CanvasRenderingContext2D; x, y, radiusX, radiusY, rotation, + startAngle, endAngle: float64; counterclockwise = false): Err[DOMException] {.jsfunc.} = return ctx.state.path.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) -proc rect(ctx: CanvasRenderingContext2D, x, y, w, h: float64) {.jsfunc.} = +proc rect(ctx: CanvasRenderingContext2D; x, y, w, h: float64) {.jsfunc.} = ctx.state.path.rect(x, y, w, h) -proc roundRect(ctx: CanvasRenderingContext2D, x, y, w, h, radii: float64) {.jsfunc.} = +proc roundRect(ctx: CanvasRenderingContext2D; x, y, w, h, radii: float64) + {.jsfunc.} = ctx.state.path.roundRect(x, y, w, h, radii) # Reflected attributes. @@ -731,7 +735,7 @@ template toset(ts: openArray[TagType]): set[TagType] = tags.incl(tag) tags -func makes(name: static string, ts: set[TagType]): ReflectEntry = +func makes(name: static string; ts: set[TagType]): ReflectEntry = const attrname = attrType0(name) ReflectEntry( attrname: attrname, @@ -740,7 +744,7 @@ func makes(name: static string, ts: set[TagType]): ReflectEntry = tags: ts ) -func makes(attrname, funcname: static string, ts: set[TagType]): +func makes(attrname, funcname: static string; ts: set[TagType]): ReflectEntry = const attrname = attrType0(attrname) ReflectEntry( @@ -750,14 +754,14 @@ func makes(attrname, funcname: static string, ts: set[TagType]): tags: ts ) -func makes(name: static string, ts: varargs[TagType]): ReflectEntry = +func makes(name: static string; ts: varargs[TagType]): ReflectEntry = makes(name, toset(ts)) -func makes(attrname, funcname: static string, ts: varargs[TagType]): +func makes(attrname, funcname: static string; ts: varargs[TagType]): ReflectEntry = makes(attrname, funcname, toset(ts)) -func makeb(attrname, funcname: static string, ts: varargs[TagType]): +func makeb(attrname, funcname: static string; ts: varargs[TagType]): ReflectEntry = const attrname = attrType0(attrname) ReflectEntry( @@ -767,10 +771,10 @@ func makeb(attrname, funcname: static string, ts: varargs[TagType]): tags: toset(ts) ) -func makeb(name: static string, ts: varargs[TagType]): ReflectEntry = +func makeb(name: static string; ts: varargs[TagType]): ReflectEntry = makeb(name, name, ts) -func makeul(name: static string, ts: varargs[TagType], default = 0u32): +func makeul(name: static string; ts: varargs[TagType]; default = 0u32): ReflectEntry = const attrname = attrType0(name) ReflectEntry( @@ -781,7 +785,7 @@ func makeul(name: static string, ts: varargs[TagType], default = 0u32): u: default ) -func makeulgz(name: static string, ts: varargs[TagType], default = 0u32): +func makeulgz(name: static string; ts: varargs[TagType], default = 0u32): ReflectEntry = const attrname = attrType0(name) ReflectEntry( @@ -823,43 +827,43 @@ const ReflectTable0 = [ ] # Forward declarations -func attr*(element: Element, s: StaticAtom): string -func attrb*(element: Element, s: CAtom): bool -proc attr*(element: Element, name: CAtom, value: string) -proc attr*(element: Element, name: StaticAtom, value: string) +func attr*(element: Element; s: StaticAtom): string +func attrb*(element: Element; s: CAtom): bool +proc attr*(element: Element; name: CAtom; value: string) +proc attr*(element: Element; name: StaticAtom; value: string) func baseURL*(document: Document): URL -proc delAttr(element: Element, i: int, keep = false) -proc reflectAttrs(element: Element, name: CAtom, value: string) +proc delAttr(element: Element; i: int; keep = false) +proc reflectAttrs(element: Element; name: CAtom; value: string) func document*(node: Node): Document = if node of Document: return Document(node) return node.document_internal -proc toAtom*(document: Document, s: string): CAtom = +proc toAtom*(document: Document; s: string): CAtom = return document.factory.toAtom(s) -proc toAtom*(document: Document, at: StaticAtom): CAtom = +proc toAtom*(document: Document; at: StaticAtom): CAtom = return document.factory.toAtom(at) -proc toStr(document: Document, atom: CAtom): string = +proc toStr(document: Document; atom: CAtom): string = return document.factory.toStr(atom) -proc toTagType*(document: Document, atom: CAtom): TagType = +proc toTagType*(document: Document; atom: CAtom): TagType = return document.factory.toTagType(atom) -proc toStaticAtom(document: Document, atom: CAtom): StaticAtom = +proc toStaticAtom(document: Document; atom: CAtom): StaticAtom = return document.factory.toStaticAtom(atom) -proc toAtom*(document: Document, tagType: TagType): CAtom = +proc toAtom*(document: Document; tagType: TagType): CAtom = return document.factory.toAtom(tagType) -proc toAtom(document: Document, namespace: Namespace): CAtom = +proc toAtom(document: Document; namespace: Namespace): CAtom = #TODO optimize assert namespace != NO_NAMESPACE return document.toAtom($namespace) -proc toAtom(document: Document, prefix: NamespacePrefix): CAtom = +proc toAtom(document: Document; prefix: NamespacePrefix): CAtom = #TODO optimize assert prefix != NO_PREFIX return document.toAtom($prefix) @@ -875,22 +879,22 @@ func tagType*(element: Element): TagType = func localNameStr*(element: Element): string = return element.document.toStr(element.localName) -func findAttr(element: Element, qualifiedName: CAtom): int = +func findAttr(element: Element; qualifiedName: CAtom): int = for i, attr in element.attrs: if attr.qualifiedName == qualifiedName: return i return -1 -func findAttr(element: Element, qualifiedName: StaticAtom): int = +func findAttr(element: Element; qualifiedName: StaticAtom): int = return element.findAttr(element.document.toAtom(qualifiedName)) -func findAttrNS(element: Element, namespace, qualifiedName: CAtom): int = +func findAttrNS(element: Element; namespace, qualifiedName: CAtom): int = for i, attr in element.attrs: if attr.namespace == namespace and attr.qualifiedName == qualifiedName: return i return -1 -func escapeText(s: string, attribute_mode = false): string = +func escapeText(s: string; attribute_mode = false): string = var nbsp_mode = false var nbsp_prev: char for c in s: @@ -915,7 +919,9 @@ func escapeText(s: string, attribute_mode = false): string = result &= c func `$`*(node: Node): string = - if node == nil: return "null" #TODO this isn't standard compliant but helps debugging + # Note: this function should only be used for debugging. + if node == nil: + return "null" if node of Element: let element = Element(node) result = "<" & element.localNameStr @@ -990,12 +996,12 @@ iterator elements*(node: Node): Element {.inline.} = if child of Element: yield Element(child) -iterator elements*(node: Node, tag: TagType): Element {.inline.} = +iterator elements*(node: Node; tag: TagType): Element {.inline.} = for desc in node.elements: if desc.tagType == tag: yield desc -iterator elements*(node: Node, tag: set[TagType]): Element {.inline.} = +iterator elements*(node: Node; tag: set[TagType]): Element {.inline.} = for desc in node.elements: if desc.tagType in tag: yield desc @@ -1095,7 +1101,7 @@ func len(collection: Collection): int = type CollectionMatchFun = proc(node: Node): bool {.noSideEffect.} -func newCollection[T: Collection](root: Node, match: CollectionMatchFun, +func newCollection[T: Collection](root: Node; match: CollectionMatchFun; islive, childonly: bool): T = result = T( islive: islive, @@ -1167,18 +1173,18 @@ func childNodes(node: Node): NodeList {.jsfget.} = func length(tokenList: DOMTokenList): uint32 {.jsfget.} = return uint32(tokenList.toks.len) -func item(tokenList: DOMTokenList, i: int): Option[string] {.jsfunc.} = +func item(tokenList: DOMTokenList; i: int): Option[string] {.jsfunc.} = if i < tokenList.toks.len: return some(tokenList.element.document.toStr(tokenList.toks[i])) return none(string) -func contains*(tokenList: DOMTokenList, a: CAtom): bool = +func contains*(tokenList: DOMTokenList; a: CAtom): bool = return a in tokenList.toks -func contains(tokenList: DOMTokenList, a: StaticAtom): bool = +func contains(tokenList: DOMTokenList; a: StaticAtom): bool = return tokenList.element.document.toAtom(a) in tokenList.toks -func jsContains(tokenList: DOMTokenList, s: string): bool +func jsContains(tokenList: DOMTokenList; s: string): bool {.jsfunc: "contains".} = return tokenList.element.document.toAtom(s) in tokenList @@ -1204,7 +1210,7 @@ func validateDOMToken(tok: string): Err[DOMException] = "InvalidCharacterError") return ok() -proc add(tokenList: DOMTokenList, tokens: varargs[string]): Err[DOMException] +proc add(tokenList: DOMTokenList; tokens: varargs[string]): Err[DOMException] {.jsfunc.} = for tok in tokens: ?validateDOMToken(tok) @@ -1214,7 +1220,7 @@ proc add(tokenList: DOMTokenList, tokens: varargs[string]): Err[DOMException] tokenList.update() return ok() -proc remove(tokenList: DOMTokenList, tokens: varargs[string]): +proc remove(tokenList: DOMTokenList; tokens: varargs[string]): Err[DOMException] {.jsfunc.} = for tok in tokens: ?validateDOMToken(tok) @@ -1226,7 +1232,7 @@ proc remove(tokenList: DOMTokenList, tokens: varargs[string]): tokenList.update() return ok() -proc toggle(tokenList: DOMTokenList, token: string, force = none(bool)): +proc toggle(tokenList: DOMTokenList; token: string; force = none(bool)): DOMResult[bool] {.jsfunc.} = ?validateDOMToken(token) let token = tokenList.element.document.toAtom(token) @@ -1243,7 +1249,7 @@ proc toggle(tokenList: DOMTokenList, token: string, force = none(bool)): return ok(true) return ok(false) -proc replace(tokenList: DOMTokenList, token, newToken: string): +proc replace(tokenList: DOMTokenList; token, newToken: string): DOMResult[bool] {.jsfunc.} = ?validateDOMToken(token) ?validateDOMToken(newToken) @@ -1264,7 +1270,7 @@ const SupportedTokensMap = { ] }.toTable() -func supports(tokenList: DOMTokenList, token: string): +func supports(tokenList: DOMTokenList; token: string): JSResult[bool] {.jsfunc.} = let localName = tokenList.element.document.toStaticAtom(tokenList.localName) if localName in SupportedTokensMap: @@ -1275,7 +1281,7 @@ func supports(tokenList: DOMTokenList, token: string): func value(tokenList: DOMTokenList): string {.jsfget.} = return $tokenList -func getter(tokenList: DOMTokenList, i: int): Option[string] {.jsgetprop.} = +func getter(tokenList: DOMTokenList; i: int): Option[string] {.jsgetprop.} = return tokenList.item(i) # DOMStringMap @@ -1291,18 +1297,18 @@ func validateAttributeQName(name: string): Err[DOMException] = return errDOMException("Invalid character in attribute name", "InvalidCharacterError") -func hasprop(map: ptr DOMStringMap, name: string): bool {.jshasprop.} = +func hasprop(map: ptr DOMStringMap; name: string): bool {.jshasprop.} = let name = map[].target.document.toAtom("data-" & name) return map[].target.attrb(name) -proc delete(map: ptr DOMStringMap, name: string): bool {.jsfunc.} = +proc delete(map: ptr DOMStringMap; name: string): bool {.jsfunc.} = let name = map[].target.document.toAtom("data-" & name.camelToKebabCase()) let i = map[].target.findAttr(name) if i != -1: map[].target.delAttr(i) return i != -1 -func getter(map: ptr DOMStringMap, name: string): Option[string] +func getter(map: ptr DOMStringMap; name: string): Option[string] {.jsgetprop.} = let name = map[].target.document.toAtom("data-" & name.camelToKebabCase()) let i = map[].target.findAttr(name) @@ -1310,7 +1316,7 @@ func getter(map: ptr DOMStringMap, name: string): Option[string] return some(map[].target.attrs[i].value) return none(string) -proc setter(map: ptr DOMStringMap, name, value: string): Err[DOMException] +proc setter(map: ptr DOMStringMap; name, value: string): Err[DOMException] {.jssetprop.} = var washy = false for c in name: @@ -1325,7 +1331,7 @@ proc setter(map: ptr DOMStringMap, name, value: string): Err[DOMException] map.target.attr(aname, value) return ok() -func names(ctx: JSContext, map: ptr DOMStringMap): JSPropertyEnumList +func names(ctx: JSContext; map: ptr DOMStringMap): JSPropertyEnumList {.jspropnames.} = var list = newJSPropertyEnumList(ctx, uint32(map[].target.attrs.len)) for attr in map[].target.attrs: @@ -1338,17 +1344,17 @@ func names(ctx: JSContext, map: ptr DOMStringMap): JSPropertyEnumList func length(nodeList: NodeList): uint32 {.jsfget.} = return uint32(nodeList.len) -func hasprop(nodeList: NodeList, i: int): bool {.jshasprop.} = +func hasprop(nodeList: NodeList; i: int): bool {.jshasprop.} = return i < nodeList.len -func item(nodeList: NodeList, i: int): Node {.jsfunc.} = +func item(nodeList: NodeList; i: int): Node {.jsfunc.} = if i < nodeList.len: return nodeList.snapshot[i] -func getter(nodeList: NodeList, i: int): Option[Node] {.jsgetprop.} = +func getter(nodeList: NodeList; i: int): Option[Node] {.jsgetprop.} = return option(nodeList.item(i)) -func names(ctx: JSContext, nodeList: NodeList): JSPropertyEnumList +func names(ctx: JSContext; nodeList: NodeList): JSPropertyEnumList {.jspropnames.} = let L = nodeList.length var list = newJSPropertyEnumList(ctx, L) @@ -1360,15 +1366,15 @@ func names(ctx: JSContext, nodeList: NodeList): JSPropertyEnumList proc length(collection: HTMLCollection): uint32 {.jsfget.} = return uint32(collection.len) -func hasprop(collection: HTMLCollection, u: uint32): bool {.jshasprop.} = +func hasprop(collection: HTMLCollection; u: uint32): bool {.jshasprop.} = return u < collection.length -func item(collection: HTMLCollection, u: uint32): Element {.jsfunc.} = +func item(collection: HTMLCollection; u: uint32): Element {.jsfunc.} = if u < collection.length: return Element(collection.snapshot[int(u)]) return nil -func namedItem(collection: HTMLCollection, s: string): Element {.jsfunc.} = +func namedItem(collection: HTMLCollection; s: string): Element {.jsfunc.} = let a = collection.root.document.toAtom(s) for it in collection.snapshot: let it = Element(it) @@ -1376,14 +1382,14 @@ func namedItem(collection: HTMLCollection, s: string): Element {.jsfunc.} = return it return nil -func getter[T: uint32|string](collection: HTMLCollection, u: T): +func getter[T: uint32|string](collection: HTMLCollection; u: T): Option[Element] {.jsgetprop.} = when T is uint32: return option(collection.item(u)) else: return option(collection.namedItem(u)) -func names(ctx: JSContext, collection: HTMLCollection): JSPropertyEnumList +func names(ctx: JSContext; collection: HTMLCollection): JSPropertyEnumList {.jspropnames.} = let L = collection.length var list = newJSPropertyEnumList(ctx, L) @@ -1403,17 +1409,18 @@ func names(ctx: JSContext, collection: HTMLCollection): JSPropertyEnumList proc length(collection: HTMLAllCollection): uint32 {.jsfget.} = return uint32(collection.len) -func hasprop(collection: HTMLAllCollection, i: int): bool {.jshasprop.} = +func hasprop(collection: HTMLAllCollection; i: int): bool {.jshasprop.} = return i < collection.len -func item(collection: HTMLAllCollection, i: int): Element {.jsfunc.} = +func item(collection: HTMLAllCollection; i: int): Element {.jsfunc.} = if i < collection.len: return Element(collection.snapshot[i]) -func getter(collection: HTMLAllCollection, i: int): Option[Element] {.jsgetprop.} = +func getter(collection: HTMLAllCollection; i: int): Option[Element] + {.jsgetprop.} = return option(collection.item(i)) -func names(ctx: JSContext, collection: HTMLAllCollection): JSPropertyEnumList +func names(ctx: JSContext; collection: HTMLAllCollection): JSPropertyEnumList {.jspropnames.} = let L = collection.length var list = newJSPropertyEnumList(ctx, L) @@ -1458,7 +1465,7 @@ func url(location: Location): URL = return document.url return newURL("about:blank").get -proc setLocation*(document: Document, s: string): Err[JSError] +proc setLocation*(document: Document; s: string): Err[JSError] {.jsfset: "location".} = if document.location == nil: return err(newTypeError("document.location is not an object")) @@ -1476,16 +1483,16 @@ func `$`(location: Location): string {.jsuffunc.} = func href(location: Location): string {.jsuffget.} = return $location -proc setHref(location: Location, s: string): Err[JSError] +proc setHref(location: Location; s: string): Err[JSError] {.jsfset: "href".} = if location.document == nil: return ok() return location.document.setLocation(s) -proc assign(location: Location, s: string): Err[JSError] {.jsuffunc.} = +proc assign(location: Location; s: string): Err[JSError] {.jsuffunc.} = location.setHref(s) -proc replace(location: Location, s: string): Err[JSError] {.jsuffunc.} = +proc replace(location: Location; s: string): Err[JSError] {.jsuffunc.} = location.setHref(s) proc reload(location: Location) {.jsuffunc.} = @@ -1499,7 +1506,7 @@ func origin(location: Location): string {.jsuffget.} = func protocol(location: Location): string {.jsuffget.} = return location.url.protocol -proc protocol(location: Location, s: string): Err[DOMException] {.jsfset.} = +proc protocol(location: Location; s: string): Err[DOMException] {.jsfset.} = let document = location.document if document == nil: return @@ -1513,7 +1520,7 @@ proc protocol(location: Location, s: string): Err[DOMException] {.jsfset.} = func host(location: Location): string {.jsuffget.} = return location.url.host -proc setHost(location: Location, s: string) {.jsfset: "host".} = +proc setHost(location: Location; s: string) {.jsfset: "host".} = let document = location.document if document == nil: return @@ -1524,7 +1531,7 @@ proc setHost(location: Location, s: string) {.jsfset: "host".} = proc hostname(location: Location): string {.jsuffget.} = return location.url.hostname -proc setHostname(location: Location, s: string) {.jsfset: "hostname".} = +proc setHostname(location: Location; s: string) {.jsfset: "hostname".} = let document = location.document if document == nil: return @@ -1535,7 +1542,7 @@ proc setHostname(location: Location, s: string) {.jsfset: "hostname".} = proc port(location: Location): string {.jsuffget.} = return location.url.port -proc setPort(location: Location, s: string) {.jsfset: "port".} = +proc setPort(location: Location; s: string) {.jsfset: "port".} = let document = location.document if document == nil: return @@ -1546,7 +1553,7 @@ proc setPort(location: Location, s: string) {.jsfset: "port".} = proc pathname(location: Location): string {.jsuffget.} = return location.url.pathname -proc setPathname(location: Location, s: string) {.jsfset: "pathname".} = +proc setPathname(location: Location; s: string) {.jsfset: "pathname".} = let document = location.document if document == nil: return @@ -1557,7 +1564,7 @@ proc setPathname(location: Location, s: string) {.jsfset: "pathname".} = proc search(location: Location): string {.jsuffget.} = return location.url.search -proc setSearch(location: Location, s: string) {.jsfset: "search".} = +proc setSearch(location: Location; s: string) {.jsfset: "search".} = let document = location.document if document == nil: return @@ -1568,7 +1575,7 @@ proc setSearch(location: Location, s: string) {.jsfset: "search".} = proc hash(location: Location): string {.jsuffget.} = return location.url.hash -proc setHash(location: Location, s: string) {.jsfset: "hash".} = +proc setHash(location: Location; s: string) {.jsfset: "hash".} = let document = location.document if document == nil: return @@ -1599,13 +1606,13 @@ proc jsValue(attr: Attr): string {.jsfget: "value".} = func jsName(attr: Attr): string {.jsfget: "name".} = return attr.ownerElement.document.toStr(attr.data.qualifiedName) -func findAttr(map: NamedNodeMap, dataIdx: int): int = +func findAttr(map: NamedNodeMap; dataIdx: int): int = for i, attr in map.attrlist: if attr.dataIdx == dataIdx: return i return -1 -proc getAttr(map: NamedNodeMap, dataIdx: int): Attr = +proc getAttr(map: NamedNodeMap; dataIdx: int): Attr = let i = map.findAttr(dataIdx) if i != -1: return map.attrlist[i] @@ -1618,7 +1625,7 @@ proc getAttr(map: NamedNodeMap, dataIdx: int): Attr = map.attrlist.add(attr) return attr -func normalizeAttrQName(element: Element, qualifiedName: string): CAtom = +func normalizeAttrQName(element: Element; qualifiedName: string): CAtom = if element.namespace == Namespace.HTML and not element.document.isxml: return element.document.toAtom(qualifiedName.toLowerAscii()) return element.document.toAtom(qualifiedName) @@ -1639,41 +1646,43 @@ func attributes(element: Element): NamedNodeMap {.jsfget.} = )) return element.attributesInternal -func findAttr(element: Element, qualifiedName: string): int = +func findAttr(element: Element; qualifiedName: string): int = return element.findAttr(element.normalizeAttrQName(qualifiedName)) -func findAttrNS(element: Element, namespace, localName: string): int = +func findAttrNS(element: Element; namespace, localName: string): int = let namespace = element.document.toAtom(namespace) let localName = element.document.toAtom(localName) return element.findAttrNS(namespace, localName) -func hasAttribute(element: Element, qualifiedName: string): bool {.jsfunc.} = +func hasAttribute(element: Element; qualifiedName: string): bool {.jsfunc.} = return element.findAttr(qualifiedName) != -1 -func hasAttributeNS(element: Element, namespace, localName: string): bool {.jsfunc.} = +func hasAttributeNS(element: Element; namespace, localName: string): bool + {.jsfunc.} = return element.findAttrNS(namespace, localName) != -1 -func getAttribute(element: Element, qualifiedName: string): Option[string] {.jsfunc.} = +func getAttribute(element: Element; qualifiedName: string): Option[string] + {.jsfunc.} = let i = element.findAttr(qualifiedName) if i != -1: return some(element.attrs[i].value) return none(string) -func getAttributeNS(element: Element, namespace, localName: string): +func getAttributeNS(element: Element; namespace, localName: string): Option[string] {.jsfunc.} = let i = element.findAttrNS(namespace, localName) if i != -1: return some(element.attrs[i].value) return none(string) -proc getNamedItem(map: NamedNodeMap, qualifiedName: string): Option[Attr] +proc getNamedItem(map: NamedNodeMap; qualifiedName: string): Option[Attr] {.jsfunc.} = let i = map.element.findAttr(qualifiedName) if i != -1: return some(map.getAttr(i)) return none(Attr) -proc getNamedItemNS(map: NamedNodeMap, namespace, localName: string): +proc getNamedItemNS(map: NamedNodeMap; namespace, localName: string): Option[Attr] {.jsfunc.} = let i = map.element.findAttrNS(namespace, localName) if i != -1: @@ -1683,25 +1692,25 @@ proc getNamedItemNS(map: NamedNodeMap, namespace, localName: string): func length(map: NamedNodeMap): uint32 {.jsfget.} = return uint32(map.element.attrs.len) -proc item(map: NamedNodeMap, i: uint32): Option[Attr] {.jsfunc.} = +proc item(map: NamedNodeMap; i: uint32): Option[Attr] {.jsfunc.} = if int(i) < map.element.attrs.len: return some(map.getAttr(int(i))) return none(Attr) -func hasprop[T: uint32|string](map: NamedNodeMap, i: T): bool {.jshasprop.} = +func hasprop[T: uint32|string](map: NamedNodeMap; i: T): bool {.jshasprop.} = when T is uint32: return int(i) < map.element.attrs.len else: return map.getNamedItem(i).isSome -func getter[T: uint32|string](map: NamedNodeMap, i: T): Option[Attr] +func getter[T: uint32|string](map: NamedNodeMap; i: T): Option[Attr] {.jsgetprop.} = when T is uint32: return map.item(i) else: return map.getNamedItem(i) -func names(ctx: JSContext, map: NamedNodeMap): JSPropertyEnumList +func names(ctx: JSContext; map: NamedNodeMap): JSPropertyEnumList {.jspropnames.} = let len = if map.element.namespace == Namespace.HTML: uint32(map.attrlist.len + map.element.attrs.len) @@ -1798,7 +1807,7 @@ template toOA*(writeBuffer: DocumentWriteBuffer): openArray[char] = proc CDB_parseDocumentWriteChunk(wrapper: pointer) {.importc.} # https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps -proc write(document: Document, text: varargs[string]): Err[DOMException] +proc write(document: Document; text: varargs[string]): Err[DOMException] {.jsfunc.} = if document.isxml: return errDOMException("document.write not supported in XML documents", @@ -1819,7 +1828,7 @@ proc write(document: Document, text: varargs[string]): Err[DOMException] CDB_parseDocumentWriteChunk(document.parser) return ok() -func findFirst*(document: Document, tagType: TagType): HTMLElement = +func findFirst*(document: Document; tagType: TagType): HTMLElement = for element in document.elements(tagType): return HTMLElement(element) nil @@ -1839,17 +1848,17 @@ func select*(option: HTMLOptionElement): HTMLSelectElement = return HTMLSelectElement(anc) return nil -func countChildren(node: Node, nodeType: type): int = +func countChildren(node: Node; nodeType: type): int = for child in node.childList: if child of nodeType: inc result -func hasChild(node: Node, nodeType: type): bool = +func hasChild(node: Node; nodeType: type): bool = for child in node.childList: if child of nodeType: return true -func hasChildExcept(node: Node, nodeType: type, ex: Node): bool = +func hasChildExcept(node: Node; nodeType: type; ex: Node): bool = for child in node.childList: if child == ex: continue @@ -1869,7 +1878,7 @@ func nextSibling*(node: Node): Node {.jsfget.} = return nil return node.parentNode.childList[i] -func hasNextSibling(node: Node, nodeType: type): bool = +func hasNextSibling(node: Node; nodeType: type): bool = var node = node.nextSibling while node != nil: if node of nodeType: @@ -1877,7 +1886,7 @@ func hasNextSibling(node: Node, nodeType: type): bool = node = node.nextSibling return false -func hasPreviousSibling(node: Node, nodeType: type): bool = +func hasPreviousSibling(node: Node; nodeType: type): bool = var node = node.previousSibling while node != nil: if node of nodeType: @@ -1949,13 +1958,13 @@ func lastElementChild*(node: Node): Element {.jsfget.} = return child return nil -func findAncestor*(node: Node, tagTypes: set[TagType]): Element = +func findAncestor*(node: Node; tagTypes: set[TagType]): Element = for element in node.ancestors: if element.tagType in tagTypes: return element return nil -func getElementById(node: Node, id: string): Element {.jsfunc.} = +func getElementById(node: Node; id: string): Element {.jsfunc.} = if id.len == 0: return nil let id = node.document.toAtom(id) @@ -1964,7 +1973,7 @@ func getElementById(node: Node, id: string): Element {.jsfunc.} = return child return nil -func getElementsByTagName0(root: Node, tagName: string): HTMLCollection = +func getElementsByTagName0(root: Node; tagName: string): HTMLCollection = if tagName == "*": return newCollection[HTMLCollection]( root, @@ -1987,13 +1996,15 @@ func getElementsByTagName0(root: Node, tagName: string): HTMLCollection = childonly = false ) -func getElementsByTagName(document: Document, tagName: string): HTMLCollection {.jsfunc.} = +func getElementsByTagName(document: Document; tagName: string): HTMLCollection + {.jsfunc.} = return document.getElementsByTagName0(tagName) -func getElementsByTagName(element: Element, tagName: string): HTMLCollection {.jsfunc.} = +func getElementsByTagName(element: Element; tagName: string): HTMLCollection + {.jsfunc.} = return element.getElementsByTagName0(tagName) -func getElementsByClassName0(node: Node, classNames: string): HTMLCollection = +func getElementsByClassName0(node: Node; classNames: string): HTMLCollection = var classAtoms = newSeq[CAtom]() let document = node.document let isquirks = document.mode == QUIRKS @@ -2024,10 +2035,12 @@ func getElementsByClassName0(node: Node, classNames: string): HTMLCollection = childonly = false ) -func getElementsByClassName(document: Document, classNames: string): HTMLCollection {.jsfunc.} = +func getElementsByClassName(document: Document; classNames: string): + HTMLCollection {.jsfunc.} = return document.getElementsByClassName0(classNames) -func getElementsByClassName(element: Element, classNames: string): HTMLCollection {.jsfunc.} = +func getElementsByClassName(element: Element; classNames: string): + HTMLCollection {.jsfunc.} = return element.getElementsByClassName0(classNames) func previousElementSibling*(elem: Element): Element {.jsfget.} = @@ -2051,34 +2064,34 @@ func nextElementSibling*(elem: Element): Element {.jsfget.} = func documentElement(document: Document): Element {.jsfget.} = document.firstElementChild() -func attr*(element: Element, s: CAtom): string = +func attr*(element: Element; s: CAtom): string = let i = element.findAttr(s) if i != -1: return element.attrs[i].value return "" -func attr*(element: Element, s: StaticAtom): string = +func attr*(element: Element; s: StaticAtom): string = return element.attr(element.document.toAtom(s)) -func attrl*(element: Element, s: StaticAtom): Option[int32] = +func attrl*(element: Element; s: StaticAtom): Option[int32] = return parseInt32(element.attr(s)) -func attrulgz*(element: Element, s: StaticAtom): Option[uint32] = +func attrulgz*(element: Element; s: StaticAtom): Option[uint32] = let x = parseUInt32(element.attr(s), allowSign = true) if x.isSome and x.get > 0: return x return none(uint32) -func attrul*(element: Element, s: StaticAtom): Option[uint32] = +func attrul*(element: Element; s: StaticAtom): Option[uint32] = let x = parseUInt32(element.attr(s), allowSign = true) if x.isSome and x.get >= 0: return x return none(uint32) -func attrb*(element: Element, s: CAtom): bool = +func attrb*(element: Element; s: CAtom): bool = return element.findAttr(s) != -1 -func attrb*(element: Element, at: StaticAtom): bool = +func attrb*(element: Element; at: StaticAtom): bool = let atom = element.document.toAtom(at) return element.attrb(atom) @@ -2089,7 +2102,7 @@ func serializesAsVoid(element: Element): bool = func serializeFragment(node: Node): string -func serializeFragmentInner(child: Node, parentType: TagType): string = +func serializeFragmentInner(child: Node; parentType: TagType): string = result = "" if child of Element: let element = Element(child) @@ -2259,29 +2272,27 @@ func enctype*(element: Element): FormEncodingType = if element.isSubmitButton(): if element.attrb(satFormenctype): return case element.attr(satFormenctype).toLowerAscii() - of "application/x-www-form-urlencoded": FORM_ENCODING_TYPE_URLENCODED - of "multipart/form-data": FORM_ENCODING_TYPE_MULTIPART - of "text/plain": FORM_ENCODING_TYPE_TEXT_PLAIN - else: FORM_ENCODING_TYPE_URLENCODED - + of "application/x-www-form-urlencoded": fetUrlencoded + of "multipart/form-data": fetMultipart + of "text/plain": fetTextPlain + else: fetUrlencoded if element of HTMLInputElement: let element = HTMLInputElement(element) if element.form != nil: if element.form.attrb(satEnctype): return case element.attr(satEnctype).toLowerAscii() - of "application/x-www-form-urlencoded": FORM_ENCODING_TYPE_URLENCODED - of "multipart/form-data": FORM_ENCODING_TYPE_MULTIPART - of "text/plain": FORM_ENCODING_TYPE_TEXT_PLAIN - else: FORM_ENCODING_TYPE_URLENCODED - - return FORM_ENCODING_TYPE_URLENCODED + of "application/x-www-form-urlencoded": fetUrlencoded + of "multipart/form-data": fetMultipart + of "text/plain": fetTextPlain + else: fetUrlencoded + return fetUrlencoded func parseFormMethod(s: string): FormMethod = return case s.toLowerAscii() - of "get": FORM_METHOD_GET - of "post": FORM_METHOD_POST - of "dialog": FORM_METHOD_DIALOG - else: FORM_METHOD_GET + of "get": fmGet + of "post": fmPost + of "dialog": fmDialog + else: fmGet func formmethod*(element: Element): FormMethod = if element of HTMLFormElement: @@ -2289,20 +2300,17 @@ func formmethod*(element: Element): FormMethod = # on implicit form submission and other browsers seem to agree on this # behavior. return parseFormMethod(element.attr(satMethod)) - if element.isSubmitButton(): if element.attrb(satFormmethod): return parseFormMethod(element.attr(satFormmethod)) - if element of FormAssociatedElement: let element = FormAssociatedElement(element) if element.form != nil: if element.form.attrb(satMethod): return parseFormMethod(element.form.attr(satMethod)) + return fmGet - return FORM_METHOD_GET - -func findAnchor*(document: Document, id: string): Element = +func findAnchor*(document: Document; id: string): Element = if id.len == 0: return nil let id = document.toAtom(id) @@ -2324,7 +2332,7 @@ isDefaultPassive = func (eventTarget: EventTarget): bool = EventTarget(node.document.html) == eventTarget or EventTarget(node.document.body) == eventTarget -proc parseColor(element: Element, s: string): RGBAColor = +proc parseColor(element: Element; s: string): RGBAColor = let cval = parseComponentValue(newStringStream(s)) #TODO return element style # For now we just use white. @@ -2369,26 +2377,26 @@ func href(base: HTMLBaseElement): string {.jsfget.} = func href*(anchor: HTMLAnchorElement): string {.jsfget.} = anchor.href0 -proc href(anchor: HTMLAnchorElement, href: string) {.jsfset.} = +proc href(anchor: HTMLAnchorElement; href: string) {.jsfset.} = anchor.attr(satHref, href) func `$`(anchor: HTMLAnchorElement): string {.jsfunc.} = anchor.href -proc setRelList(anchor: HTMLAnchorElement, s: string) {.jsfset: "relList".} = +proc setRelList(anchor: HTMLAnchorElement; s: string) {.jsfset: "relList".} = anchor.attr(satRel, s) # <area> func href(area: HTMLAreaElement): string {.jsfget.} = area.href0 -proc href(area: HTMLAreaElement, href: string) {.jsfset.} = +proc href(area: HTMLAreaElement; href: string) {.jsfset.} = area.attr(satHref, href) func `$`(area: HTMLAreaElement): string {.jsfunc.} = area.href -proc setRelList(area: HTMLAreaElement, s: string) {.jsfset: "relList".} = +proc setRelList(area: HTMLAreaElement; s: string) {.jsfset: "relList".} = area.attr(satRel, s) # <label> @@ -2412,11 +2420,11 @@ func form(label: HTMLLabelElement): HTMLFormElement {.jsfget.} = return control.form # <link> -proc setRelList(link: HTMLLinkElement, s: string) {.jsfset: "relList".} = +proc setRelList(link: HTMLLinkElement; s: string) {.jsfset: "relList".} = link.attr(satRel, s) # <form> -proc setRelList(form: HTMLFormElement, s: string) {.jsfset: "relList".} = +proc setRelList(form: HTMLFormElement; s: string) {.jsfset: "relList".} = form.attr(satRel, s) # <input> @@ -2445,25 +2453,25 @@ func getSrc*(this: HTMLVideoElement|HTMLAudioElement): string = break src -func newText(document: Document, data: string): Text = +func newText(document: Document; data: string): Text = return Text( document_internal: document, data: data, index: -1 ) -func newText(ctx: JSContext, data = ""): Text {.jsctor.} = +func newText(ctx: JSContext; data = ""): Text {.jsctor.} = let window = ctx.getGlobalOpaque(Window).get return window.document.newText(data) -func newCDATASection(document: Document, data: string): CDATASection = +func newCDATASection(document: Document; data: string): CDATASection = return CDATASection( document_internal: document, data: data, index: -1 ) -func newProcessingInstruction(document: Document, target, data: string): +func newProcessingInstruction(document: Document; target, data: string): ProcessingInstruction = return ProcessingInstruction( document_internal: document, @@ -2482,20 +2490,20 @@ func newDocumentFragment(ctx: JSContext): DocumentFragment {.jsctor.} = let window = ctx.getGlobalOpaque(Window).get return window.document.newDocumentFragment() -func newComment(document: Document, data: string): Comment = +func newComment(document: Document; data: string): Comment = return Comment( document_internal: document, data: data, index: -1 ) -func newComment(ctx: JSContext, data: string = ""): Comment {.jsctor.} = +func newComment(ctx: JSContext; data: string = ""): Comment {.jsctor.} = let window = ctx.getGlobalOpaque(Window).get return window.document.newComment(data) #TODO custom elements -proc newHTMLElement*(document: Document, localName: CAtom, - namespace = Namespace.HTML, prefix = NO_PREFIX, +proc newHTMLElement*(document: Document; localName: CAtom; + namespace = Namespace.HTML; prefix = NO_PREFIX; attrs = newSeq[AttrData]()): HTMLElement = let tagType = document.toTagType(localName) case tagType @@ -2582,8 +2590,8 @@ proc newHTMLElement*(document: Document, localName: CAtom, result.dataset = DOMStringMap(target: result) result.attrs = attrs -proc newHTMLElement*(document: Document, tagType: TagType, - namespace = Namespace.HTML, prefix = NO_PREFIX, +proc newHTMLElement*(document: Document; tagType: TagType; + namespace = Namespace.HTML; prefix = NO_PREFIX; attrs = newSeq[AttrData]()): HTMLElement = let localName = document.toAtom(tagType) return document.newHTMLElement(localName, namespace, prefix, attrs) @@ -2610,7 +2618,7 @@ func newDocument(ctx: JSContext): Document {.jsctor.} = let factory = if window != nil: window.factory else: newCAtomFactory() return newDocument(factory) -func newDocumentType*(document: Document, name, publicId, systemId: string): +func newDocumentType*(document: Document; name, publicId, systemId: string): DocumentType = return DocumentType( document_internal: document, @@ -2649,7 +2657,7 @@ func baseURL*(document: Document): URL = func baseURI(node: Node): string {.jsfget.} = return $node.document.baseURL -func parseURL*(document: Document, s: string): Option[URL] = +func parseURL*(document: Document; s: string): Option[URL] = #TODO encodings return parseURL(s, some(document.baseURL)) @@ -2686,7 +2694,7 @@ proc invalidateCollections(node: Node) = for id in node.liveCollections: node.document.invalidCollections.incl(id) -proc delAttr(element: Element, i: int, keep = false) = +proc delAttr(element: Element; i: int; keep = false) = let map = element.attributesInternal let name = element.attrs[i].qualifiedName element.attrs.delete(i) # ordering matters @@ -2713,7 +2721,7 @@ proc delAttr(element: Element, i: int, keep = false) = element.invalidateCollections() element.invalid = true -proc newCSSStyleDeclaration(element: Element, value: string): +proc newCSSStyleDeclaration(element: Element; value: string): CSSStyleDeclaration = let inline_rules = newStringStream(value).parseListOfDeclarations2() var decls: seq[CSSDeclaration] @@ -2729,19 +2737,19 @@ proc cssText(this: CSSStyleDeclaration): string {.jsfunc.} = func length(this: CSSStyleDeclaration): uint32 = return uint32(this.decls.len) -func item(this: CSSStyleDeclaration, u: uint32): Option[string] = +func item(this: CSSStyleDeclaration; u: uint32): Option[string] = if u < this.length: return some(this.decls[int(u)].name) return none(string) -proc getPropertyValue(this: CSSStyleDeclaration, s: string): string = +proc getPropertyValue(this: CSSStyleDeclaration; s: string): string = for decl in this.decls: if decl.name == s: return $decl.value return "" # https://drafts.csswg.org/cssom/#idl-attribute-to-css-property -func IDLAttributeToCSSProperty(s: string, dashPrefix = false): string = +func IDLAttributeToCSSProperty(s: string; dashPrefix = false): string = result = if dashPrefix: "-" else: "" for c in s: if c in AsciiUpperAlpha: @@ -2750,7 +2758,7 @@ func IDLAttributeToCSSProperty(s: string, dashPrefix = false): string = else: result &= c -proc getter[T: uint32|string](this: CSSStyleDeclaration, u: T): +proc getter[T: uint32|string](this: CSSStyleDeclaration; u: T): Option[string] {.jsgetprop.} = when T is uint32: return this.item(u) @@ -2768,12 +2776,12 @@ proc style*(element: Element): CSSStyleDeclaration {.jsfget.} = return element.style_cached # Forward declaration hack -var appliesFwdDecl*: proc(mqlist: MediaQueryList, window: Window): bool +var appliesFwdDecl*: proc(mqlist: MediaQueryList; window: Window): bool {.nimcall, noSideEffect.} # see https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet #TODO make this somewhat compliant with ^this -proc loadResource(window: Window, link: HTMLLinkElement) = +proc loadResource(window: Window; link: HTMLLinkElement) = if satStylesheet notin link.relList: return if link.fetchStarted: @@ -2810,7 +2818,7 @@ proc loadResource(window: Window, link: HTMLLinkElement) = ) window.loadingResourcePromises.add(p) -proc loadResource(window: Window, image: HTMLImageElement) = +proc loadResource(window: Window; image: HTMLImageElement) = if not window.images or image.fetchStarted: return image.fetchStarted = true @@ -2861,30 +2869,30 @@ proc reflectEvent(element: Element; target: EventTarget; name: StaticAtom; proc reflectAttrs(element: Element; name: CAtom; value: string) = let name = element.document.toStaticAtom(name) - template reflect_str(element: Element, n: StaticAtom, val: untyped) = + template reflect_str(element: Element; n: StaticAtom; val: untyped) = if name == n: element.val = value return - template reflect_atom(element: Element, n: StaticAtom, val: untyped) = + template reflect_atom(element: Element; n: StaticAtom; val: untyped) = if name == n: element.val = element.document.toAtom(value) return - template reflect_str(element: Element, n: StaticAtom, val, fun: untyped) = + template reflect_str(element: Element; n: StaticAtom; val, fun: untyped) = if name == n: element.val = fun(value) return - template reflect_bool(element: Element, n: StaticAtom, val: untyped) = + template reflect_bool(element: Element; n: StaticAtom; val: untyped) = if name == n: element.val = true return - template reflect_domtoklist0(element: Element, val: untyped) = + template reflect_domtoklist0(element: Element; val: untyped) = element.val.toks.setLen(0) for x in value.split(AsciiWhitespace): if x != "": let a = element.document.toAtom(x) if a notin element.val: element.val.toks.add(a) - template reflect_domtoklist(element: Element, n: StaticAtom, val: untyped) = + template reflect_domtoklist(element: Element; n: StaticAtom; val: untyped) = if name == n: element.reflect_domtoklist0 val return @@ -2953,7 +2961,7 @@ proc reflectAttrs(element: Element; name: CAtom; value: string) = window.loadResource(image) else: discard -proc attr*(element: Element, name: CAtom, value: string) = +proc attr*(element: Element; name: CAtom; value: string) = let i = element.findAttr(name) if i != -1: element.attrs[i].value = value @@ -2968,11 +2976,11 @@ proc attr*(element: Element, name: CAtom, value: string) = )) element.reflectAttrs(name, value) -proc attr*(element: Element, name: StaticAtom, value: string) = +proc attr*(element: Element; name: StaticAtom; value: string) = element.attr(element.document.toAtom(name), value) -proc attrns*(element: Element, localName: CAtom, prefix: NamespacePrefix, - namespace: Namespace, value: sink string) = +proc attrns*(element: Element; localName: CAtom; prefix: NamespacePrefix; + namespace: Namespace; value: sink string) = if prefix == NO_PREFIX and namespace == NO_NAMESPACE: element.attr(localName, value) return @@ -3002,17 +3010,17 @@ proc attrns*(element: Element, localName: CAtom, prefix: NamespacePrefix, )) element.reflectAttrs(qualifiedName, value) -proc attrl(element: Element, name: StaticAtom, value: int32) = +proc attrl(element: Element; name: StaticAtom; value: int32) = element.attr(name, $value) -proc attrul(element: Element, name: StaticAtom, value: uint32) = +proc attrul(element: Element; name: StaticAtom; value: uint32) = element.attr(name, $value) -proc attrulgz(element: Element, name: StaticAtom, value: uint32) = +proc attrulgz(element: Element; name: StaticAtom; value: uint32) = if value > 0: element.attrul(name, value) -proc setAttribute(element: Element, qualifiedName, value: string): +proc setAttribute(element: Element; qualifiedName, value: string): Err[DOMException] {.jsfunc.} = ?validateAttributeName(qualifiedName) let qualifiedName = if element.namespace == Namespace.HTML and @@ -3023,7 +3031,7 @@ proc setAttribute(element: Element, qualifiedName, value: string): element.attr(qualifiedName, value) return ok() -proc setAttributeNS(element: Element, namespace, qualifiedName, +proc setAttributeNS(element: Element; namespace, qualifiedName, value: string): Err[DOMException] {.jsfunc.} = ?validateAttributeQName(qualifiedName) let ps = qualifiedName.until(':') @@ -3032,8 +3040,10 @@ proc setAttributeNS(element: Element, namespace, qualifiedName, #TODO atomize here if prefix != "" and namespace == "" or prefix == "xml" and namespace != $Namespace.XML or - (qualifiedName == "xmlns" or prefix == "xmlns") and namespace != $Namespace.XMLNS or - namespace == $Namespace.XMLNS and qualifiedName != "xmlns" and prefix != "xmlns": + (qualifiedName == "xmlns" or prefix == "xmlns") and + namespace != $Namespace.XMLNS or + namespace == $Namespace.XMLNS and qualifiedName != "xmlns" and + prefix != "xmlns": return errDOMException("Unexpected namespace", "NamespaceError") let qualifiedName = element.document.toAtom(qualifiedName) let namespace = element.document.toAtom(namespace) @@ -3049,17 +3059,18 @@ proc setAttributeNS(element: Element, namespace, qualifiedName, )) return ok() -proc removeAttribute(element: Element, qualifiedName: string) {.jsfunc.} = +proc removeAttribute(element: Element; qualifiedName: string) {.jsfunc.} = let i = element.findAttr(qualifiedName) if i != -1: element.delAttr(i) -proc removeAttributeNS(element: Element, namespace, localName: string) {.jsfunc.} = +proc removeAttributeNS(element: Element; namespace, localName: string) + {.jsfunc.} = let i = element.findAttrNS(namespace, localName) if i != -1: element.delAttr(i) -proc toggleAttribute(element: Element, qualifiedName: string, +proc toggleAttribute(element: Element; qualifiedName: string; force = none(bool)): DOMResult[bool] {.jsfunc.} = ?validateAttributeName(qualifiedName) let qualifiedName = element.normalizeAttrQName(qualifiedName) @@ -3075,10 +3086,10 @@ proc toggleAttribute(element: Element, qualifiedName: string, return ok(false) return ok(true) -proc value(attr: Attr, s: string) {.jsfset.} = +proc value(attr: Attr; s: string) {.jsfset.} = attr.ownerElement.attr(attr.data.qualifiedName, s) -proc setNamedItem(map: NamedNodeMap, attr: Attr): DOMResult[Attr] +proc setNamedItem(map: NamedNodeMap; attr: Attr): DOMResult[Attr] {.jsfunc.} = if attr.ownerElement == map.element: # Setting attr on its owner element does nothing, since the "get an @@ -3096,11 +3107,11 @@ proc setNamedItem(map: NamedNodeMap, attr: Attr): DOMResult[Attr] map.element.attrs.add(attr.data) return ok(nil) -proc setNamedItemNS(map: NamedNodeMap, attr: Attr): DOMResult[Attr] +proc setNamedItemNS(map: NamedNodeMap; attr: Attr): DOMResult[Attr] {.jsfunc.} = return map.setNamedItem(attr) -proc removeNamedItem(map: NamedNodeMap, qualifiedName: string): +proc removeNamedItem(map: NamedNodeMap; qualifiedName: string): DOMResult[Attr] {.jsfunc.} = let i = map.element.findAttr(qualifiedName) if i != -1: @@ -3109,7 +3120,7 @@ proc removeNamedItem(map: NamedNodeMap, qualifiedName: string): return ok(attr) return errDOMException("Item not found", "NotFoundError") -proc removeNamedItemNS(map: NamedNodeMap, namespace, localName: string): +proc removeNamedItemNS(map: NamedNodeMap; namespace, localName: string): DOMResult[Attr] {.jsfunc.} = let i = map.element.findAttrNS(namespace, localName) if i != -1: @@ -3118,11 +3129,11 @@ proc removeNamedItemNS(map: NamedNodeMap, namespace, localName: string): return ok(attr) return errDOMException("Item not found", "NotFoundError") -proc jsId(element: Element, id: string) {.jsfset: "id".} = +proc jsId(element: Element; id: string) {.jsfset: "id".} = element.attr(satId, id) # Pass an index to avoid searching for the node in parent's child list. -proc remove*(node: Node, suppressObservers: bool) = +proc remove*(node: Node; suppressObservers: bool) = let parent = node.parentNode assert parent != nil assert node.index != -1 @@ -3140,13 +3151,14 @@ proc remove*(node: Node, suppressObservers: bool) = node of HTMLLinkElement): node.document.cachedSheetsInvalid = true - #TODO assigned, shadow root, shadow root again, custom nodes, registered observers + #TODO assigned, shadow root, shadow root again, custom nodes, registered + # observers #TODO not suppress observers => queue tree mutation record proc remove*(node: Node) {.jsfunc.} = node.remove(suppressObservers = false) -proc adopt(document: Document, node: Node) = +proc adopt(document: Document; node: Node) = let oldDocument = node.document if node.parentNode != nil: remove(node) @@ -3200,7 +3212,7 @@ proc resetElement*(element: Element) = textarea.invalid = true else: discard -proc setForm*(element: FormAssociatedElement, form: HTMLFormElement) = +proc setForm*(element: FormAssociatedElement; form: HTMLFormElement) = case element.tagType of TAG_INPUT: let input = HTMLInputElement(element) @@ -3460,10 +3472,10 @@ proc replaceAll(parent, node: Node) = parent.append(node) #TODO tree mutation record -proc createTextNode*(document: Document, data: string): Text {.jsfunc.} = +proc createTextNode*(document: Document; data: string): Text {.jsfunc.} = return newText(document, data) -proc textContent*(node: Node, data: Option[string]) {.jsfset.} = +proc textContent*(node: Node; data: Option[string]) {.jsfset.} = if node of Element or node of DocumentFragment: let x = if data.isSome: node.document.createTextNode(data.get) @@ -3495,15 +3507,15 @@ proc blockRendering*(element: Element) = if document.contentType == "text/html" and document.body == nil: element.document.renderBlockingElements.add(element) -proc markAsReady(element: HTMLScriptElement, res: ScriptResult) = +proc markAsReady(element: HTMLScriptElement; res: ScriptResult) = element.scriptResult = res if element.onReady != nil: element.onReady() element.onReady = nil element.delayingTheLoadEvent = false -proc createClassicScript(ctx: JSContext, source: string, baseURL: URL, - options: ScriptOptions, mutedErrors = false): Script = +proc createClassicScript(ctx: JSContext; source: string; baseURL: URL; + options: ScriptOptions; mutedErrors = false): Script = let urls = baseURL.serialize(excludepassword = true) let record = compileScript(ctx, source, cstring(urls)) return Script( @@ -3515,8 +3527,8 @@ proc createClassicScript(ctx: JSContext, source: string, baseURL: URL, type OnCompleteProc = proc(element: HTMLScriptElement, res: ScriptResult) -proc fetchClassicScript(element: HTMLScriptElement, url: URL, - options: ScriptOptions, cors: CORSAttribute, cs: Charset, +proc fetchClassicScript(element: HTMLScriptElement; url: URL; + options: ScriptOptions; cors: CORSAttribute; cs: Charset, onComplete: OnCompleteProc) = let window = element.document.window if not element.scriptingEnabled or window.loader.isNone: @@ -3538,15 +3550,15 @@ proc fetchClassicScript(element: HTMLScriptElement, url: URL, element.onComplete(ScriptResult(t: RESULT_SCRIPT, script: script)) #TODO settings object -proc fetchDescendantsAndLink(element: HTMLScriptElement, script: Script, - destination: RequestDestination, onComplete: OnCompleteProc) -proc fetchSingleModule(element: HTMLScriptElement, url: URL, - destination: RequestDestination, options: ScriptOptions, - referrer: URL, isTopLevel: bool, onComplete: OnCompleteProc) +proc fetchDescendantsAndLink(element: HTMLScriptElement; script: Script; + destination: RequestDestination; onComplete: OnCompleteProc) +proc fetchSingleModule(element: HTMLScriptElement; url: URL; + destination: RequestDestination; options: ScriptOptions; + referrer: URL; isTopLevel: bool; onComplete: OnCompleteProc) #TODO settings object -proc fetchExternalModuleGraph(element: HTMLScriptElement, url: URL, - options: ScriptOptions, onComplete: OnCompleteProc) = +proc fetchExternalModuleGraph(element: HTMLScriptElement; url: URL; + options: ScriptOptions; onComplete: OnCompleteProc) = let window = element.document.window if not element.scriptingEnabled or window.loader.isNone: element.onComplete(ScriptResult(t: RESULT_NULL)) @@ -3558,7 +3570,7 @@ proc fetchExternalModuleGraph(element: HTMLScriptElement, url: URL, options, parseURL("about:client").get, isTopLevel = true, - onComplete = proc(element: HTMLScriptElement, res: ScriptResult) = + onComplete = proc(element: HTMLScriptElement; res: ScriptResult) = if res.t == RESULT_NULL: element.onComplete(res) else: @@ -3566,14 +3578,14 @@ proc fetchExternalModuleGraph(element: HTMLScriptElement, url: URL, onComplete) ) -proc fetchDescendantsAndLink(element: HTMLScriptElement, script: Script, - destination: RequestDestination, onComplete: OnCompleteProc) = +proc fetchDescendantsAndLink(element: HTMLScriptElement; script: Script; + destination: RequestDestination; onComplete: OnCompleteProc) = discard #TODO settings object -proc fetchSingleModule(element: HTMLScriptElement, url: URL, - destination: RequestDestination, options: ScriptOptions, - referrer: URL, isTopLevel: bool, onComplete: OnCompleteProc) = +proc fetchSingleModule(element: HTMLScriptElement; url: URL; + destination: RequestDestination; options: ScriptOptions, + referrer: URL; isTopLevel: bool; onComplete: OnCompleteProc) = let moduleType = "javascript" #TODO moduleRequest let settings = element.document.window.settings @@ -3672,7 +3684,8 @@ proc prepare*(element: HTMLScriptElement) = element.forceAsync = false element.alreadyStarted = true element.preparationTimeDocument = element.document - if parserDocument != nil and parserDocument != element.preparationTimeDocument: + if parserDocument != nil and + parserDocument != element.preparationTimeDocument: return if not element.scriptingEnabled: return @@ -3685,15 +3698,20 @@ proc prepare*(element: HTMLScriptElement) = let event = element.attr(satEvent).strip(chars = AsciiWhitespace) if not f.equalsIgnoreCase("window"): return - if not event.equalsIgnoreCase("onload") and not event.equalsIgnoreCase("onload()"): + if not event.equalsIgnoreCase("onload") and + not event.equalsIgnoreCase("onload()"): return let cs = getCharset(element.attr(satCharset)) let encoding = if cs != CHARSET_UNKNOWN: cs else: element.document.charset let classicCORS = element.crossOrigin + let parserMetadata = if element.parserDocument != nil: + pmParserInserted + else: + pmNotParserInserted var options = ScriptOptions( nonce: element.internalNonce, integrity: element.attr(satIntegrity), - parserMetadata: if element.parserDocument != nil: PARSER_INSERTED else: NOT_PARSER_INSERTED, + parserMetadata: parserMetadata, referrerpolicy: element.referrerpolicy ) #TODO settings object @@ -3742,7 +3760,8 @@ proc prepare*(element: HTMLScriptElement) = elif element.parserDocument == nil: prepdoc.scriptsToExecInOrder.addFirst(element) element.onReady = (proc() = - if prepdoc.scriptsToExecInOrder.len > 0 and prepdoc.scriptsToExecInOrder[0] != element: + if prepdoc.scriptsToExecInOrder.len > 0 and + prepdoc.scriptsToExecInOrder[0] != element: while prepdoc.scriptsToExecInOrder.len > 0: let script = prepdoc.scriptsToExecInOrder[0] if script.scriptResult == nil: @@ -3768,7 +3787,7 @@ proc prepare*(element: HTMLScriptElement) = element.execute() #TODO options/custom elements -proc createElement(document: Document, localName: string): +proc createElement(document: Document; localName: string): DOMResult[Element] {.jsfunc.} = if not localName.matchNameProduction(): return errDOMException("Invalid character in element name", @@ -3777,7 +3796,8 @@ proc createElement(document: Document, localName: string): document.toAtom(localName.toLowerAscii()) else: document.toAtom(localName) - let namespace = if not document.isxml: #TODO or content type is application/xhtml+xml + let namespace = if not document.isxml: + #TODO or content type is application/xhtml+xml Namespace.HTML else: NO_NAMESPACE @@ -3788,7 +3808,7 @@ proc createElement(document: Document, localName: string): proc createDocumentFragment(document: Document): DocumentFragment {.jsfunc.} = return newDocumentFragment(document) -proc createDocumentType(implementation: ptr DOMImplementation, qualifiedName, +proc createDocumentType(implementation: ptr DOMImplementation; qualifiedName, publicId, systemId: string): DOMResult[DocumentType] {.jsfunc.} = if not qualifiedName.matchQNameProduction(): return errDOMException("Invalid character in document type name", @@ -3796,7 +3816,7 @@ proc createDocumentType(implementation: ptr DOMImplementation, qualifiedName, let document = implementation.document return ok(document.newDocumentType(qualifiedName, publicId, systemId)) -proc createHTMLDocument(ctx: JSContext, implementation: ptr DOMImplementation, +proc createHTMLDocument(ctx: JSContext; implementation: ptr DOMImplementation; title = none(string)): Document {.jsfunc.} = let doc = newDocument(ctx) doc.contentType = "text/html" @@ -3816,7 +3836,7 @@ proc createHTMLDocument(ctx: JSContext, implementation: ptr DOMImplementation, proc hasFeature(implementation: ptr DOMImplementation): bool {.jsfunc.} = return true -proc createCDATASection(document: Document, data: string): +proc createCDATASection(document: Document; data: string): DOMResult[CDATASection] {.jsfunc.} = if not document.isxml: return errDOMException("CDATA sections are not supported in HTML", @@ -3826,17 +3846,17 @@ proc createCDATASection(document: Document, data: string): "InvalidCharacterError") return ok(newCDATASection(document, data)) -proc createComment*(document: Document, data: string): Comment {.jsfunc.} = +proc createComment*(document: Document; data: string): Comment {.jsfunc.} = return newComment(document, data) -proc createProcessingInstruction(document: Document, target, data: string): +proc createProcessingInstruction(document: Document; target, data: string): DOMResult[ProcessingInstruction] {.jsfunc.} = if not target.matchNameProduction() or "?>" in data: return errDOMException("Invalid data for processing instruction", "InvalidCharacterError") return ok(newProcessingInstruction(document, target, data)) -proc clone(node: Node, document = none(Document), deep = false): Node = +proc clone(node: Node; document = none(Document), deep = false): Node = let document = document.get(node.document) let copy = if node of Element: #TODO is value @@ -3911,18 +3931,18 @@ proc clone(node: Node, document = none(Document), deep = false): Node = copy.append(child.clone(deep = true)) return copy -proc cloneNode(node: Node, deep = false): Node {.jsfunc.} = +proc cloneNode(node: Node; deep = false): Node {.jsfunc.} = #TODO shadow root return node.clone(deep = deep) # Forward definition hack (these are set in selectors.nim) -var doqsa*: proc (node: Node, q: string): seq[Element] -var doqs*: proc (node: Node, q: string): Element +var doqsa*: proc (node: Node; q: string): seq[Element] +var doqs*: proc (node: Node; q: string): Element -proc querySelectorAll*(node: Node, q: string): seq[Element] {.jsfunc.} = +proc querySelectorAll*(node: Node; q: string): seq[Element] {.jsfunc.} = return doqsa(node, q) -proc querySelector*(node: Node, q: string): Element {.jsfunc.} = +proc querySelector*(node: Node; q: string): Element {.jsfunc.} = return doqs(node, q) const (ReflectTable, TagReflectMap, ReflectAllStartIndex) = (func(): ( @@ -3949,11 +3969,13 @@ const (ReflectTable, TagReflectMap, ReflectAllStartIndex) = (func(): ( inc i )() -proc jsReflectGet(ctx: JSContext, this: JSValue, magic: cint): JSValue {.cdecl.} = +proc jsReflectGet(ctx: JSContext; this: JSValue; magic: cint): JSValue + {.cdecl.} = let entry = ReflectTable[uint16(magic)] let op = getOpaque0(this) if unlikely(not ctx.isInstanceOf(this, "Element") or op == nil): - return JS_ThrowTypeError(ctx, "Reflected getter called on a value that is not an element") + return JS_ThrowTypeError(ctx, + "Reflected getter called on a value that is not an element") let element = cast[Element](op) if element.tagType notin entry.tags: return JS_ThrowTypeError(ctx, "Invalid tag type %s", element.tagType) @@ -3970,9 +3992,11 @@ proc jsReflectGet(ctx: JSContext, this: JSValue, magic: cint): JSValue {.cdecl.} of REFLECT_ULONG_GZ: return toJS(ctx, element.attrulgz(entry.attrname).get(entry.u)) -proc jsReflectSet(ctx: JSContext, this, val: JSValue, magic: cint): JSValue {.cdecl.} = +proc jsReflectSet(ctx: JSContext; this, val: JSValue; magic: cint): JSValue + {.cdecl.} = if unlikely(not ctx.isInstanceOf(this, "Element")): - return JS_ThrowTypeError(ctx, "Reflected getter called on a value that is not an element") + return JS_ThrowTypeError(ctx, + "Reflected getter called on a value that is not an element") let entry = ReflectTable[uint16(magic)] let op = getOpaque0(this) assert op != nil @@ -4020,14 +4044,20 @@ func getReflectFunctions(tags: set[TagType]): seq[TabGetSet] = return result func getElementReflectFunctions(): seq[TabGetSet] = + result = @[] var i: int16 = ReflectAllStartIndex while i < int16(ReflectTable.len): let entry = ReflectTable[i] assert entry.tags == AllTagTypes - result.add(TabGetSet(name: ReflectTable[i].funcname, get: jsReflectGet, set: jsReflectSet, magic: i)) + result.add(TabGetSet( + name: ReflectTable[i].funcname, + get: jsReflectGet, + set: jsReflectSet, + magic: i + )) inc i -proc getContext*(jctx: JSContext, this: HTMLCanvasElement, contextId: string, +proc getContext*(jctx: JSContext; this: HTMLCanvasElement; contextId: string; options = none(JSValue)): RenderingContext {.jsfunc.} = if contextId == "2d": if this.ctx2d != nil: @@ -4036,7 +4066,7 @@ proc getContext*(jctx: JSContext, this: HTMLCanvasElement, contextId: string, return nil #TODO quality should be `any' -proc toBlob(ctx: JSContext, this: HTMLCanvasElement, callback: JSValue, +proc toBlob(ctx: JSContext; this: HTMLCanvasElement; callback: JSValue; s = "image/png", quality: float64 = 1): JSValue {.jsfunc.} = var outlen: int let buf = this.bitmap.toPNG(outlen) @@ -4059,7 +4089,7 @@ proc fragmentParsingAlgorithm*(element: Element; s: string): DocumentFragment = fragment.append(child) return fragment -proc innerHTML(element: Element, s: string) {.jsfset.} = +proc innerHTML(element: Element; s: string) {.jsfset.} = #TODO shadow root let fragment = fragmentParsingAlgorithm(element, s) let ctx = if element of HTMLTemplateElement: @@ -4068,7 +4098,7 @@ proc innerHTML(element: Element, s: string) {.jsfset.} = element ctx.replaceAll(fragment) -proc outerHTML(element: Element, s: string): Err[DOMException] {.jsfset.} = +proc outerHTML(element: Element; s: string): Err[DOMException] {.jsfset.} = let parent0 = element.parentNode if parent0 == nil: return ok() @@ -4098,7 +4128,7 @@ func parseInsertAdjacentPosition(s: string): DOMResult[InsertAdjacentPosition] = return errDOMException("Invalid position", "SyntaxError") # https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml -proc insertAdjacentHTML(element: Element, position, text: string): +proc insertAdjacentHTML(element: Element; position, text: string): Err[DOMException] {.jsfunc.} = let position = ?parseInsertAdjacentPosition(position) let ctx0 = case position @@ -4126,16 +4156,16 @@ proc insertAdjacentHTML(element: Element, position, text: string): of iapAfterEnd: ctx.parentNode.insert(fragment, ctx.nextSibling) -proc registerElements(ctx: JSContext, nodeCID: JSClassID) = +proc registerElements(ctx: JSContext; nodeCID: JSClassID) = let elementCID = ctx.registerType(Element, parent = nodeCID) const extra_getset = getElementReflectFunctions() let htmlElementCID = ctx.registerType(HTMLElement, parent = elementCID, has_extra_getset = true, extra_getset = extra_getset) - template register(t: typed, tags: set[TagType]) = + template register(t: typed; tags: set[TagType]) = const extra_getset = getReflectFunctions(tags) ctx.registerType(t, parent = htmlElementCID, has_extra_getset = true, extra_getset = extra_getset) - template register(t: typed, tag: TagType) = + template register(t: typed; tag: TagType) = register(t, {tag}) register(HTMLInputElement, TAG_INPUT) register(HTMLAnchorElement, TAG_A) diff --git a/src/html/env.nim b/src/html/env.nim index 14a12edd..2d5743ed 100644 --- a/src/html/env.nim +++ b/src/html/env.nim @@ -44,7 +44,8 @@ proc oscpu(navigator: ptr Navigator): string {.jsfget.} = "Windows NT 10.0" # NavigatorLanguage proc language(navigator: ptr Navigator): string {.jsfget.} = "en-US" -proc languages(navigator: ptr Navigator): seq[string] {.jsfget.} = @["en-US"] #TODO frozen array? +proc languages(navigator: ptr Navigator): seq[string] {.jsfget.} = + @["en-US"] #TODO frozen array? # NavigatorOnline proc onLine(navigator: ptr Navigator): bool {.jsfget.} = @@ -66,8 +67,12 @@ proc item(pluginArray: ptr PluginArray): JSValue {.jsfunc.} = JS_NULL proc length(pluginArray: ptr PluginArray): uint32 {.jsfget.} = 0 proc item(mimeTypeArray: ptr MimeTypeArray): JSValue {.jsfunc.} = JS_NULL proc length(mimeTypeArray: ptr MimeTypeArray): uint32 {.jsfget.} = 0 -proc getter(pluginArray: ptr PluginArray, i: int): Option[JSValue] {.jsgetprop.} = discard -proc getter(mimeTypeArray: ptr MimeTypeArray, i: int): Option[JSValue] {.jsgetprop.} = discard +proc getter(pluginArray: ptr PluginArray; i: int): Option[JSValue] + {.jsgetprop.} = + discard +proc getter(mimeTypeArray: ptr MimeTypeArray; i: int): Option[JSValue] + {.jsgetprop.} = + discard # Screen proc availWidth(screen: ptr Screen): int64 {.jsfget.} = @@ -91,24 +96,24 @@ proc addNavigatorModule(ctx: JSContext) = ctx.registerType(MimeTypeArray) ctx.registerType(Screen) -proc fetch[T: Request|string](window: Window, req: T, init = none(RequestInit)): +proc fetch[T: Request|string](window: Window; req: T; init = none(RequestInit)): JSResult[FetchPromise] {.jsfunc.} = if window.loader.isSome: let req = ?newRequest(window.jsctx, req, init) return ok(window.loader.get.fetch(req)) -proc setTimeout[T: JSValue|string](window: Window, handler: T, +proc setTimeout[T: JSValue|string](window: Window; handler: T; timeout = 0i32): int32 {.jsfunc.} = return window.timeouts.setTimeout(handler, timeout) -proc setInterval[T: JSValue|string](window: Window, handler: T, +proc setInterval[T: JSValue|string](window: Window; handler: T; interval = 0i32): int32 {.jsfunc.} = return window.timeouts.setInterval(handler, interval) -proc clearTimeout(window: Window, id: int32) {.jsfunc.} = +proc clearTimeout(window: Window; id: int32) {.jsfunc.} = window.timeouts.clearTimeout(id) -proc clearInterval(window: Window, id: int32) {.jsfunc.} = +proc clearInterval(window: Window; id: int32) {.jsfunc.} = window.timeouts.clearInterval(id) proc screenX(window: Window): int64 {.jsfget.} = 0 @@ -121,7 +126,7 @@ proc outerHeight(window: Window): int64 {.jsfget.} = (addr window.screen).availHeight proc devicePixelRatio(window: Window): float64 {.jsfget.} = 1 -proc setLocation(window: Window, s: string): Err[JSError] +proc setLocation(window: Window; s: string): Err[JSError] {.jsfset: "location".} = window.document.setLocation(s) @@ -143,14 +148,14 @@ func getTop(window: Window): Window {.jsuffget: "top".} = func getParent(window: Window): Window {.jsfget: "parent".} = return window #TODO frames? -proc atob(window: Window, data: string): DOMResult[NarrowString] {.jsfunc.} = +proc atob(window: Window; data: string): DOMResult[NarrowString] {.jsfunc.} = return atob(data) -proc btoa(ctx: JSContext, window: Window, data: JSValue): DOMResult[string] +proc btoa(ctx: JSContext; window: Window; data: JSValue): DOMResult[string] {.jsfunc.} = return btoa(ctx, data) -proc getComputedStyle(window: Window, element: Element, +proc getComputedStyle(window: Window; element: Element; pseudoElt = none(Element)): JSResult[CSSStyleDeclaration] {.jsfunc.} = #TODO implement this properly return ok(element.style) @@ -198,8 +203,8 @@ proc addScripting*(window: Window; selector: Selector[int]) = proc runJSJobs*(window: Window) = window.jsrt.runJSJobs(window.console.err) -proc newWindow*(scripting, images: bool, selector: Selector[int], - attrs: WindowAttributes, factory: CAtomFactory, +proc newWindow*(scripting, images: bool; selector: Selector[int]; + attrs: WindowAttributes; factory: CAtomFactory; navigate: proc(url: URL) = nil, loader = none(FileLoader)): Window = let err = newDynFileStream(stderr) let window = Window( diff --git a/src/html/event.nim b/src/html/event.nim index 6307cf3a..9616d55e 100644 --- a/src/html/event.nim +++ b/src/html/event.nim @@ -18,13 +18,13 @@ type BUBBLING_PHASE = 3u16 EventFlag* = enum - FLAG_STOP_PROPAGATION - FLAG_STOP_IMMEDIATE_PROPAGATION - FLAG_CANCELED - FLAG_IN_PASSIVE_LISTENER - FLAG_COMPOSED - FLAG_INITIALIZED - FLAG_DISPATCH + efStopPropagation + efStopImmediatePropagation + efCanceled + efInPassiveListener + efComposed + efInitialized + efDispatch Event* = ref object of RootObj ctype {.jsget: "type".}: string @@ -76,42 +76,42 @@ type detail: JSValue # Event -proc innerEventCreationSteps(event: Event, eventInitDict: EventInit) = - event.flags = {FLAG_INITIALIZED} +proc innerEventCreationSteps(event: Event; eventInitDict: EventInit) = + event.flags = {efInitialized} #TODO this is probably incorrect? # I think it measures the time since the first fork. not sure though event.timeStamp = round(cpuTime()) event.bubbles = eventInitDict.bubbles event.cancelable = eventInitDict.cancelable if eventInitDict.composed: - event.flags.incl(FLAG_COMPOSED) + event.flags.incl(efComposed) #TODO eventInitDict type -proc newEvent(ctype: string, eventInitDict = EventInit()): +proc newEvent(ctype: string; eventInitDict = EventInit()): JSResult[Event] {.jsctor.} = let event = Event() event.innerEventCreationSteps(eventInitDict) event.ctype = ctype return ok(event) -proc newEvent*(ctx: JSContext, ctype: string, target: EventTarget): Event = +proc newEvent*(ctx: JSContext; ctype: string; target: EventTarget): Event = return Event( ctype: ctype, target: target, currentTarget: target ) -proc initialize(this: Event, ctype: string, bubbles, cancelable: bool) = - this.flags.incl(FLAG_INITIALIZED) +proc initialize(this: Event; ctype: string; bubbles, cancelable: bool) = + this.flags.incl(efInitialized) this.isTrusted = false this.target = nil this.ctype = ctype this.bubbles = bubbles this.cancelable = cancelable -proc initEvent(this: Event, ctype: string, bubbles, cancelable: bool) +proc initEvent(this: Event; ctype: string; bubbles, cancelable: bool) {.jsfunc.} = - if FLAG_DISPATCH notin this.flags: + if efDispatch notin this.flags: this.initialize(ctype, bubbles, cancelable) func srcElement(this: Event): EventTarget {.jsfget.} = @@ -124,40 +124,40 @@ func composedPath(this: Event): seq[EventTarget] {.jsfunc.} = return @[this.currentTarget] proc stopPropagation(this: Event) {.jsfunc.} = - this.flags.incl(FLAG_STOP_PROPAGATION) + this.flags.incl(efStopPropagation) func cancelBubble(this: Event): bool {.jsfget.} = - return FLAG_STOP_PROPAGATION in this.flags + return efStopPropagation in this.flags -proc cancelBubble(this: Event, cancel: bool) {.jsfset.} = +proc cancelBubble(this: Event; cancel: bool) {.jsfset.} = if cancel: this.stopPropagation() proc stopImmediatePropagation(this: Event) {.jsfunc.} = - this.flags.incl({FLAG_STOP_PROPAGATION, FLAG_STOP_IMMEDIATE_PROPAGATION}) + this.flags.incl({efStopPropagation, efStopImmediatePropagation}) proc setCanceledFlag(this: Event) = - if this.cancelable and FLAG_IN_PASSIVE_LISTENER notin this.flags: - this.flags.incl(FLAG_CANCELED) + if this.cancelable and efInPassiveListener notin this.flags: + this.flags.incl(efCanceled) proc returnValue(this: Event): bool {.jsfget.} = - return FLAG_CANCELED notin this.flags + return efCanceled notin this.flags -proc returnValue(this: Event, value: bool) {.jsfset.} = +proc returnValue(this: Event; value: bool) {.jsfset.} = if not value: this.setCanceledFlag() proc preventDefault(this: Event) {.jsfunc.} = - this.flags.incl(FLAG_CANCELED) + this.flags.incl(efCanceled) func defaultPrevented(this: Event): bool {.jsfget.} = - return FLAG_CANCELED in this.flags + return efCanceled in this.flags func composed(this: Event): bool {.jsfget.} = - return FLAG_COMPOSED in this.flags + return efComposed in this.flags # CustomEvent -proc newCustomEvent(ctype: string, eventInitDict = CustomEventInit()): +proc newCustomEvent(ctype: string; eventInitDict = CustomEventInit()): JSResult[CustomEvent] {.jsctor.} = let event = CustomEvent() event.innerEventCreationSteps(eventInitDict) @@ -165,12 +165,12 @@ proc newCustomEvent(ctype: string, eventInitDict = CustomEventInit()): event.ctype = ctype return ok(event) -proc finalize(rt: JSRuntime, this: CustomEvent) {.jsfin.} = +proc finalize(rt: JSRuntime; this: CustomEvent) {.jsfin.} = JS_FreeValueRT(rt, this.detail) -proc initCustomEvent(this: CustomEvent, ctype: string, - bubbles, cancelable: bool, detail: JSValue) {.jsfunc.} = - if FLAG_DISPATCH notin this.flags: +proc initCustomEvent(this: CustomEvent; ctype: string; + bubbles, cancelable: bool; detail: JSValue) {.jsfunc.} = + if efDispatch notin this.flags: this.initialize(ctype, bubbles, cancelable) this.detail = detail @@ -234,7 +234,7 @@ proc removeAnEventListener(eventTarget: EventTarget; ctx: JSContext; i: int) = listener.callback = JS_UNDEFINED eventTarget.eventListeners.delete(i) -proc flatten(ctx: JSContext, options: JSValue): bool = +proc flatten(ctx: JSContext; options: JSValue): bool = if JS_IsBool(options): return fromJS[bool](ctx, options).get(false) if JS_IsObject(options): @@ -242,7 +242,7 @@ proc flatten(ctx: JSContext, options: JSValue): bool = return fromJS[bool](ctx, x).get(false) return false -proc flattenMore(ctx: JSContext, options: JSValue): +proc flattenMore(ctx: JSContext; options: JSValue): tuple[ capture: bool, once: bool, @@ -278,8 +278,8 @@ proc addEventListener*(ctx: JSContext; eventTarget: EventTarget; ctype: string; eventTarget.addAnEventListener(listener) ok() -proc removeEventListener(ctx: JSContext, eventTarget: EventTarget, - ctype: string, callback: EventListenerCallback, +proc removeEventListener(ctx: JSContext; eventTarget: EventTarget; + ctype: string; callback: EventListenerCallback; options = JS_UNDEFINED) {.jsfunc.} = let capture = flatten(ctx, options) let i = eventTarget.findEventListener(ctype, callback, capture) diff --git a/src/html/formdata.nim b/src/html/formdata.nim index 6db82333..c14a36ab 100644 --- a/src/html/formdata.nim +++ b/src/html/formdata.nim @@ -13,7 +13,7 @@ import utils/twtstr import chame/tags -proc constructEntryList*(form: HTMLFormElement, submitter: Element = nil, +proc constructEntryList*(form: HTMLFormElement; submitter: Element = nil; encoding = "UTF-8"): seq[FormDataEntry] proc generateBoundary(): string = @@ -26,8 +26,8 @@ proc generateBoundary(): string = proc newFormData0*(): FormData = return FormData(boundary: generateBoundary()) -proc newFormData*(form: HTMLFormElement = nil, - submitter: HTMLElement = nil): DOMResult[FormData] {.jsctor.} = +proc newFormData*(form: HTMLFormElement = nil; submitter: HTMLElement = nil): + DOMResult[FormData] {.jsctor.} = let this = newFormData0() if form != nil: if submitter != nil: @@ -43,7 +43,7 @@ proc newFormData*(form: HTMLFormElement = nil, #TODO filename should not be allowed for string entries # in other words, this should be an overloaded function, not just an or type -proc append*[T: string|Blob](this: FormData, name: string, value: T, +proc append*[T: string|Blob](this: FormData; name: string; value: T; filename = none(string)) {.jsfunc.} = when T is Blob: let filename = if filename.isSome: @@ -65,12 +65,12 @@ proc append*[T: string|Blob](this: FormData, name: string, value: T, svalue: value )) -proc delete(this: FormData, name: string) {.jsfunc.} = +proc delete(this: FormData; name: string) {.jsfunc.} = for i in countdown(this.entries.high, 0): if this.entries[i].name == name: this.entries.delete(i) -proc get(ctx: JSContext, this: FormData, name: string): JSValue {.jsfunc.} = +proc get(ctx: JSContext; this: FormData; name: string): JSValue {.jsfunc.} = for entry in this.entries: if entry.name == name: if entry.isstr: @@ -79,7 +79,7 @@ proc get(ctx: JSContext, this: FormData, name: string): JSValue {.jsfunc.} = return toJS(ctx, entry.value) return JS_NULL -proc getAll(ctx: JSContext, this: FormData, name: string): seq[JSValue] +proc getAll(ctx: JSContext; this: FormData; name: string): seq[JSValue] {.jsfunc.} = for entry in this.entries: if entry.name == name: diff --git a/src/html/script.nim b/src/html/script.nim index e90eff90..61066abe 100644 --- a/src/html/script.nim +++ b/src/html/script.nim @@ -5,7 +5,7 @@ import types/url type ParserMetadata* = enum - PARSER_INSERTED, NOT_PARSER_INSERTED + pmParserInserted, pmNotParserInserted ScriptType* = enum NO_SCRIPTTYPE, CLASSIC, MODULE, IMPORTMAP @@ -51,17 +51,17 @@ type ModuleMap* = seq[ModuleMapEntry] -proc find*(moduleMap: ModuleMap, url: URL, moduleType: string): int = +proc find*(moduleMap: ModuleMap; url: URL; moduleType: string): int = let surl = $url for i, entry in moduleMap: if entry.key.moduleType == moduleType and entry.key.url == surl: return i return -1 -func fetchDestinationFromModuleType*(defaultDestination: RequestDestination, +func fetchDestinationFromModuleType*(default: RequestDestination; moduleType: string): RequestDestination = if moduleType == "json": return RequestDestination.JSON if moduleType == "css": return RequestDestination.STYLE - return defaultDestination + return default diff --git a/src/html/xmlhttprequest.nim b/src/html/xmlhttprequest.nim index e9905760..69fe157d 100644 --- a/src/html/xmlhttprequest.nim +++ b/src/html/xmlhttprequest.nim @@ -14,12 +14,12 @@ import types/url type XMLHttpRequestResponseType = enum - TYPE_UNKNOWN = "" - TYPE_ARRAYBUFFER = "arraybuffer" - TYPE_BLOB = "blob" - TYPE_DOCUMENT = "document" - TYPE_JSON = "json" - TYPE_TEXT = "text" + xhrtUnknown = "" + xhrtArraybuffer = "arraybuffer" + xhrtBlob = "blob" + xhrtDocument = "document" + xhrtJSON = "json" + xhrtText = "text" XMLHttpRequestState = enum UNSENT = 0u16 @@ -29,7 +29,7 @@ type DONE = 4u16 XMLHttpRequestFlag = enum - SEND_FLAG, UPLOAD_LISTENER_FLAG, SYNC_FLAG + xhrfSend, xhrfUploadListener, xhrfSync XMLHttpRequestEventTarget = ref object of EventTarget onloadstart {.jsgetset.}: EventHandler @@ -81,7 +81,7 @@ proc parseMethod(s: string): DOMResult[HttpMethod] = else: errDOMException("Invalid method", "SyntaxError") -proc open(ctx: JSContext, this: XMLHttpRequest, httpMethod, url: string): +proc open(ctx: JSContext; this: XMLHttpRequest; httpMethod, url: string): Err[DOMException] {.jsfunc.} = let httpMethod = ?parseMethod(httpMethod) let global = JS_GetGlobalObject(ctx) @@ -98,12 +98,12 @@ proc open(ctx: JSContext, this: XMLHttpRequest, httpMethod, url: string): let async = true #TODO if async is false... probably just throw. #TODO terminate fetch controller - this.flags.excl(SEND_FLAG) - this.flags.excl(UPLOAD_LISTENER_FLAG) + this.flags.excl(xhrfSend) + this.flags.excl(xhrfUploadListener) if async: - this.flags.excl(SYNC_FLAG) + this.flags.excl(xhrfSync) else: - this.flags.incl(SYNC_FLAG) + this.flags.incl(xhrfSync) this.requestMethod = httpMethod this.authorRequestHeaders = newHeaders() this.response = makeNetworkError() diff --git a/src/img/bitmap.nim b/src/img/bitmap.nim index 064e574d..76d36747 100644 --- a/src/img/bitmap.nim +++ b/src/img/bitmap.nim @@ -15,13 +15,13 @@ proc newBitmap*(width, height: uint64): Bitmap = height: height ) -proc setpx*(bmp: Bitmap, x, y: uint64, color: RGBAColor) {.inline.} = +proc setpx*(bmp: Bitmap; x, y: uint64; color: RGBAColor) {.inline.} = bmp.px[bmp.width * y + x] = color -proc getpx*(bmp: Bitmap, x, y: uint64): RGBAColor {.inline.} = +proc getpx*(bmp: Bitmap; x, y: uint64): RGBAColor {.inline.} = return bmp.px[bmp.width * y + x] -proc setpxb*(bmp: Bitmap, x, y: uint64, color: RGBAColor) {.inline.} = +proc setpxb*(bmp: Bitmap; x, y: uint64; color: RGBAColor) {.inline.} = if color.a == 255: bmp.setpx(x, y, color) else: diff --git a/src/img/painter.nim b/src/img/painter.nim index c52cb02e..53841a14 100644 --- a/src/img/painter.nim +++ b/src/img/painter.nim @@ -10,11 +10,11 @@ import types/line import types/vector type CanvasFillRule* = enum - NON_ZERO = "nonzero" - EVEN_ODD = "evenodd" + cfrNonZero = "nonzero" + cfrEvenOdd = "evenodd" # https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases -proc plotLineLow(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = +proc plotLineLow(bmp: Bitmap; x0, y0, x1, y1: int64; color: RGBAColor) = var dx = x1 - x0 var dy = y1 - y0 var yi = 1 @@ -32,7 +32,7 @@ proc plotLineLow(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = D = D - 2 * dx; D = D + 2 * dy; -proc plotLineHigh(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = +proc plotLineHigh(bmp: Bitmap; x0, y0, x1, y1: int64; color: RGBAColor) = var dx = x1 - x0 var dy = y1 - y0 var xi = 1 @@ -51,7 +51,7 @@ proc plotLineHigh(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = D = D + 2 * dx #TODO should be uint64... -proc plotLine(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = +proc plotLine(bmp: Bitmap; x0, y0, x1, y1: int64; color: RGBAColor) = if abs(y1 - y0) < abs(x1 - x0): if x0 > x1: bmp.plotLineLow(x1, y1, x0, y0, color) @@ -63,23 +63,23 @@ proc plotLine(bmp: Bitmap, x0, y0, x1, y1: int64, color: RGBAColor) = else: bmp.plotLineHigh(x0, y0, x1, y1, color) -proc plotLine(bmp: Bitmap, a, b: Vector2D, color: RGBAColor) = +proc plotLine(bmp: Bitmap; a, b: Vector2D; color: RGBAColor) = bmp.plotLine(int64(a.x), int64(a.y), int64(b.x), int64(b.y), color) -proc plotLine(bmp: Bitmap, line: Line, color: RGBAColor) = +proc plotLine(bmp: Bitmap; line: Line; color: RGBAColor) = bmp.plotLine(line.p0, line.p1, color) -proc strokePath*(bmp: Bitmap, path: Path, color: RGBAColor) = +proc strokePath*(bmp: Bitmap; path: Path; color: RGBAColor) = for line in path.lines: bmp.plotLine(line, color) -func isInside(windingNumber: int, fillRule: CanvasFillRule): bool = +func isInside(windingNumber: int; fillRule: CanvasFillRule): bool = return case fillRule - of NON_ZERO: windingNumber != 0 - of EVEN_ODD: windingNumber mod 2 == 0 + of cfrNonZero: windingNumber != 0 + of cfrEvenOdd: windingNumber mod 2 == 0 # Mainly adapted from SerenityOS. -proc fillPath*(bmp: Bitmap, path: Path, color: RGBAColor, +proc fillPath*(bmp: Bitmap; path: Path; color: RGBAColor; fillRule: CanvasFillRule) = let lines = path.getLineSegments() var i = 0 @@ -95,21 +95,21 @@ proc fillPath*(bmp: Bitmap, path: Path, color: RGBAColor, ylines.add(lines[j]) inc i ylines.sort(cmpLineSegmentX) - var w = if fillRule == NON_ZERO: 1 else: 0 + var w = if fillRule == cfrNonZero: 1 else: 0 for k in 0 ..< ylines.high: let a = ylines[k] let b = ylines[k + 1] let sx = int64(a.minyx) let ex = int64(b.minyx) - if isInside(w, fillRule) and y > 0: + if w.isInside(fillRule) and y > 0: for x in sx .. ex: if x > 0: bmp.setpxb(uint64(x), uint64(y), color) if int64(a.p0.y) != y and int64(a.p1.y) != y and int64(b.p0.y) != y and int64(b.p1.y) != y and sx != ex or a.islope * b.islope < 0: case fillRule - of EVEN_ODD: inc w - of NON_ZERO: + of cfrEvenOdd: inc w + of cfrNonZero: if a.p0.y < a.p1.y: inc w else: @@ -118,12 +118,12 @@ proc fillPath*(bmp: Bitmap, path: Path, color: RGBAColor, if ylines.len > 0: ylines[^1].minyx += ylines[^1].islope -proc fillRect*(bmp: Bitmap, x0, x1, y0, y1: uint64, color: RGBAColor) = +proc fillRect*(bmp: Bitmap; x0, x1, y0, y1: uint64, color: RGBAColor) = for y in y0 ..< y1: for x in x0 ..< x1: bmp.setpxb(x, y, color) -proc strokeRect*(bmp: Bitmap, x0, x1, y0, y1: uint64, color: RGBAColor) = +proc strokeRect*(bmp: Bitmap; x0, x1, y0, y1: uint64, color: RGBAColor) = for x in x0 ..< x1: bmp.setpxb(x, y0, color) bmp.setpxb(x, y1, color) @@ -131,7 +131,7 @@ proc strokeRect*(bmp: Bitmap, x0, x1, y0, y1: uint64, color: RGBAColor) = bmp.setpxb(x0, y, color) bmp.setpxb(x1, y, color) -proc clearRect*(bmp: Bitmap, x0, x1, y0, y1: uint64) = +proc clearRect*(bmp: Bitmap; x0, x1, y0, y1: uint64) = for y in y0 ..< y1: for x in x0 ..< x1: bmp.setpx(x, y, rgba(0, 0, 0, 0)) @@ -178,7 +178,7 @@ proc getCharBmp(u: uint32): Bitmap = glyphCacheI = 0 return bmp -proc drawBitmap(a, b: Bitmap, p: Vector2D) = +proc drawBitmap(a, b: Bitmap; p: Vector2D) = for y in 0 ..< b.height: for x in 0 ..< b.width: let ax = uint64(p.x) + x @@ -186,7 +186,7 @@ proc drawBitmap(a, b: Bitmap, p: Vector2D) = if ax >= 0 and ay >= y and ax < a.width and ay < a.height: a.setpxb(ax, ay, b.getpx(x, y)) -proc fillText*(bmp: Bitmap, text: string, x, y: float64, color: RGBAColor, +proc fillText*(bmp: Bitmap; text: string; x, y: float64; color: RGBAColor; textAlign: CSSTextAlign) = var w = 0f64 var glyphs: seq[Bitmap] @@ -197,15 +197,15 @@ proc fillText*(bmp: Bitmap, text: string, x, y: float64, color: RGBAColor, var x = x #TODO rtl case textAlign - of TEXT_ALIGN_LEFT, TEXT_ALIGN_START: discard - of TEXT_ALIGN_RIGHT, TEXT_ALIGN_END: x -= w - of TEXT_ALIGN_CENTER: x -= w / 2 + of TextAlignLeft, TextAlignStart: discard + of TextAlignRight, TextAlignEnd: x -= w + of TextAlignCenter: x -= w / 2 else: doAssert false for glyph in glyphs: bmp.drawBitmap(glyph, Vector2D(x: x, y: y - 8)) x += float64(glyph.width) -proc strokeText*(bmp: Bitmap, text: string, x, y: float64, color: RGBAColor, +proc strokeText*(bmp: Bitmap; text: string; x, y: float64; color: RGBAColor; textAlign: CSSTextAlign) = #TODO bmp.fillText(text, x, y, color, textAlign) diff --git a/src/img/path.nim b/src/img/path.nim index 61c71888..9d386752 100644 --- a/src/img/path.nim +++ b/src/img/path.nim @@ -49,25 +49,25 @@ proc newPath*(): Path = needsNewSubpath: true ) -proc addSubpathAt(path: Path, p: Vector2D) = +proc addSubpathAt(path: Path; p: Vector2D) = path.subpaths.add(Subpath(points: @[p])) -proc addSegment(path: Path, segment: PathSegment, p: Vector2D) = +proc addSegment(path: Path; segment: PathSegment; p: Vector2D) = path.subpaths[^1].segments.add(segment) path.subpaths[^1].points.add(p) -proc addStraightSegment(path: Path, p: Vector2D) = +proc addStraightSegment(path: Path; p: Vector2D) = let segment = PathSegment(t: SEGMENT_STRAIGHT) path.addSegment(segment, p) -proc addQuadraticSegment(path: Path, cp, p: Vector2D) = +proc addQuadraticSegment(path: Path; cp, p: Vector2D) = let segment = PathSegment( t: SEGMENT_QUADRATIC, cp: cp ) path.addSegment(segment, p) -proc addBezierSegment(path: Path, cp0, cp1, p: Vector2D) = +proc addBezierSegment(path: Path; cp0, cp1, p: Vector2D) = let segment = PathSegment( t: SEGMENT_BEZIER, cp0: cp0, @@ -76,7 +76,7 @@ proc addBezierSegment(path: Path, cp0, cp1, p: Vector2D) = path.addSegment(segment, p) # Goes from start tangent point to end tangent point -proc addArcSegment(path: Path, o, etan: Vector2D, r: float64, ia: bool) = +proc addArcSegment(path: Path; o, etan: Vector2D; r: float64; ia: bool) = let segment = PathSegment( t: SEGMENT_ARC, oa: o, @@ -85,7 +85,7 @@ proc addArcSegment(path: Path, o, etan: Vector2D, r: float64, ia: bool) = ) path.addSegment(segment, etan) -proc addEllipseSegment(path: Path, o, etan: Vector2D, rx, ry: float64) = +proc addEllipseSegment(path: Path; o, etan: Vector2D; rx, ry: float64) = #TODO simplify to bezier? let segment = PathSegment( t: SEGMENT_ELLIPSE, @@ -114,9 +114,9 @@ iterator items*(pl: PathLines): LineSegment {.inline.} = for line in pl.lines: yield line -func `[]`*(pl: PathLines, i: int): LineSegment = pl.lines[i] -func `[]`*(pl: PathLines, i: BackwardsIndex): LineSegment = pl.lines[i] -func `[]`*(pl: PathLines, s: Slice[int]): seq[LineSegment] = pl.lines[s] +func `[]`*(pl: PathLines; i: int): LineSegment = pl.lines[i] +func `[]`*(pl: PathLines; i: BackwardsIndex): LineSegment = pl.lines[i] +func `[]`*(pl: PathLines; s: Slice[int]): seq[LineSegment] = pl.lines[s] func len*(pl: PathLines): int = pl.lines.len iterator quadraticLines(a, b, c: Vector2D): Line {.inline.} = @@ -163,7 +163,7 @@ func arcControlPoints(p1, p4, o: Vector2D): tuple[c0, c1: Vector2D] = let c1 = o + b + Vector2D(x: k2 * b.y, y: -k2 * b.x) return (c0, c1) -iterator arcLines(p0, p1, o: Vector2D, r: float64, i: bool): Line {.inline.} = +iterator arcLines(p0, p1, o: Vector2D; r: float64; i: bool): Line {.inline.} = var p0 = p0 let pp0 = p0 - o let pp1 = p1 - o @@ -181,7 +181,7 @@ iterator arcLines(p0, p1, o: Vector2D, r: float64, i: bool): Line {.inline.} = p0 = p1 theta -= step -iterator lines(subpath: Subpath, i: int): Line {.inline.} = +iterator lines(subpath: Subpath; i: int): Line {.inline.} = let p0 = subpath.points[i] let p1 = subpath.points[i + 1] case subpath.segments[i].t @@ -232,20 +232,20 @@ proc getLineSegments*(path: Path): PathLines = lines: segments ) -proc moveTo(path: Path, v: Vector2D) = +proc moveTo(path: Path; v: Vector2D) = path.addSubpathAt(v) path.needsNewSubpath = false #TODO TODO TODO ???? why here proc beginPath*(path: Path) = path.subpaths.setLen(0) -proc moveTo*(path: Path, x, y: float64) = +proc moveTo*(path: Path; x, y: float64) = for v in [x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return path.moveTo(Vector2D(x: x, y: y)) -proc ensureSubpath(path: Path, x, y: float64) = +proc ensureSubpath(path: Path; x, y: float64) = if path.needsNewSubpath: path.moveTo(x, y) path.needsNewSubpath = false @@ -272,7 +272,7 @@ proc tempOpenPath*(path: Path) = path.subpaths[^1].closed = false path.tempClosed = false -proc lineTo*(path: Path, x, y: float64) = +proc lineTo*(path: Path; x, y: float64) = for v in [x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -281,7 +281,7 @@ proc lineTo*(path: Path, x, y: float64) = else: path.addStraightSegment(Vector2D(x: x, y: y)) -proc quadraticCurveTo*(path: Path, cpx, cpy, x, y: float64) = +proc quadraticCurveTo*(path: Path; cpx, cpy, x, y: float64) = for v in [cpx, cpy, x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -290,7 +290,7 @@ proc quadraticCurveTo*(path: Path, cpx, cpy, x, y: float64) = let p = Vector2D(x: x, y: y) path.addQuadraticSegment(cp, p) -proc bezierCurveTo*(path: Path, cp0x, cp0y, cp1x, cp1y, x, y: float64) = +proc bezierCurveTo*(path: Path; cp0x, cp0y, cp1x, cp1y, x, y: float64) = for v in [cp0x, cp0y, cp1x, cp1y, x, y]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -300,7 +300,7 @@ proc bezierCurveTo*(path: Path, cp0x, cp0y, cp1x, cp1y, x, y: float64) = let p = Vector2D(x: x, y: y) path.addBezierSegment(cp0, cp1, p) -proc arcTo*(path: Path, x1, y1, x2, y2, radius: float64): Err[DOMException] = +proc arcTo*(path: Path; x1, y1, x2, y2, radius: float64): Err[DOMException] = for v in [x1, y1, x2, y2, radius]: if classify(v) in {fcInf, fcNegInf, fcNan}: return ok() @@ -332,7 +332,7 @@ proc arcTo*(path: Path, x1, y1, x2, y2, radius: float64): Err[DOMException] = path.addArcSegment(origin, tv2, radius, true) #TODO always inner? return ok() -func resolveEllipsePoint(o: Vector2D, angle, radiusX, radiusY, +func resolveEllipsePoint(o: Vector2D; angle, radiusX, radiusY, rotation: float64): Vector2D = # Stolen from SerenityOS let tanrel = tan(angle) @@ -346,7 +346,7 @@ func resolveEllipsePoint(o: Vector2D, angle, radiusX, radiusY, let rely = ab * tanrel / sq * sn return Vector2D(x: relx, y: rely).rotate(rotation) + o -proc arc*(path: Path, x, y, radius, startAngle, endAngle: float64, +proc arc*(path: Path; x, y, radius, startAngle, endAngle: float64; counterclockwise: bool): Err[DOMException] = for v in [x, y, radius, startAngle, endAngle]: if classify(v) in {fcInf, fcNegInf, fcNan}: @@ -368,8 +368,8 @@ proc arc*(path: Path, x, y, radius, startAngle, endAngle: float64, path.addArcSegment(o, e, radius, abs(startAngle - endAngle) < PI) return ok() -proc ellipse*(path: Path, x, y, radiusX, radiusY, rotation, startAngle, - endAngle: float64, counterclockwise: bool): Err[DOMException] = +proc ellipse*(path: Path; x, y, radiusX, radiusY, rotation, startAngle, + endAngle: float64; counterclockwise: bool): Err[DOMException] = for v in [x, y, radiusX, radiusY, rotation, startAngle, endAngle]: if classify(v) in {fcInf, fcNegInf, fcNan}: return ok() @@ -390,7 +390,7 @@ proc ellipse*(path: Path, x, y, radiusX, radiusY, rotation, startAngle, path.addEllipseSegment(o, e, radiusX, radiusY) return ok() -proc rect*(path: Path, x, y, w, h: float64) = +proc rect*(path: Path; x, y, w, h: float64) = for v in [x, y, w, h]: if classify(v) in {fcInf, fcNegInf, fcNan}: return @@ -401,7 +401,7 @@ proc rect*(path: Path, x, y, w, h: float64) = path.addStraightSegment(Vector2D(x: x, y: y)) path.addSubpathAt(Vector2D(x: x, y: y)) -proc roundRect*(path: Path, x, y, w, h, radii: float64) = +proc roundRect*(path: Path; x, y, w, h, radii: float64) = for v in [x, y, w, h]: if classify(v) in {fcInf, fcNegInf, fcNan}: return diff --git a/src/img/png.nim b/src/img/png.nim index 27482e63..7f4d8493 100644 --- a/src/img/png.nim +++ b/src/img/png.nim @@ -15,21 +15,21 @@ func pngInt(i: uint32): auto = func oq(writer: PNGWriter): ptr UncheckedArray[uint8] = cast[ptr UncheckedArray[uint8]](writer.buf) -proc writeStr[T](writer: var PNGWriter, s: T) = +proc writeStr[T](writer: var PNGWriter; s: T) = if writer.outlen < writer.i + s.len: writer.outlen = writer.i + s.len writer.buf = realloc(writer.buf, writer.outlen) copyMem(addr writer.oq[writer.i], unsafeAddr s[0], s.len) writer.i += s.len -proc writeInt(writer: var PNGWriter, i: uint32) = +proc writeInt(writer: var PNGWriter; i: uint32) = writer.writeStr(i.toBytesBE()) -proc writePngInt(writer: var PNGWriter, i: uint32) = +proc writePngInt(writer: var PNGWriter; i: uint32) = doAssert i < 0x80000000u32 writer.writeInt(i) -proc writeChunk[T](writer: var PNGWriter, t: string, data: T) = +proc writeChunk[T](writer: var PNGWriter; t: string; data: T) = var crc = uint32(crc32(0, cast[ptr uint8](unsafeAddr t[0]), cuint(t.len))) if data.len > 0: crc = uint32(crc32(crc, cast[ptr uint8](unsafeAddr data[0]), @@ -41,15 +41,15 @@ proc writeChunk[T](writer: var PNGWriter, t: string, data: T) = writer.writeInt(uint32(crc)) type PNGColorType {.size: sizeof(uint8).} = enum - GRAYSCALE = 0 - TRUECOLOR = 2 - INDEXED_COLOR = 3 - GRAYSCALE_WITH_ALPHA = 4 - TRUECOLOR_WITH_ALPHA = 6 + pcGrayscale = 0 + pcTrueColor = 2 + pcIndexedColor = 3 + pcGrayscaleWithAlpha = 4 + pcTrueColorWithAlpha = 6 const PNGSignature = "\x89PNG\r\n\x1A\n" -proc writeIHDR(writer: var PNGWriter, width, height: uint32, - bitDepth: uint8, colorType: PNGColorType, +proc writeIHDR(writer: var PNGWriter; width, height: uint32; + bitDepth: uint8; colorType: PNGColorType; compressionMethod, filterMethod, interlaceMethod: uint8) = writer.writeStr(PNGSignature) var ihdr {.noinit.}: array[13, uint8] @@ -64,7 +64,7 @@ proc writeIHDR(writer: var PNGWriter, width, height: uint32, ihdr[12] = interlaceMethod writer.writeChunk("IHDR", ihdr) -proc writeIDAT(writer: var PNGWriter, bmp: Bitmap) = +proc writeIDAT(writer: var PNGWriter; bmp: Bitmap) = #TODO smaller idat chunks # +1 height for filter var idat = newSeq[uint8]((bmp.width + 1) * bmp.height * 4) @@ -87,13 +87,13 @@ proc writeIDAT(writer: var PNGWriter, bmp: Bitmap) = oidat.setLen(int(hlen)) writer.writeChunk("IDAT", oidat) -proc toPNG*(bmp: Bitmap, outlen: var int): pointer = +proc toPNG*(bmp: Bitmap; outlen: var int): pointer = var writer = PNGWriter( buf: alloc(PNGSignature.len), outlen: PNGSignature.len ) writer.writeIHDR(uint32(bmp.width), uint32(bmp.height), 8, - TRUECOLOR_WITH_ALPHA, 0, 0, 0) + pcTrueColorWithAlpha, 0, 0, 0) writer.writeIDAT(bmp) writer.writeChunk("IEND", "") outlen = writer.outlen @@ -125,28 +125,28 @@ func height(reader: PNGReader): int {.inline.} = int(reader.bmp.height) func spp(reader: PNGReader): int = case reader.colorType - of TRUECOLOR: return 3 - of GRAYSCALE: return 1 - of INDEXED_COLOR: return 1 - of GRAYSCALE_WITH_ALPHA: return 2 - of TRUECOLOR_WITH_ALPHA: return 4 + of pcTrueColor: return 3 + of pcGrayscale: return 1 + of pcIndexedColor: return 1 + of pcGrayscaleWithAlpha: return 2 + of pcTrueColorWithAlpha: return 4 func scanlen(reader: PNGReader): int {.inline.} = let w = reader.width + 1 return (w * reader.spp * int(reader.bitDepth) + 7) div 8 -proc handleError(reader: var PNGReader, msg: string) = +proc handleError(reader: var PNGReader; msg: string) = #TODO proper error handling? stderr.write(msg & "\n") reader.bmp = nil if reader.hasstrm: discard inflateEnd(addr reader.strm) -template err(reader: var PNGReader, msg: string) = +template err(reader: var PNGReader; msg: string) = reader.handleError(msg) return -template readStr(reader: var PNGReader, L: int): string = +template readStr(reader: var PNGReader; L: int): string = if reader.i + L > reader.limit: reader.err "too short" var s = newString(L) @@ -176,20 +176,20 @@ template readPNGInt(reader: var PNGReader): uint32 = template readColorType(reader: var PNGReader): PNGColorType = case reader.readU8() - of 0u8: GRAYSCALE - of 2u8: TRUECOLOR - of 3u8: INDEXED_COLOR - of 4u8: GRAYSCALE_WITH_ALPHA - of 6u8: TRUECOLOR_WITH_ALPHA + of 0u8: pcGrayscale + of 2u8: pcTrueColor + of 3u8: pcIndexedColor + of 4u8: pcGrayscaleWithAlpha + of 6u8: pcTrueColorWithAlpha else: reader.err "unknown color type" -func bitDepthValid(colorType: PNGColorType, bitDepth: uint8): bool = +func bitDepthValid(colorType: PNGColorType; bitDepth: uint8): bool = case colorType - of GRAYSCALE: + of pcGrayscale: return int(bitDepth) in [1, 2, 4, 8, 16] - of INDEXED_COLOR: + of pcIndexedColor: return int(bitDepth) in [1, 2, 4, 8] - of TRUECOLOR, GRAYSCALE_WITH_ALPHA, TRUECOLOR_WITH_ALPHA: + of pcTrueColor, pcGrayscaleWithAlpha, pcTrueColorWithAlpha: return int(bitDepth) in [8, 16] proc readIHDR(reader: var PNGReader) = @@ -220,11 +220,11 @@ proc readIHDR(reader: var PNGReader) = proc readbKGD(reader: var PNGReader) = case reader.colorType - of GRAYSCALE, GRAYSCALE_WITH_ALPHA: + of pcGrayscale, pcGrayscaleWithAlpha: # We can't really use bit depth > 8 discard reader.readU8() reader.background = gray(reader.readU8()) - of TRUECOLOR, TRUECOLOR_WITH_ALPHA: + of pcTrueColor, pcTrueColorWithAlpha: discard reader.readU8() let r = reader.readU8() discard reader.readU8() @@ -232,7 +232,7 @@ proc readbKGD(reader: var PNGReader) = discard reader.readU8() let b = reader.readU8() reader.background = rgb(r, g, b) - of INDEXED_COLOR: + of pcIndexedColor: let i = int(reader.readU8()) if i >= reader.palette.len: reader.err "invalid palette index" @@ -240,11 +240,11 @@ proc readbKGD(reader: var PNGReader) = proc readtRNS(reader: var PNGReader) = case reader.colorType - of GRAYSCALE, GRAYSCALE_WITH_ALPHA: + of pcGrayscale, pcGrayscaleWithAlpha: # We can't really use bit depth > 8 discard reader.readU8() reader.trns = gray(reader.readU8()) - of TRUECOLOR, TRUECOLOR_WITH_ALPHA: + of pcTrueColor, pcTrueColorWithAlpha: discard reader.readU8() let r = reader.readU8() discard reader.readU8() @@ -252,13 +252,13 @@ proc readtRNS(reader: var PNGReader) = discard reader.readU8() let b = reader.readU8() reader.trns = rgb(r, g, b) - of INDEXED_COLOR: + of pcIndexedColor: if reader.limit - reader.i > reader.palette.len: reader.err "too many trns values" for i in 0 ..< reader.palette.len: reader.palette[i].a = reader.readU8() -proc unfilter(reader: var PNGReader, irow: openArray[uint8], bpp: int) = +proc unfilter(reader: var PNGReader; irow: openArray[uint8]; bpp: int) = # none, sub, up -> replace uprow directly # average, paeth -> copy to temp array, then replace uprow let fil = irow[0] @@ -283,9 +283,9 @@ proc unfilter(reader: var PNGReader, irow: openArray[uint8], bpp: int) = else: reader.err "got invalid filter" -proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = +proc writepxs(reader: var PNGReader; crow: var openArray[RGBAColor]) = case reader.colorType - of GRAYSCALE: + of pcGrayscale: var i = 0 var j = 0 for x in 0 ..< crow.len: @@ -301,7 +301,7 @@ proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = i += j div 8 j = j mod 8 crow[x] = rgba(n, n, n, 255u8) - of TRUECOLOR: + of pcTrueColor: let step = int(reader.bitDepth) div 8 var i = 0 for x in 0 ..< crow.len: @@ -312,7 +312,7 @@ proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = let b = reader.uprow[i] i += step crow[x] = rgba(r, g, b, 255u8) - of INDEXED_COLOR: + of pcIndexedColor: var i = 0 var j = 0 for x in 0 ..< crow.len: @@ -329,7 +329,7 @@ proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = if unlikely(int(n) >= reader.palette.len): reader.err "invalid palette index" crow[x] = reader.palette[n] - of GRAYSCALE_WITH_ALPHA: + of pcGrayscaleWithAlpha: let step = int(reader.bitDepth) div 8 var i = 0 for x in 0 ..< crow.len: @@ -338,7 +338,7 @@ proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = let a = reader.uprow[i] i += step crow[x] = rgba(n, n, n, a) - of TRUECOLOR_WITH_ALPHA: + of pcTrueColorWithAlpha: let step = int(reader.bitDepth) div 8 for x in 0 ..< crow.len: let r = reader.uprow[x * step] @@ -350,7 +350,7 @@ proc writepxs(reader: var PNGReader, crow: var openArray[RGBAColor]) = proc readPLTE(reader: var PNGReader) = # For non-indexed-color, palette is just a suggestion for quantization. #TODO support this in term - const CanHavePLTE = {TRUECOLOR, INDEXED_COLOR, TRUECOLOR_WITH_ALPHA} + const CanHavePLTE = {pcTrueColor, pcIndexedColor, pcTrueColorWithAlpha} if reader.plteseen: reader.err "too many PLTE chunks" if reader.colorType notin CanHavePLTE: @@ -371,7 +371,7 @@ proc readIDAT(reader: var PNGReader) = reader.err "idat buffer already filled" if reader.strmend: reader.err "stream already ended" - if reader.colorType == INDEXED_COLOR and not reader.plteseen: + if reader.colorType == pcIndexedColor and not reader.plteseen: reader.err "palette expected for indexed color" reader.strm.avail_in = cuint(reader.limit - reader.i) reader.strm.next_in = addr reader.iq[reader.i] @@ -414,16 +414,16 @@ proc readIEND(reader: var PNGReader) = reader.err "IEND too long" reader.isend = true -proc readUnknown(reader: var PNGReader, s: string) = +proc readUnknown(reader: var PNGReader; s: string) = if (int(s[0]) and 0x20) == 0: reader.err "unrecognized critical chunk " & s #else: eprint "warning: unknown chunk " & s #debug reader.i = reader.limit -proc zlibAlloc(opaque: pointer, items: cuint, size: cuint): pointer {.cdecl.} = +proc zlibAlloc(opaque: pointer; items: cuint; size: cuint): pointer {.cdecl.} = return alloc(items * size) -proc zlibFree(opaque: pointer, address: pointer) {.cdecl.} = +proc zlibFree(opaque: pointer; address: pointer) {.cdecl.} = dealloc(address) proc initZStream(reader: var PNGReader) = diff --git a/src/io/bufreader.nim b/src/io/bufreader.nim index eca6b585..6de269ac 100644 --- a/src/io/bufreader.nim +++ b/src/io/bufreader.nim @@ -118,7 +118,7 @@ proc sread*(reader: var BufferedReader; s: var seq) = for x in s.mitems: reader.sread(x) -proc sread*[U; V](reader: var BufferedReader, t: var Table[U, V]) = +proc sread*[U; V](reader: var BufferedReader; t: var Table[U, V]) = var len: int reader.sread(len) for i in 0..<len: diff --git a/src/io/bufstream.nim b/src/io/bufstream.nim index 118b81e5..62a0df3e 100644 --- a/src/io/bufstream.nim +++ b/src/io/bufstream.nim @@ -8,10 +8,10 @@ type registered: bool writeBuffer: string -method recvData*(s: BufStream, buffer: pointer, len: int): int = +method recvData*(s: BufStream; buffer: pointer; len: int): int = s.source.recvData(buffer, len) -method sendData*(s: BufStream, buffer: pointer, len: int): int = +method sendData*(s: BufStream; buffer: pointer; len: int): int = s.source.setBlocking(false) block nobuf: var n: int @@ -45,9 +45,5 @@ proc flushWrite*(s: BufStream): bool = s.writeBuffer = s.writeBuffer.substr(n) return false -proc newBufStream*(ps: PosixStream, registerFun: proc(fd: int)): BufStream = - return BufStream( - source: ps, - blocking: ps.blocking, - registerFun: registerFun - ) +proc newBufStream*(ps: PosixStream; registerFun: proc(fd: int)): BufStream = + return BufStream(source: ps, blocking: ps.blocking, registerFun: registerFun) diff --git a/src/io/posixstream.nim b/src/io/posixstream.nim index bfd925f2..dd2101fa 100644 --- a/src/io/posixstream.nim +++ b/src/io/posixstream.nim @@ -32,7 +32,7 @@ proc raisePosixIOError*() = else: raise newException(IOError, $strerror(errno)) -method recvData*(s: PosixStream, buffer: pointer, len: int): int = +method recvData*(s: PosixStream; buffer: pointer; len: int): int = let n = read(s.fd, buffer, len) if n < 0: raisePosixIOError() @@ -46,13 +46,13 @@ proc sreadChar*(s: PosixStream): char = let n = read(s.fd, addr result, 1) assert n == 1 -method sendData*(s: PosixStream, buffer: pointer, len: int): int = +method sendData*(s: PosixStream; buffer: pointer; len: int): int = let n = write(s.fd, buffer, len) if n < 0: raisePosixIOError() return n -method setBlocking*(s: PosixStream, blocking: bool) {.base.} = +method setBlocking*(s: PosixStream; blocking: bool) {.base.} = s.blocking = blocking let ofl = fcntl(s.fd, F_GETFL, 0) if blocking: @@ -70,7 +70,7 @@ method sclose*(s: PosixStream) = proc newPosixStream*(fd: FileHandle): PosixStream = return PosixStream(fd: fd, blocking: true) -proc newPosixStream*(path: string, flags, mode: cint): PosixStream = +proc newPosixStream*(path: string; flags, mode: cint): PosixStream = let fd = open(cstring(path), flags, mode) if fd == -1: return nil diff --git a/src/io/promise.nim b/src/io/promise.nim index c7942190..63ae256f 100644 --- a/src/io/promise.nim +++ b/src/io/promise.nim @@ -16,7 +16,7 @@ type res: T get: GetValueProc[T] - GetValueProc[T] = (proc(opaque: pointer, res: var T)) + GetValueProc[T] = (proc(opaque: pointer; res: var T)) PromiseMap* = object tab: Table[int, EmptyPromise] @@ -30,12 +30,13 @@ proc newPromiseMap*(opaque: pointer): PromiseMap = opaque: opaque ) -proc addPromise*[T](map: var PromiseMap, id: int, get: GetValueProc[T]): Promise[T] = +proc addPromise*[T](map: var PromiseMap; id: int; get: GetValueProc[T]): + Promise[T] = let promise = Promise[T](get: get, opaque: map.opaque) map.tab[id] = promise return promise -proc addEmptyPromise*(map: var PromiseMap, id: int): EmptyPromise = +proc addEmptyPromise*(map: var PromiseMap; id: int): EmptyPromise = let promise = EmptyPromise(opaque: map.opaque) map.tab[id] = promise return promise @@ -52,7 +53,7 @@ proc resolve*(promise: EmptyPromise) = break promise.next = nil -proc resolve*[T](promise: Promise[T], res: T) = +proc resolve*[T](promise: Promise[T]; res: T) = if promise.cb != nil: if promise.get != nil: promise.get(promise.opaque, promise.res) @@ -60,7 +61,7 @@ proc resolve*[T](promise: Promise[T], res: T) = promise.res = res promise.resolve() -proc resolve*(map: var PromiseMap, promiseid: int) = +proc resolve*(map: var PromiseMap; promiseid: int) = var promise: EmptyPromise if map.tab.pop(promiseid, promise): promise.resolve() @@ -73,14 +74,14 @@ proc newResolvedPromise*(): EmptyPromise = func empty*(map: PromiseMap): bool = map.tab.len == 0 -proc then*(promise: EmptyPromise, cb: (proc())): EmptyPromise {.discardable.} = +proc then*(promise: EmptyPromise; cb: (proc())): EmptyPromise {.discardable.} = promise.cb = cb promise.next = EmptyPromise() if promise.state == PROMISE_FULFILLED: promise.resolve() return promise.next -proc then*(promise: EmptyPromise, cb: (proc(): EmptyPromise)): EmptyPromise +proc then*(promise: EmptyPromise; cb: (proc(): EmptyPromise)): EmptyPromise {.discardable.} = let next = EmptyPromise() promise.then(proc() = @@ -92,14 +93,16 @@ proc then*(promise: EmptyPromise, cb: (proc(): EmptyPromise)): EmptyPromise next.resolve()) return next -proc then*[T](promise: Promise[T], cb: (proc(x: T))): EmptyPromise {.discardable.} = +proc then*[T](promise: Promise[T]; cb: (proc(x: T))): EmptyPromise + {.discardable.} = return promise.then(proc() = if promise.get != nil: promise.get(promise.opaque, promise.res) promise.get = nil cb(promise.res)) -proc then*[T](promise: EmptyPromise, cb: (proc(): Promise[T])): Promise[T] {.discardable.} = +proc then*[T](promise: EmptyPromise; cb: (proc(): Promise[T])): Promise[T] + {.discardable.} = let next = Promise[T]() promise.then(proc() = var p2 = cb() @@ -111,7 +114,8 @@ proc then*[T](promise: EmptyPromise, cb: (proc(): Promise[T])): Promise[T] {.dis next.resolve()) return next -proc then*[T](promise: Promise[T], cb: (proc(x: T): EmptyPromise)): EmptyPromise {.discardable.} = +proc then*[T](promise: Promise[T]; cb: (proc(x: T): EmptyPromise)): EmptyPromise + {.discardable.} = let next = EmptyPromise() promise.then(proc(x: T) = let p2 = cb(x) @@ -122,14 +126,16 @@ proc then*[T](promise: Promise[T], cb: (proc(x: T): EmptyPromise)): EmptyPromise next.resolve()) return next -proc then*[T, U](promise: Promise[T], cb: (proc(x: T): U)): Promise[U] {.discardable.} = +proc then*[T, U](promise: Promise[T]; cb: (proc(x: T): U)): Promise[U] + {.discardable.} = let next = Promise[U]() promise.then(proc(x: T) = next.res = cb(x) next.resolve()) return next -proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Promise[U])): Promise[U] {.discardable.} = +proc then*[T, U](promise: Promise[T]; cb: (proc(x: T): Promise[U])): Promise[U] + {.discardable.} = let next = Promise[U]() promise.then(proc(x: T) = let p2 = cb(x) @@ -141,7 +147,7 @@ proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Promise[U])): Promise[U] next.resolve()) return next -proc then*[T, U](promise: Promise[T], cb: (proc(x: T): Opt[Promise[U]])): +proc then*[T, U](promise: Promise[T]; cb: (proc(x: T): Opt[Promise[U]])): Promise[Opt[U]] {.discardable.} = let next = Promise[Opt[U]]() promise.then(proc(x: T) = diff --git a/src/io/readablestream.nim b/src/io/readablestream.nim index 16a650e2..8269f1dc 100644 --- a/src/io/readablestream.nim +++ b/src/io/readablestream.nim @@ -26,7 +26,7 @@ type ReadableStream* = object underlyingSource: UnderlyingSource -proc newReadableStream(underlyingSource = none(UnderlyingSource), +proc newReadableStream(underlyingSource = none(UnderlyingSource); strategy = none(QueuingStrategySize)): ReadableStream = let this = ReadableStream() discard diff --git a/src/io/socketstream.nim b/src/io/socketstream.nim index 32aff96d..13fcd664 100644 --- a/src/io/socketstream.nim +++ b/src/io/socketstream.nim @@ -9,7 +9,7 @@ import io/serversocket type SocketStream* = ref object of PosixStream source*: Socket -method recvData*(s: SocketStream, buffer: pointer, len: int): int = +method recvData*(s: SocketStream; buffer: pointer; len: int): int = let n = s.source.recv(buffer, len) if n < 0: raisePosixIOError() @@ -19,7 +19,7 @@ method recvData*(s: SocketStream, buffer: pointer, len: int): int = s.isend = true return n -method sendData*(s: SocketStream, buffer: pointer, len: int): int = +method sendData*(s: SocketStream; buffer: pointer; len: int): int = let n = s.source.send(buffer, len) if n < 0: raisePosixIOError() @@ -28,7 +28,7 @@ method sendData*(s: SocketStream, buffer: pointer, len: int): int = {.compile: "sendfd.c".} proc sendfd(sock, fd: cint): int {.importc.} -proc sendFileHandle*(s: SocketStream, fd: FileHandle) = +proc sendFileHandle*(s: SocketStream; fd: FileHandle) = assert not s.source.hasDataBuffered let n = sendfd(s.fd, cint(fd)) if n < 0: @@ -36,7 +36,7 @@ proc sendFileHandle*(s: SocketStream, fd: FileHandle) = assert n == 1 # we send a single nul byte as buf {.compile: "recvfd.c".} -proc recvfd(sock: cint, fdout: ptr cint): int {.importc.} +proc recvfd(sock: cint; fdout: ptr cint): int {.importc.} proc recvFileHandle*(s: SocketStream): FileHandle = assert not s.source.hasDataBuffered @@ -46,7 +46,7 @@ proc recvFileHandle*(s: SocketStream): FileHandle = raisePosixIOError() return FileHandle(fd) -method setBlocking*(s: SocketStream, blocking: bool) = +method setBlocking*(s: SocketStream; blocking: bool) = s.blocking = blocking s.source.getFd().setBlocking(blocking) @@ -96,7 +96,7 @@ proc connectSocketStream*(socketDir: string; baseFd, pid: int; except OSError: return nil -proc acceptSocketStream*(ssock: ServerSocket, blocking = true): SocketStream = +proc acceptSocketStream*(ssock: ServerSocket; blocking = true): SocketStream = var sock: Socket ssock.sock.accept(sock, inheritable = true) if not blocking: diff --git a/src/io/tempfile.nim b/src/io/tempfile.nim index 5968270b..44c63297 100644 --- a/src/io/tempfile.nim +++ b/src/io/tempfile.nim @@ -1,7 +1,7 @@ import std/os var tmpf_seq: int -proc getTempFile*(tmpdir: string, ext = ""): string = +proc getTempFile*(tmpdir: string; ext = ""): string = if not dirExists(tmpdir): createDir(tmpdir) var tmpf = tmpdir / "chatmp" & $getCurrentProcessId() & "-" & $tmpf_seq diff --git a/src/io/urlfilter.nim b/src/io/urlfilter.nim index 457d79f8..6bbb247c 100644 --- a/src/io/urlfilter.nim +++ b/src/io/urlfilter.nim @@ -11,8 +11,8 @@ type URLFilter* = object allowhosts: seq[Regex] default: bool -proc newURLFilter*(scheme = none(string), allowschemes: seq[string] = @[], - allowhost = none(string), allowhosts: seq[Regex] = @[], +proc newURLFilter*(scheme = none(string); allowschemes: seq[string] = @[]; + allowhost = none(string); allowhosts: seq[Regex] = @[]; default = false): URLFilter = doAssert scheme.isSome or allowschemes.len == 0, "allowschemes without scheme is not supported" @@ -28,7 +28,7 @@ proc newURLFilter*(scheme = none(string), allowschemes: seq[string] = @[], # If scheme/s are given, only URLs with the same scheme are matched. # Then, allowhost and allowhosts are checked; if none of these match the host, # the function returns the value of `default'. -proc match*(filter: URLFilter, url: URL): bool = +proc match*(filter: URLFilter; url: URL): bool = block check_scheme: if filter.scheme.isSome and filter.scheme.get != url.scheme: for scheme in filter.allowschemes: diff --git a/src/js/base64.nim b/src/js/base64.nim index 3d540664..a8362910 100644 --- a/src/js/base64.nim +++ b/src/js/base64.nim @@ -17,7 +17,7 @@ proc atob*(data: string): DOMResult[NarrowString] = return errDOMException("Invalid character in string", "InvalidCharacterError") -proc btoa*(ctx: JSContext, data: JSValue): DOMResult[string] = +proc btoa*(ctx: JSContext; data: JSValue): DOMResult[string] = let data = JS_ToString(ctx, data) if JS_IsException(data): return err() diff --git a/src/js/console.nim b/src/js/console.nim index d5e074e8..305dfa9b 100644 --- a/src/js/console.nim +++ b/src/js/console.nim @@ -18,7 +18,7 @@ proc newConsole*(err: DynStream; clearFun: proc() = nil; showFun: proc() = nil; hideFun: hideFun ) -proc log*(console: Console, ss: varargs[string]) {.jsfunc.} = +proc log*(console: Console; ss: varargs[string]) {.jsfunc.} = for i in 0..<ss.len: console.err.write(ss[i]) if i != ss.high: @@ -31,23 +31,23 @@ proc clear(console: Console) {.jsfunc.} = console.clearFun() # For now, these are the same as log(). -proc debug(console: Console, ss: varargs[string]) {.jsfunc.} = +proc debug(console: Console; ss: varargs[string]) {.jsfunc.} = console.log(ss) -proc error(console: Console, ss: varargs[string]) {.jsfunc.} = +proc error(console: Console; ss: varargs[string]) {.jsfunc.} = console.log(ss) -proc info(console: Console, ss: varargs[string]) {.jsfunc.} = +proc info(console: Console; ss: varargs[string]) {.jsfunc.} = console.log(ss) -proc warn(console: Console, ss: varargs[string]) {.jsfunc.} = +proc warn(console: Console; ss: varargs[string]) {.jsfunc.} = console.log(ss) -proc show(console: Console, ss: varargs[string]) {.jsfunc.} = +proc show(console: Console; ss: varargs[string]) {.jsfunc.} = if console.showFun != nil: console.showFun() -proc hide(console: Console, ss: varargs[string]) {.jsfunc.} = +proc hide(console: Console; ss: varargs[string]) {.jsfunc.} = if console.hideFun != nil: console.hideFun() diff --git a/src/js/encoding.nim b/src/js/encoding.nim index eff99805..df4043b5 100644 --- a/src/js/encoding.nim +++ b/src/js/encoding.nim @@ -63,21 +63,21 @@ proc grow(buf: var Growbuf) = buf.cap *= 2 buf.p = cast[ptr UncheckedArray[uint8]](buf.p.realloc(buf.cap)) -proc write(buf: var Growbuf, s: openArray[uint8]) = +proc write(buf: var Growbuf; s: openArray[uint8]) = if buf.len + s.len > buf.cap: buf.grow() if s.len > 0: copyMem(addr buf.p[buf.len], unsafeAddr s[0], s.len) buf.len += s.len -proc write(buf: var Growbuf, s: string) = +proc write(buf: var Growbuf; s: string) = if buf.len + s.len > buf.cap: buf.grow() if s.len > 0: copyMem(addr buf.p[buf.len], unsafeAddr s[0], s.len) buf.len += s.len -proc decode0(this: JSTextDecoder, ctx: JSContext, input: JSArrayBufferView, +proc decode0(this: JSTextDecoder; ctx: JSContext; input: JSArrayBufferView; stream: bool): JSResult[JSValue] = var oq = Growbuf( p: cast[ptr UncheckedArray[uint8]](alloc(BufferSize)), @@ -106,7 +106,7 @@ proc decode0(this: JSTextDecoder, ctx: JSContext, input: JSArrayBufferView, oq.grow() return ok(JS_NewStringLen(ctx, cast[cstring](oq.p), csize_t(oq.len))) -proc validate0(this: JSTextDecoder, ctx: JSContext, input: JSArrayBufferView, +proc validate0(this: JSTextDecoder; ctx: JSContext; input: JSArrayBufferView; stream: bool): JSResult[JSValue] = # assume input is valid; do not allocate yet var oq = Growbuf(p: nil, len: 0, cap: 0) diff --git a/src/js/fromjs.nim b/src/js/fromjs.nim index f93e89fa..4cdc18d1 100644 --- a/src/js/fromjs.nim +++ b/src/js/fromjs.nim @@ -11,9 +11,9 @@ import js/opaque import types/opt import utils/twtstr -proc fromJS*[T](ctx: JSContext, val: JSValue): JSResult[T] +proc fromJS*[T](ctx: JSContext; val: JSValue): JSResult[T] -func isInstanceOfNonGlobal(ctx: JSContext, val: JSValue, class: string): bool = +func isInstanceOfNonGlobal(ctx: JSContext; val: JSValue; class: string): bool = let ctxOpaque = ctx.getOpaque() var classid = JS_GetClassID(val) let tclassid = ctxOpaque.creg[class] @@ -30,7 +30,7 @@ func isInstanceOfNonGlobal(ctx: JSContext, val: JSValue, class: string): bool = break return found -func isInstanceOfGlobal(ctx: JSContext, val: JSValue, class: string): bool = +func isInstanceOfGlobal(ctx: JSContext; val: JSValue; class: string): bool = let ctxOpaque = ctx.getOpaque() #TODO gparent only works for a single level. (But this is not really a # problem right now, because our global objects have at most one inheritance @@ -48,11 +48,11 @@ func isInstanceOfGlobal(ctx: JSContext, val: JSValue, class: string): bool = return true return false -func isInstanceOf*(ctx: JSContext, val: JSValue, class: string): bool = +func isInstanceOf*(ctx: JSContext; val: JSValue; class: string): bool = return ctx.isInstanceOfGlobal(val, class) or ctx.isInstanceOfNonGlobal(val, class) -func toString(ctx: JSContext, val: JSValue): Opt[string] = +func toString(ctx: JSContext; val: JSValue): Opt[string] = var plen: csize_t let outp = JS_ToCStringLen(ctx, addr plen, val) # cstring if outp != nil: @@ -63,7 +63,7 @@ func toString(ctx: JSContext, val: JSValue): Opt[string] = result = ok(ret) JS_FreeCString(ctx, outp) -func fromJSString(ctx: JSContext, val: JSValue): JSResult[string] = +func fromJSString(ctx: JSContext; val: JSValue): JSResult[string] = var plen: csize_t let outp = JS_ToCStringLen(ctx, addr plen, val) # cstring if outp == nil: @@ -75,7 +75,7 @@ func fromJSString(ctx: JSContext, val: JSValue): JSResult[string] = JS_FreeCString(ctx, outp) return ok(ret) -func fromJSInt[T: SomeInteger](ctx: JSContext, val: JSValue): +func fromJSInt[T: SomeInteger](ctx: JSContext; val: JSValue): JSResult[T] = when T is int: # Always int32, so we don't risk 32-bit only breakage. @@ -110,7 +110,7 @@ func fromJSInt[T: SomeInteger](ctx: JSContext, val: JSValue): return err() return ok(cast[uint64](ret)) -proc fromJSFloat64(ctx: JSContext, val: JSValue): JSResult[float64] = +proc fromJSFloat64(ctx: JSContext; val: JSValue): JSResult[float64] = var f64: float64 if JS_ToFloat64(ctx, addr f64, val) < 0: return err() @@ -150,14 +150,16 @@ macro fromJSTupleBody(a: tuple) = let doneVal = JS_GetProperty(ctx, next, ctx.getOpaque().str_refs[DONE]) `done` = ?fromJS[bool](ctx, doneVal) var i = `i` - # we're emulating a sequence, so we must query all remaining parameters too: + # we're emulating a sequence, so we must query all remaining parameters + # too: while not `done`: inc i let next = JS_Call(ctx, next_method, it, 0, nil) if JS_IsException(next): return err() defer: JS_FreeValue(ctx, next) - let doneVal = JS_GetProperty(ctx, next, ctx.getOpaque().str_refs[DONE]) + let doneVal = JS_GetProperty(ctx, next, + ctx.getOpaque().str_refs[DONE]) if JS_IsException(doneVal): return err() defer: JS_FreeValue(ctx, doneVal) @@ -166,10 +168,11 @@ macro fromJSTupleBody(a: tuple) = let msg = "Too many arguments in sequence (got " & $i & ", expected " & $`len` & ")" return err(newTypeError(msg)) - JS_FreeValue(ctx, JS_GetProperty(ctx, next, ctx.getOpaque().str_refs[VALUE])) + JS_FreeValue(ctx, JS_GetProperty(ctx, next, + ctx.getOpaque().str_refs[VALUE])) ) -proc fromJSTuple[T: tuple](ctx: JSContext, val: JSValue): JSResult[T] = +proc fromJSTuple[T: tuple](ctx: JSContext; val: JSValue): JSResult[T] = let itprop = JS_GetProperty(ctx, val, ctx.getOpaque().sym_refs[ITERATOR]) if JS_IsException(itprop): return err() @@ -186,7 +189,7 @@ proc fromJSTuple[T: tuple](ctx: JSContext, val: JSValue): JSResult[T] = fromJSTupleBody(x) return ok(x) -proc fromJSSeq[T](ctx: JSContext, val: JSValue): JSResult[seq[T]] = +proc fromJSSeq[T](ctx: JSContext; val: JSValue): JSResult[seq[T]] = let itprop = JS_GetProperty(ctx, val, ctx.getOpaque().sym_refs[ITERATOR]) if JS_IsException(itprop): return err() @@ -220,7 +223,7 @@ proc fromJSSeq[T](ctx: JSContext, val: JSValue): JSResult[seq[T]] = s.add(genericRes) return ok(s) -proc fromJSSet[T](ctx: JSContext, val: JSValue): JSResult[set[T]] = +proc fromJSSet[T](ctx: JSContext; val: JSValue): JSResult[set[T]] = let itprop = JS_GetProperty(ctx, val, ctx.getOpaque().sym_refs[ITERATOR]) if JS_IsException(itprop): return err() @@ -254,7 +257,7 @@ proc fromJSSet[T](ctx: JSContext, val: JSValue): JSResult[set[T]] = s.incl(genericRes) return ok(s) -proc fromJSTable[A, B](ctx: JSContext, val: JSValue): JSResult[Table[A, B]] = +proc fromJSTable[A, B](ctx: JSContext; val: JSValue): JSResult[Table[A, B]] = if not JS_IsObject(val): return err(newTypeError("object expected")) var ptab: ptr UncheckedArray[JSPropertyEnum] @@ -287,13 +290,13 @@ template optionType[T](o: type Option[T]): auto = # or null. (This is rather pointless for anything else.) # Opt is for passing down exceptions received up in the chain. # So e.g. none(T) translates to JS_NULL, but err() translates to JS_EXCEPTION. -proc fromJSOption[T](ctx: JSContext, val: JSValue): JSResult[Option[T]] = +proc fromJSOption[T](ctx: JSContext; val: JSValue): JSResult[Option[T]] = if JS_IsNull(val): return ok(none(T)) let res = ?fromJS[T](ctx, val) return ok(option(res)) -proc fromJSBool(ctx: JSContext, val: JSValue): JSResult[bool] = +proc fromJSBool(ctx: JSContext; val: JSValue): JSResult[bool] = let ret = JS_ToBool(ctx, val) if ret == -1: # exception return err() @@ -301,7 +304,7 @@ proc fromJSBool(ctx: JSContext, val: JSValue): JSResult[bool] = return ok(false) return ok(true) -proc fromJSEnum[T: enum](ctx: JSContext, val: JSValue): JSResult[T] = +proc fromJSEnum[T: enum](ctx: JSContext; val: JSValue): JSResult[T] = if JS_IsException(val): return err() let s = ?toString(ctx, val) @@ -310,7 +313,7 @@ proc fromJSEnum[T: enum](ctx: JSContext, val: JSValue): JSResult[T] = return ok(r.get) return errTypeError("`" & s & "' is not a valid value for enumeration " & $T) -proc fromJSPObj0(ctx: JSContext, val: JSValue, t: string): +proc fromJSPObj0(ctx: JSContext; val: JSValue; t: string): JSResult[pointer] = if JS_IsException(val): return err(nil) @@ -326,15 +329,15 @@ proc fromJSPObj0(ctx: JSContext, val: JSValue, t: string): let op = JS_GetOpaque(val, classid) return ok(op) -proc fromJSObject[T: ref object](ctx: JSContext, val: JSValue): JSResult[T] = +proc fromJSObject[T: ref object](ctx: JSContext; val: JSValue): JSResult[T] = return ok(cast[T](?fromJSPObj0(ctx, val, $T))) -proc fromJSVoid(ctx: JSContext, val: JSValue): JSResult[void] = +proc fromJSVoid(ctx: JSContext; val: JSValue): JSResult[void] = if JS_IsException(val): return err() return ok() -proc fromJSDict[T: JSDict](ctx: JSContext, val: JSValue): JSResult[T] = +proc fromJSDict[T: JSDict](ctx: JSContext; val: JSValue): JSResult[T] = if not JS_IsUndefined(val) and not JS_IsNull(val) and not JS_IsObject(val): return err(newTypeError("Dictionary is not an object")) #TODO throw on missing required values @@ -346,7 +349,7 @@ proc fromJSDict[T: JSDict](ctx: JSContext, val: JSValue): JSResult[T] = v = ?fromJS[typeof(v)](ctx, esm) return ok(d) -proc fromJSArrayBuffer(ctx: JSContext, val: JSValue): JSResult[JSArrayBuffer] = +proc fromJSArrayBuffer(ctx: JSContext; val: JSValue): JSResult[JSArrayBuffer] = var len: csize_t let p = JS_GetArrayBuffer(ctx, addr len, val) if p == nil: @@ -357,7 +360,7 @@ proc fromJSArrayBuffer(ctx: JSContext, val: JSValue): JSResult[JSArrayBuffer] = ) return ok(abuf) -proc fromJSArrayBufferView(ctx: JSContext, val: JSValue): +proc fromJSArrayBufferView(ctx: JSContext; val: JSValue): JSResult[JSArrayBufferView] = var offset: csize_t var nmemb: csize_t @@ -373,15 +376,15 @@ proc fromJSArrayBufferView(ctx: JSContext, val: JSValue): ) return ok(view) -proc promiseThenCallback(ctx: JSContext, this_val: JSValue, argc: cint, - argv: ptr JSValue, magic: cint, func_data: ptr JSValue): JSValue {.cdecl.} = +proc promiseThenCallback(ctx: JSContext; this_val: JSValue; argc: cint; + argv: ptr JSValue; magic: cint; func_data: ptr JSValue): JSValue {.cdecl.} = let op = JS_GetOpaque(func_data[], JS_GetClassID(func_data[])) let p = cast[EmptyPromise](op) p.resolve() GC_unref(p) return JS_UNDEFINED -proc fromJSEmptyPromise(ctx: JSContext, val: JSValue): JSResult[EmptyPromise] = +proc fromJSEmptyPromise(ctx: JSContext; val: JSValue): JSResult[EmptyPromise] = if not JS_IsObject(val): return err(newTypeError("Value is not an object")) #TODO I have a feeling this leaks memory in some cases :( @@ -403,7 +406,7 @@ macro fromJS2(ctx: JSContext; val: JSValue; x: static string): untyped = return quote do: `id`(`ctx`, `val`) -proc fromJS*[T](ctx: JSContext, val: JSValue): JSResult[T] = +proc fromJS*[T](ctx: JSContext; val: JSValue): JSResult[T] = when T is string: return fromJSString(ctx, val) elif T is Option: @@ -447,7 +450,7 @@ const JS_ATOM_TAG_INT = cuint(1u32 shl 31) func JS_IsNumber*(v: JSAtom): JS_BOOL = return (cast[cuint](v) and JS_ATOM_TAG_INT) != 0 -func fromJS*[T: string|uint32](ctx: JSContext, atom: JSAtom): Opt[T] = +func fromJS*[T: string|uint32](ctx: JSContext; atom: JSAtom): Opt[T] = when T is SomeNumber: if JS_IsNumber(atom): return ok(T(cast[uint32](atom) and (not JS_ATOM_TAG_INT))) @@ -455,10 +458,10 @@ func fromJS*[T: string|uint32](ctx: JSContext, atom: JSAtom): Opt[T] = let val = JS_AtomToValue(ctx, atom) return toString(ctx, val) -proc fromJSPObj[T](ctx: JSContext, val: JSValue): JSResult[ptr T] = +proc fromJSPObj[T](ctx: JSContext; val: JSValue): JSResult[ptr T] = return cast[JSResult[ptr T]](fromJSPObj0(ctx, val, $T)) -template fromJSP*[T](ctx: JSContext, val: JSValue): untyped = +template fromJSP*[T](ctx: JSContext; val: JSValue): untyped = when T is FromJSAllowedT: fromJSPObj[T](ctx, val) else: diff --git a/src/js/intl.nim b/src/js/intl.nim index 9e17edf3..8be5a768 100644 --- a/src/js/intl.nim +++ b/src/js/intl.nim @@ -17,8 +17,8 @@ jsDestructor(NumberFormat) jsDestructor(PluralRules) #TODO ...yeah -proc newNumberFormat(name: string = "en-US", - options = none(JSValue)): NumberFormat {.jsctor.} = +proc newNumberFormat(name: string = "en-US"; options = none(JSValue)): + NumberFormat {.jsctor.} = return NumberFormat() #TODO @@ -31,7 +31,7 @@ proc resolvedOptions(this: PluralRules): PRResolvedOptions {.jsfunc.} = ) #TODO: this should accept string/BigInt too -proc format(nf: NumberFormat, num: float64): string {.jsfunc.} = +proc format(nf: NumberFormat; num: float64): string {.jsfunc.} = let s = $num var i = 0 var L = s.len diff --git a/src/js/javascript.nim b/src/js/javascript.nim index ef848038..f2f72979 100644 --- a/src/js/javascript.nim +++ b/src/js/javascript.nim @@ -99,28 +99,28 @@ type ctorBody: NimNode BoundFunctionType = enum - FUNCTION = "js_func" - CONSTRUCTOR = "js_ctor" - GETTER = "js_get" - SETTER = "js_set" - PROPERTY_GET = "js_prop_get" - PROPERTY_SET = "js_prop_set" - PROPERTY_DEL = "js_prop_del" - PROPERTY_HAS = "js_prop_has" - PROPERTY_NAMES = "js_prop_names" - FINALIZER = "js_fin" + bfFunction = "js_func" + bfConstructor = "js_ctor" + bfGetter = "js_get" + bfSetter = "js_set" + bfPropertyGet = "js_prop_get" + bfPropertySet = "js_prop_set" + bfPropertyDel = "js_prop_del" + bfPropertyHas = "js_prop_has" + bfPropertyNames = "js_prop_names" + bfFinalizer = "js_fin" var runtimes {.threadvar.}: seq[JSRuntime] -proc bindMalloc(s: ptr JSMallocState, size: csize_t): pointer {.cdecl.} = +proc bindMalloc(s: ptr JSMallocState; size: csize_t): pointer {.cdecl.} = return alloc(size) -proc bindFree(s: ptr JSMallocState, p: pointer) {.cdecl.} = +proc bindFree(s: ptr JSMallocState; p: pointer) {.cdecl.} = if p == nil: return dealloc(p) -proc bindRealloc(s: ptr JSMallocState, p: pointer, size: csize_t): pointer +proc bindRealloc(s: ptr JSMallocState; p: pointer; size: csize_t): pointer {.cdecl.} = return realloc(p, size) @@ -147,16 +147,17 @@ proc newJSContext*(rt: JSRuntime): JSContext = JS_SetContextOpaque(ctx, cast[pointer](opaque)) return ctx -func getClass*(ctx: JSContext, class: string): JSClassID = +func getClass*(ctx: JSContext; class: string): JSClassID = # This function *should* never fail. ctx.getOpaque().creg[class] -func hasClass*(ctx: JSContext, class: type): bool = +func hasClass*(ctx: JSContext; class: type): bool = return $class in ctx.getOpaque().creg -func newJSCFunction*(ctx: JSContext, name: string, fun: JSCFunction, - argc: int = 0, proto = JS_CFUNC_generic, magic = 0): JSValue = - return JS_NewCFunction2(ctx, fun, cstring(name), cint(argc), proto, cint(magic)) +func newJSCFunction*(ctx: JSContext; name: string; fun: JSCFunction; + argc = 0; proto = JS_CFUNC_generic; magic = 0): JSValue = + return JS_NewCFunction2(ctx, fun, cstring(name), cint(argc), proto, + cint(magic)) proc free*(ctx: var JSContext) = var opaque = ctx.getOpaque() @@ -234,8 +235,8 @@ proc runJSJobs*(rt: JSRuntime; err: DynStream) = # Since every prototype has a list of all its ancestor's LegacyUnforgeable # functions, it is sufficient to simply merge the new list of new classes # with their parent's list to achieve this. -proc addClassUnforgeable(ctx: JSContext, proto: JSValue, - classid, parent: JSClassID, ourUnforgeable: JSFunctionList) = +proc addClassUnforgeable(ctx: JSContext; proto: JSValue; + classid, parent: JSClassID; ourUnforgeable: JSFunctionList) = let ctxOpaque = ctx.getOpaque() var merged = @ourUnforgeable ctxOpaque.unforgeable.withValue(parent, uf): @@ -245,18 +246,19 @@ proc addClassUnforgeable(ctx: JSContext, proto: JSValue, let ufp = addr ctxOpaque.unforgeable[classid][0] JS_SetPropertyFunctionList(ctx, proto, ufp, cint(merged.len)) -func newJSClass*(ctx: JSContext, cdef: JSClassDefConst, tname: string, - nimt: pointer, ctor: JSCFunction, funcs: JSFunctionList, parent: JSClassID, - asglobal: bool, nointerface: bool, finalizer: JSFinalizerFunction, - namespace: JSValue, errid: Opt[JSErrorEnum], - unforgeable, staticfuns: JSFunctionList, +func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; tname: string; + nimt: pointer; ctor: JSCFunction; funcs: JSFunctionList; parent: JSClassID; + asglobal: bool; nointerface: bool; finalizer: JSFinalizerFunction; + namespace: JSValue; errid: Opt[JSErrorEnum]; + unforgeable, staticfuns: JSFunctionList; ishtmldda: bool): JSClassID {.discardable.} = let rt = JS_GetRuntime(ctx) discard JS_NewClassID(addr result) var ctxOpaque = ctx.getOpaque() var rtOpaque = rt.getOpaque() if JS_NewClass(rt, result, cdef) != 0: - raise newException(Defect, "Failed to allocate JS class: " & $cdef.class_name) + raise newException(Defect, "Failed to allocate JS class: " & + $cdef.class_name) ctxOpaque.typemap[nimt] = result ctxOpaque.creg[tname] = result ctxOpaque.parents[result] = parent @@ -276,7 +278,8 @@ func newJSClass*(ctx: JSContext, cdef: JSClassDefConst, tname: string, # (QuickJS uses the pointer later.) #TODO maybe put them in ctxOpaque instead? rtOpaque.flist.add(@funcs) - JS_SetPropertyFunctionList(ctx, proto, addr rtOpaque.flist[^1][0], cint(funcs.len)) + JS_SetPropertyFunctionList(ctx, proto, addr rtOpaque.flist[^1][0], + cint(funcs.len)) #TODO check if this is an indexed property getter if cdef.exotic != nil and cdef.exotic.get_own_property != nil: let val = JS_DupValue(ctx, ctxOpaque.Array_prototype_values) @@ -298,7 +301,8 @@ func newJSClass*(ctx: JSContext, cdef: JSClassDefConst, tname: string, ctxOpaque.unforgeable.withValue(result, uf): JS_SetPropertyFunctionList(ctx, global, addr uf[][0], cint(uf[].len)) JS_FreeValue(ctx, global) - let jctor = ctx.newJSCFunction($cdef.class_name, ctor, 0, JS_CFUNC_constructor) + let jctor = ctx.newJSCFunction($cdef.class_name, ctor, 0, + JS_CFUNC_constructor) if staticfuns.len > 0: rtOpaque.flist.add(@staticfuns) JS_SetPropertyFunctionList(ctx, jctor, addr rtOpaque.flist[^1][0], @@ -315,7 +319,11 @@ func newJSClass*(ctx: JSContext, cdef: JSClassDefConst, tname: string, else: ctx.definePropertyCW(namespace, $cdef.class_name, jctor) -type FuncParam = tuple[name: string, t: NimNode, val: Option[NimNode], generic: Option[NimNode]] +type FuncParam = tuple + name: string + t: NimNode + val: Option[NimNode] + generic: Option[NimNode] func getMinArgs(params: seq[FuncParam]): int = for i in 0..<params.len: @@ -329,17 +337,17 @@ func getMinArgs(params: seq[FuncParam]): int = return i return params.len -func fromJSP[T: string|uint32](ctx: JSContext, atom: JSAtom): Opt[T] = +func fromJSP[T: string|uint32](ctx: JSContext; atom: JSAtom): Opt[T] = return fromJS[T](ctx, atom) -proc defineConsts*[T](ctx: JSContext, classid: JSClassID, +proc defineConsts*[T](ctx: JSContext; classid: JSClassID; consts: static openArray[(string, T)]) = let proto = ctx.getOpaque().ctors[classid] for (k, v) in consts: ctx.definePropertyE(proto, k, v) -proc defineConsts*(ctx: JSContext, classid: JSClassID, - consts: typedesc[enum], astype: typedesc) = +proc defineConsts*(ctx: JSContext; classid: JSClassID; + consts: typedesc[enum]; astype: typedesc) = let proto = ctx.getOpaque().ctors[classid] for e in consts: ctx.definePropertyE(proto, $e, astype(e)) @@ -358,7 +366,8 @@ type newName: NimNode newBranchList: seq[NimNode] errval: NimNode # JS_EXCEPTION or -1 - dielabel: NimNode # die: didn't match parameters, but could still match other ones + # die: didn't match parameters, but could still match other ones + dielabel: NimNode jsFunCallLists: seq[NimNode] jsFunCallList: NimNode jsFunCall: NimNode @@ -400,8 +409,10 @@ proc getGenerics(fun: NimNode): Table[string, seq[NimNode]] = assert gen_name != nil gen_types.add(node) of nnkInfix: - assert node[0].eqIdent(ident("|")) or node[0].eqIdent(ident("or")), "Only OR generics are supported." - for i in countdown(node.len - 1, 1): stack.add(node[i]) # except infix ident + assert node[0].eqIdent(ident("|")) or node[0].eqIdent(ident("or")), + "Only OR generics are supported." + for i in countdown(node.len - 1, 1): # except infix ident + stack.add(node[i]) of nnkBracketExpr: gen_types.add(node) else: @@ -542,7 +553,8 @@ template fromJS_or_die*(t, ctx, val, ev, dl: untyped): untyped = break dl x.get -proc addParam2(gen: var JSFuncGenerator, s, t, val: NimNode, fallback: NimNode = nil) = +proc addParam2(gen: var JSFuncGenerator; s, t, val: NimNode; + fallback: NimNode = nil) = let ev = gen.errval let dl = gen.dielabel let stmt = quote do: @@ -558,11 +570,13 @@ proc addParam2(gen: var JSFuncGenerator, s, t, val: NimNode, fallback: NimNode = else: `fallback`)) -proc addValueParam(gen: var JSFuncGenerator, s, t: NimNode, fallback: NimNode = nil) = +proc addValueParam(gen: var JSFuncGenerator; s, t: NimNode; + fallback: NimNode = nil) = let j = gen.j gen.addParam2(s, t, quote do: argv[`j`], fallback) -proc addUnionParamBranch(gen: var JSFuncGenerator, query, newBranch: NimNode, fallback: NimNode = nil) = +proc addUnionParamBranch(gen: var JSFuncGenerator; query, newBranch: NimNode; + fallback: NimNode = nil) = let i = gen.i let query = if fallback == nil: query else: quote do: (`i` < argc and `query`) @@ -575,7 +589,7 @@ proc addUnionParamBranch(gen: var JSFuncGenerator, query, newBranch: NimNode, fa gen.jsFunCallLists[i] = oldBranch gen.newBranchList.add(newBranch) -func isSequence*(ctx: JSContext, o: JSValue): bool = +func isSequence*(ctx: JSContext; o: JSValue): bool = if not JS_IsObject(o): return false let prop = JS_GetProperty(ctx, o, ctx.getOpaque().sym_refs[ITERATOR]) @@ -583,7 +597,7 @@ func isSequence*(ctx: JSContext, o: JSValue): bool = result = not JS_IsUndefined(prop) JS_FreeValue(ctx, prop) -proc addUnionParam0(gen: var JSFuncGenerator, tt, s, val: NimNode, +proc addUnionParam0(gen: var JSFuncGenerator; tt, s, val: NimNode; fallback: NimNode = nil) = # Union types. #TODO quite a few types are still missing. @@ -695,12 +709,12 @@ proc addUnionParam0(gen: var JSFuncGenerator, tt, s, val: NimNode, gen.jsFunCallLists.add(branch) gen.newBranchList.setLen(0) -proc addUnionParam(gen: var JSFuncGenerator, tt: NimNode, s: NimNode, +proc addUnionParam(gen: var JSFuncGenerator; tt, s: NimNode; fallback: NimNode = nil) = let j = gen.j gen.addUnionParam0(tt, s, quote do: argv[`j`], fallback) -proc addFixParam(gen: var JSFuncGenerator, name: string) = +proc addFixParam(gen: var JSFuncGenerator; name: string) = let s = ident("arg_" & $gen.i) let t = gen.funcParams[gen.i][1] let id = ident(name) @@ -763,15 +777,15 @@ proc finishFunCallList(gen: var JSFuncGenerator) = var existingFuncs {.compileTime.}: HashSet[string] var jsDtors {.compileTime.}: HashSet[string] -proc registerFunction(typ: string, nf: BoundFunction) = +proc registerFunction(typ: string; nf: BoundFunction) = BoundFunctions.withValue(typ, val): val[].add(nf) do: BoundFunctions[typ] = @[nf] existingFuncs.incl(nf.id.strVal) -proc registerFunction(typ: string, t: BoundFunctionType, name: string, - id: NimNode, magic: uint16 = 0, uf = false, isstatic = false, +proc registerFunction(typ: string; t: BoundFunctionType; name: string; + id: NimNode; magic: uint16 = 0; uf = false; isstatic = false; ctorBody: NimNode = nil) = registerFunction(typ, BoundFunction( t: t, @@ -783,7 +797,7 @@ proc registerFunction(typ: string, t: BoundFunctionType, name: string, ctorBody: ctorBody )) -proc registerConstructor(gen: JSFuncGenerator, jsProc: NimNode) = +proc registerConstructor(gen: JSFuncGenerator; jsProc: NimNode) = registerFunction(gen.thisType, gen.t, gen.funcName, gen.newName, uf = gen.unforgeable, isstatic = gen.isstatic, ctorBody = jsProc) @@ -794,7 +808,7 @@ proc registerFunction(gen: JSFuncGenerator) = export JS_ThrowTypeError, JS_ThrowRangeError, JS_ThrowSyntaxError, JS_ThrowInternalError, JS_ThrowReferenceError -proc newJSProcBody(gen: var JSFuncGenerator, isva: bool): NimNode = +proc newJSProcBody(gen: var JSFuncGenerator; isva: bool): NimNode = let tt = gen.thisType let fn = gen.funcName let ma = gen.actualMinArgs @@ -817,13 +831,13 @@ proc newJSProcBody(gen: var JSFuncGenerator, isva: bool): NimNode = ) result.add(gen.jsCallAndRet) -proc newJSProc(gen: var JSFuncGenerator, params: openArray[NimNode], +proc newJSProc(gen: var JSFuncGenerator; params: openArray[NimNode]; isva = true): NimNode = let jsBody = gen.newJSProcBody(isva) let jsPragmas = newNimNode(nnkPragma).add(ident("cdecl")) return newProc(gen.newName, params, jsBody, pragmas = jsPragmas) -func getFuncName(fun: NimNode, jsname, staticName: string): string = +func getFuncName(fun: NimNode; jsname, staticName: string): string = if jsname != "": return jsname if staticName != "": @@ -837,8 +851,8 @@ func getFuncName(fun: NimNode, jsname, staticName: string): string = return x func getErrVal(t: BoundFunctionType): NimNode = - if t in {PROPERTY_GET, PROPERTY_SET, PROPERTY_DEL, PROPERTY_HAS, - PROPERTY_NAMES}: + if t in {bfPropertyGet, bfPropertySet, bfPropertyDel, bfPropertyHas, + bfPropertyNames}: return quote do: cint(-1) return quote do: JS_EXCEPTION @@ -851,7 +865,7 @@ proc addJSContext(gen: var JSFuncGenerator) = elif gen.funcParams[gen.i].t.eqIdent(ident("JSRuntime")): inc gen.i # special case for finalizers that have a JSRuntime param -proc addThisName(gen: var JSFuncGenerator, thisname: Option[string]) = +proc addThisName(gen: var JSFuncGenerator; thisname: Option[string]) = if thisname.isSome: gen.thisTypeNode = gen.funcParams[gen.i][1] gen.thisType = $gen.funcParams[gen.i][1] @@ -879,9 +893,8 @@ func getActualMinArgs(gen: var JSFuncGenerator): int = assert ma >= 0 return ma -proc initGenerator(fun: NimNode, t: BoundFunctionType, - thisname = some("this"), jsname: string = "", unforgeable = false, - staticName = ""): JSFuncGenerator = +proc initGenerator(fun: NimNode; t: BoundFunctionType; thisname = some("this"); + jsname = ""; unforgeable = false; staticName = ""): JSFuncGenerator = let jsFunCallList = newStmtList() let funcParams = getParams(fun) var gen = JSFuncGenerator( @@ -909,7 +922,7 @@ proc initGenerator(fun: NimNode, t: BoundFunctionType, gen.newName = ident($gen.t & "_" & gen.funcName) return gen -proc makeJSCallAndRet(gen: var JSFuncGenerator, okstmt, errstmt: NimNode) = +proc makeJSCallAndRet(gen: var JSFuncGenerator; okstmt, errstmt: NimNode) = let jfcl = gen.jsFunCallList let dl = gen.dielabel gen.jsCallAndRet = if gen.returnType.isSome: @@ -924,7 +937,7 @@ proc makeJSCallAndRet(gen: var JSFuncGenerator, okstmt, errstmt: NimNode) = `okstmt` `errstmt` -proc makeCtorJSCallAndRet(gen: var JSFuncGenerator, errstmt: NimNode) = +proc makeCtorJSCallAndRet(gen: var JSFuncGenerator; errstmt: NimNode) = let jfcl = gen.jsFunCallList let dl = gen.dielabel gen.jsCallAndRet = quote do: @@ -933,7 +946,7 @@ proc makeCtorJSCallAndRet(gen: var JSFuncGenerator, errstmt: NimNode) = `errstmt` macro jsctor*(fun: typed) = - var gen = initGenerator(fun, CONSTRUCTOR, thisname = none(string)) + var gen = initGenerator(fun, bfConstructor, thisname = none(string)) if gen.newName.strVal in existingFuncs: #TODO TODO TODO implement function overloading error("Function overloading hasn't been implemented yet...") @@ -948,7 +961,7 @@ macro jsctor*(fun: typed) = return newStmtList(fun) macro jshasprop*(fun: typed) = - var gen = initGenerator(fun, PROPERTY_HAS, thisname = some("obj")) + var gen = initGenerator(fun, bfPropertyHas, thisname = some("obj")) if gen.newName.strVal in existingFuncs: #TODO TODO TODO ditto error("Function overloading hasn't been implemented yet...") @@ -967,7 +980,7 @@ macro jshasprop*(fun: typed) = return newStmtList(fun, jsProc) macro jsgetprop*(fun: typed) = - var gen = initGenerator(fun, PROPERTY_GET, thisname = some("obj")) + var gen = initGenerator(fun, bfPropertyGet, thisname = some("obj")) if gen.newName.strVal in existingFuncs: #TODO TODO TODO ditto error("Function overloading hasn't been implemented yet...") @@ -996,7 +1009,7 @@ macro jsgetprop*(fun: typed) = return newStmtList(fun, jsProc) macro jssetprop*(fun: typed) = - var gen = initGenerator(fun, PROPERTY_SET, thisname = some("obj")) + var gen = initGenerator(fun, bfPropertySet, thisname = some("obj")) if gen.newName.strVal in existingFuncs: #TODO TODO TODO ditto error("Function overloading hasn't been implemented yet...") @@ -1024,7 +1037,7 @@ macro jssetprop*(fun: typed) = return newStmtList(fun, jsProc) macro jsdelprop*(fun: typed) = - var gen = initGenerator(fun, PROPERTY_DEL, thisname = some("obj")) + var gen = initGenerator(fun, bfPropertyDel, thisname = some("obj")) if gen.newName.strVal in existingFuncs: #TODO TODO TODO ditto error("Function overloading hasn't been implemented yet...") @@ -1043,7 +1056,7 @@ macro jsdelprop*(fun: typed) = return newStmtList(fun, jsProc) macro jspropnames*(fun: typed) = - var gen = initGenerator(fun, PROPERTY_NAMES, thisname = some("obj")) + var gen = initGenerator(fun, bfPropertyNames, thisname = some("obj")) if gen.newName.strVal in existingFuncs: #TODO TODO TODO ditto error("Function overloading hasn't been implemented yet...") @@ -1062,8 +1075,8 @@ macro jspropnames*(fun: typed) = gen.registerFunction() return newStmtList(fun, jsProc) -macro jsfgetn(jsname: static string, uf: static bool, fun: typed) = - var gen = initGenerator(fun, GETTER, jsname = jsname, unforgeable = uf) +macro jsfgetn(jsname: static string; uf: static bool; fun: typed) = + var gen = initGenerator(fun, bfGetter, jsname = jsname, unforgeable = uf) if gen.actualMinArgs != 0 or gen.funcParams.len != gen.minArgs: error("jsfget functions must only accept one parameter.") if gen.returnType.isNone: @@ -1085,16 +1098,16 @@ template jsfget*(fun: typed) = template jsuffget*(fun: typed) = jsfgetn("", true, fun) -template jsfget*(jsname: static string, fun: typed) = +template jsfget*(jsname: static string; fun: typed) = jsfgetn(jsname, false, fun) -template jsuffget*(jsname: static string, fun: typed) = +template jsuffget*(jsname: static string; fun: typed) = jsfgetn(jsname, true, fun) # Ideally we could simulate JS setters using nim setters, but nim setters # won't accept types that don't match their reflected field's type. -macro jsfsetn(jsname: static string, fun: typed) = - var gen = initGenerator(fun, SETTER, jsname = jsname) +macro jsfsetn(jsname: static string; fun: typed) = + var gen = initGenerator(fun, bfSetter, jsname = jsname) if gen.actualMinArgs != 1 or gen.funcParams.len != gen.minArgs: error("jsfset functions must accept two parameters") if gen.returnType.isSome: @@ -1118,15 +1131,16 @@ macro jsfsetn(jsname: static string, fun: typed) = template jsfset*(fun: typed) = jsfsetn("", fun) -template jsfset*(jsname: static string, fun: typed) = +template jsfset*(jsname: static string; fun: typed) = jsfsetn(jsname, fun) -macro jsfuncn*(jsname: static string, uf: static bool, - staticName: static string, fun: typed) = - var gen = initGenerator(fun, FUNCTION, jsname = jsname, unforgeable = uf, +macro jsfuncn*(jsname: static string; uf: static bool; + staticName: static string; fun: typed) = + var gen = initGenerator(fun, bfFunction, jsname = jsname, unforgeable = uf, staticName = staticName) if gen.minArgs == 0 and not gen.isstatic: - error("Zero-parameter functions are not supported. (Maybe pass Window or Client?)") + error("Zero-parameter functions are not supported. " & + "(Maybe pass Window or Client?)") if not gen.isstatic: gen.addFixParam("this") gen.addRequiredParams() @@ -1147,23 +1161,23 @@ template jsfunc*(fun: typed) = template jsuffunc*(fun: typed) = jsfuncn("", true, "", fun) -template jsfunc*(jsname: static string, fun: typed) = +template jsfunc*(jsname: static string; fun: typed) = jsfuncn(jsname, false, "", fun) -template jsuffunc*(jsname: static string, fun: typed) = +template jsuffunc*(jsname: static string; fun: typed) = jsfuncn(jsname, true, "", fun) -template jsstfunc*(name: static string, fun: typed) = +template jsstfunc*(name: static string; fun: typed) = jsfuncn("", false, name, fun) macro jsfin*(fun: typed) = - var gen = initGenerator(fun, FINALIZER, thisname = some("fin")) + var gen = initGenerator(fun, bfFinalizer, thisname = some("fin")) let finName = gen.newName let finFun = ident(gen.funcName) let t = gen.thisTypeNode if gen.minArgs == 1: let jsProc = quote do: - proc `finName`(rt: JSRuntime, val: JSValue) = + proc `finName`(rt: JSRuntime; val: JSValue) = let opaque = JS_GetOpaque(val, JS_GetClassID(val)) if opaque != nil: `finFun`(cast[`t`](opaque)) @@ -1171,7 +1185,7 @@ macro jsfin*(fun: typed) = result = newStmtList(fun, jsProc) elif gen.minArgs == 2: let jsProc = quote do: - proc `finName`(rt: JSRuntime, val: JSValue) = + proc `finName`(rt: JSRuntime; val: JSValue) = let opaque = JS_GetOpaque(val, JS_GetClassID(val)) if opaque != nil: `finFun`(rt, cast[`t`](opaque)) @@ -1191,7 +1205,7 @@ template jsgetset*(name: string) {.pragma.} template jsufget*() {.pragma.} template jsufget*(name: string) {.pragma.} -proc js_illegal_ctor*(ctx: JSContext, this: JSValue, argc: cint, +proc js_illegal_ctor*(ctx: JSContext; this: JSValue; argc: cint; argv: ptr UncheckedArray[JSValue]): JSValue {.cdecl.} = return JS_ThrowTypeError(ctx, "Illegal constructor") @@ -1339,7 +1353,7 @@ func jsname(info: RegistryInfo): string = return info.name return info.tname -proc newRegistryInfo(t: NimNode, name: string): RegistryInfo = +proc newRegistryInfo(t: NimNode; name: string): RegistryInfo = let info = RegistryInfo( t: t, name: name, @@ -1360,13 +1374,13 @@ proc newRegistryInfo(t: NimNode, name: string): RegistryInfo = warning("No destructor has been defined for type " & info.tname) return info -proc bindConstructor(stmts: NimNode, info: var RegistryInfo): NimNode = +proc bindConstructor(stmts: NimNode; info: var RegistryInfo): NimNode = if info.ctorFun != nil: stmts.add(info.ctorImpl) return info.ctorFun return ident("js_illegal_ctor") -proc registerGetters(stmts: NimNode, info: RegistryInfo, +proc registerGetters(stmts: NimNode; info: RegistryInfo; jsget: seq[JSObjectPragma]) = let t = info.t let tname = info.tname @@ -1374,9 +1388,9 @@ proc registerGetters(stmts: NimNode, info: RegistryInfo, for op in jsget: let node = op.varsym let fn = op.name - let id = ident($GETTER & "_" & tname & "_" & fn) + let id = ident($bfGetter & "_" & tname & "_" & fn) stmts.add(quote do: - proc `id`(ctx: JSContext, this: JSValue): JSValue {.cdecl.} = + proc `id`(ctx: JSContext; this: JSValue): JSValue {.cdecl.} = if not ctx.isInstanceOf(this, `tname`): return JS_ThrowTypeError(ctx, "'%s' called on an object that is not an instance of %s", `fn`, @@ -1388,13 +1402,13 @@ proc registerGetters(stmts: NimNode, info: RegistryInfo, return toJS(ctx, arg_0.`node`) ) registerFunction(tname, BoundFunction( - t: GETTER, + t: bfGetter, name: fn, id: id, unforgeable: op.unforgeable )) -proc registerSetters(stmts: NimNode, info: RegistryInfo, +proc registerSetters(stmts: NimNode; info: RegistryInfo; jsset: seq[JSObjectPragma]) = let t = info.t let tname = info.tname @@ -1402,9 +1416,9 @@ proc registerSetters(stmts: NimNode, info: RegistryInfo, for op in jsset: let node = op.varsym let fn = op.name - let id = ident($SETTER & "_" & tname & "_" & fn) + let id = ident($bfSetter & "_" & tname & "_" & fn) stmts.add(quote do: - proc `id`(ctx: JSContext, this: JSValue, val: JSValue): JSValue + proc `id`(ctx: JSContext; this: JSValue; val: JSValue): JSValue {.cdecl.} = if not ctx.isInstanceOf(this, `tname`): return JS_ThrowTypeError(ctx, @@ -1417,9 +1431,9 @@ proc registerSetters(stmts: NimNode, info: RegistryInfo, arg_0.`node` = fromJS_or_return(typeof(arg_0.`node`), ctx, arg_1) return JS_DupValue(ctx, arg_1) ) - registerFunction(tname, SETTER, fn, id) + registerFunction(tname, bfSetter, fn, id) -proc bindFunctions(stmts: NimNode, info: var RegistryInfo) = +proc bindFunctions(stmts: NimNode; info: var RegistryInfo) = BoundFunctions.withValue(info.tname, funs): for fun in funs[].mitems: var f0 = fun.name @@ -1427,7 +1441,7 @@ proc bindFunctions(stmts: NimNode, info: var RegistryInfo) = if fun.name.endsWith("_exceptions"): fun.name = fun.name.substr(0, fun.name.high - "_exceptions".len) case fun.t - of FUNCTION: + of bfFunction: f0 = fun.name if fun.unforgeable: info.tabUnforgeable.add(quote do: @@ -1438,48 +1452,48 @@ proc bindFunctions(stmts: NimNode, info: var RegistryInfo) = else: info.tabList.add(quote do: JS_CFUNC_DEF(`f0`, 0, cast[JSCFunction](`f1`))) - of CONSTRUCTOR: + of bfConstructor: info.ctorImpl = fun.ctorBody if info.ctorFun != nil: error("Class " & info.tname & " has 2+ constructors.") info.ctorFun = f1 - of GETTER: + of bfGetter: info.getset.withValue(f0, exv): exv[0] = f1 exv[2] = fun.unforgeable do: info.getset[f0] = (f1, newNilLit(), fun.unforgeable) - of SETTER: + of bfSetter: info.getset.withValue(f0, exv): exv[1] = f1 do: info.getset[f0] = (newNilLit(), f1, false) - of PROPERTY_GET: + of bfPropertyGet: if info.propGetFun.kind != nnkNilLit: error("Class " & info.tname & " has 2+ property getters.") info.propGetFun = f1 - of PROPERTY_SET: + of bfPropertySet: if info.propSetFun.kind != nnkNilLit: error("Class " & info.tname & " has 2+ property setters.") info.propSetFun = f1 - of PROPERTY_DEL: + of bfPropertyDel: if info.propDelFun.kind != nnkNilLit: error("Class " & info.tname & " has 2+ property setters.") info.propDelFun = f1 - of PROPERTY_HAS: + of bfPropertyHas: if info.propHasFun.kind != nnkNilLit: error("Class " & info.tname & " has 2+ hasprop getters.") info.propHasFun = f1 - of PROPERTY_NAMES: + of bfPropertyNames: if info.propNamesFun.kind != nnkNilLit: error("Class " & info.tname & " has 2+ propnames getters.") info.propNamesFun = f1 - of FINALIZER: + of bfFinalizer: f0 = fun.name info.finFun = ident(f0) info.finName = f1 -proc bindGetSet(stmts: NimNode, info: RegistryInfo) = +proc bindGetSet(stmts: NimNode; info: RegistryInfo) = for k, (get, set, unforgeable) in info.getset: if not unforgeable: info.tabList.add(quote do: JS_CGETSET_DEF(`k`, `get`, `set`)) @@ -1487,7 +1501,7 @@ proc bindGetSet(stmts: NimNode, info: RegistryInfo) = info.tabUnforgeable.add(quote do: JS_CGETSET_DEF_NOCONF(`k`, `get`, `set`)) -proc bindExtraGetSet(stmts: NimNode, info: var RegistryInfo, +proc bindExtraGetSet(stmts: NimNode; info: var RegistryInfo; extra_getset: openArray[TabGetSet]) = for x in extra_getset: let k = x.name @@ -1496,11 +1510,11 @@ proc bindExtraGetSet(stmts: NimNode, info: var RegistryInfo, let m = x.magic info.tabList.add(quote do: JS_CGETSET_MAGIC_DEF(`k`, `g`, `s`, `m`)) -proc bindCheckDestroy(stmts: NimNode, info: RegistryInfo) = +proc bindCheckDestroy(stmts: NimNode; info: RegistryInfo) = let t = info.t let dfin = info.dfin stmts.add(quote do: - proc `dfin`(rt: JSRuntime, val: JSValue): JS_BOOL {.cdecl.} = + proc `dfin`(rt: JSRuntime; val: JSValue): JS_BOOL {.cdecl.} = let opaque = JS_GetOpaque(val, JS_GetClassID(val)) if opaque != nil: when `t` is ref object: @@ -1549,7 +1563,7 @@ proc bindCheckDestroy(stmts: NimNode, info: RegistryInfo) = return true ) -proc bindEndStmts(endstmts: NimNode, info: RegistryInfo) = +proc bindEndStmts(endstmts: NimNode; info: RegistryInfo) = let jsname = info.jsname let dfin = info.dfin let classDef = info.classDef @@ -1586,7 +1600,7 @@ proc bindEndStmts(endstmts: NimNode, info: RegistryInfo) = ) let `classDef` = JSClassDefConst(addr cd)) -macro registerType*(ctx: typed, t: typed, parent: JSClassID = 0, +macro registerType*(ctx: typed; t: typed; parent: JSClassID = 0, asglobal = false, nointerface = false, name: static string = "", has_extra_getset: static bool = false, extra_getset: static openArray[TabGetSet] = [], @@ -1625,7 +1639,7 @@ macro registerType*(ctx: typed, t: typed, parent: JSClassID = 0, proc getMemoryUsage*(rt: JSRuntime): string = var m: JSMemoryUsage JS_ComputeMemoryUsage(rt, addr m) - template row(title: string, count, size, sz2, cnt2: int64, name: string): + template row(title: string; count, size, sz2, cnt2: int64, name: string): string = let fv0 = $(float(sz2) / float(cnt2)) var fv = fv0.until('.') @@ -1634,10 +1648,10 @@ proc getMemoryUsage*(rt: JSRuntime): string = else: fv &= ".0" title & ": " & $count & " " & $size & " (" & fv & ")" & name & "\n" - template row(title: string, count, size, sz2: int64, name: string): + template row(title: string; count, size, sz2: int64, name: string): string = row(title, count, size, sz2, count, name) - template row(title: string, count, size: int64, name: string): string = + template row(title: string; count, size: int64, name: string): string = row(title, count, size, size, name) var s = "" if m.malloc_count != 0: @@ -1668,17 +1682,17 @@ proc getMemoryUsage*(rt: JSRuntime): string = $m.binary_object_size return s -proc eval*(ctx: JSContext, s: string, file: string, eval_flags: int): JSValue = +proc eval*(ctx: JSContext; s: string; file: string; eval_flags: int): JSValue = return JS_Eval(ctx, cstring(s), csize_t(s.len), cstring(file), cint(eval_flags)) -proc compileScript*(ctx: JSContext, s: string, file: cstring): JSValue = +proc compileScript*(ctx: JSContext; s: string; file: cstring): JSValue = return JS_Eval(ctx, cstring(s), csize_t(s.len), file, cint(JS_EVAL_FLAG_COMPILE_ONLY)) -proc compileModule*(ctx: JSContext, s: string, file: cstring): JSValue = +proc compileModule*(ctx: JSContext; s: string; file: cstring): JSValue = return JS_Eval(ctx, cstring(s), csize_t(s.len), file, cint(JS_EVAL_TYPE_MODULE or JS_EVAL_FLAG_COMPILE_ONLY)) -proc evalFunction*(ctx: JSContext, val: JSValue): JSValue = +proc evalFunction*(ctx: JSContext; val: JSValue): JSValue = return JS_EvalFunction(ctx, val) diff --git a/src/js/module.nim b/src/js/module.nim index fe080f13..2e15ead3 100644 --- a/src/js/module.nim +++ b/src/js/module.nim @@ -3,7 +3,7 @@ import bindings/quickjs import js/javascript import js/tojs -proc setImportMeta(ctx: JSContext, funcVal: JSValue, isMain: bool) = +proc setImportMeta(ctx: JSContext; funcVal: JSValue; isMain: bool) = let m = cast[JSModuleDef](JS_VALUE_GET_PTR(funcVal)) let moduleNameAtom = JS_GetModuleName(ctx, m) let moduleName = JS_AtomToCString(ctx, moduleNameAtom) @@ -14,7 +14,7 @@ proc setImportMeta(ctx: JSContext, funcVal: JSValue, isMain: bool) = JS_FreeAtom(ctx, moduleNameAtom) JS_FreeCString(ctx, moduleName) -proc finishLoadModule*(ctx: JSContext, f: string, name: cstring): JSModuleDef = +proc finishLoadModule*(ctx: JSContext; f: string; name: cstring): JSModuleDef = let funcVal = compileModule(ctx, f, name) if JS_IsException(funcVal): return nil @@ -24,6 +24,6 @@ proc finishLoadModule*(ctx: JSContext, f: string, name: cstring): JSModuleDef = result = cast[JSModuleDef](JS_VALUE_GET_PTR(funcVal)) JS_FreeValue(ctx, funcVal) -proc normalizeModuleName*(ctx: JSContext, base_name, name: cstringConst, +proc normalizeModuleName*(ctx: JSContext; base_name, name: cstringConst; opaque: pointer): cstring {.cdecl.} = return js_strdup(ctx, cstring(name)) diff --git a/src/js/opaque.nim b/src/js/opaque.nim index bff250d0..490747bc 100644 --- a/src/js/opaque.nim +++ b/src/js/opaque.nim @@ -38,7 +38,7 @@ type err_ctors*: array[JSErrorEnum, JSValue] htmldda*: JSClassID # only one of these exists: document.all. - JSFinalizerFunction* = proc(rt: JSRuntime, val: JSValue) {.nimcall.} + JSFinalizerFunction* = proc(rt: JSRuntime; val: JSValue) {.nimcall.} JSRuntimeOpaque* = ref object plist*: Table[pointer, pointer] # Nim, JS @@ -70,7 +70,8 @@ func newJSContextOpaque*(ctx: JSContext): JSContextOpaque = JS_FreeValue(ctx, arrproto) block: let objproto = JS_GetClassProto(ctx, JS_CLASS_OBJECT) - opaque.Object_prototype_valueOf = JS_GetPropertyStr(ctx, objproto, "valueOf") + opaque.Object_prototype_valueOf = JS_GetPropertyStr(ctx, objproto, + "valueOf") JS_FreeValue(ctx, objproto) block: opaque.Uint8Array_ctor = JS_GetPropertyStr(ctx, global, "Uint8Array") @@ -94,11 +95,11 @@ func getOpaque*(ctx: JSContext): JSContextOpaque = func getOpaque*(rt: JSRuntime): JSRuntimeOpaque = return cast[JSRuntimeOpaque](JS_GetRuntimeOpaque(rt)) -func isGlobal*(ctx: JSContext, class: string): bool = +func isGlobal*(ctx: JSContext; class: string): bool = assert class != "" return ctx.getOpaque().gclaz == class -proc setOpaque*(ctx: JSContext, val: JSValue, opaque: pointer) = +proc setOpaque*(ctx: JSContext; val: JSValue; opaque: pointer) = let rt = JS_GetRuntime(ctx) let rtOpaque = rt.getOpaque() let p = JS_VALUE_GET_PTR(val) @@ -110,8 +111,7 @@ func getOpaque0*(val: JSValue): pointer = if JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT: return JS_GetOpaque(val, JS_GetClassID(val)) -func getGlobalOpaque0*(ctx: JSContext, val: JSValue = JS_UNDEFINED): - Opt[pointer] = +func getGlobalOpaque0*(ctx: JSContext; val = JS_UNDEFINED): Opt[pointer] = let global = JS_GetGlobalObject(ctx) if JS_IsUndefined(val) or val == global: let opaque = JS_GetOpaque(global, JS_CLASS_OBJECT) @@ -120,10 +120,10 @@ func getGlobalOpaque0*(ctx: JSContext, val: JSValue = JS_UNDEFINED): JS_FreeValue(ctx, global) return err() -func getGlobalOpaque*(ctx: JSContext, T: typedesc, val: JSValue = JS_UNDEFINED): Opt[T] = +func getGlobalOpaque*(ctx: JSContext; T: typedesc; val = JS_UNDEFINED): Opt[T] = return ok(cast[T](?getGlobalOpaque0(ctx, val))) -func getOpaque*(ctx: JSContext, val: JSValue, class: string): pointer = +func getOpaque*(ctx: JSContext; val: JSValue; class: string): pointer = # Unfortunately, we can't change the global object's class. #TODO: or maybe we can, but I'm afraid of breaking something. # This needs further investigation. @@ -134,5 +134,5 @@ func getOpaque*(ctx: JSContext, val: JSValue, class: string): pointer = return opaque return getOpaque0(val) -func getOpaque*[T: ref object](ctx: JSContext, val: JSValue): T = +func getOpaque*[T: ref object](ctx: JSContext; val: JSValue): T = cast[T](getOpaque(ctx, val, $T)) diff --git a/src/js/propertyenumlist.nim b/src/js/propertyenumlist.nim index 98ad2a4f..65c16c2f 100644 --- a/src/js/propertyenumlist.nim +++ b/src/js/propertyenumlist.nim @@ -13,7 +13,7 @@ type is_enumerable: bool name: string -func newJSPropertyEnumList*(ctx: JSContext, size: uint32): JSPropertyEnumList = +func newJSPropertyEnumList*(ctx: JSContext; size: uint32): JSPropertyEnumList = let p = js_malloc(ctx, csize_t(sizeof(JSPropertyEnum)) * csize_t(size)) let buffer = cast[JSPropertyEnumArray](p) return JSPropertyEnumList( @@ -27,14 +27,14 @@ proc grow(this: var JSPropertyEnumList) = let p = js_realloc(this.ctx, this.buffer, csize_t(this.size)) this.buffer = cast[JSPropertyEnumArray](p) -proc add*(this: var JSPropertyEnumList, val: uint32) = +proc add*(this: var JSPropertyEnumList; val: uint32) = let i = this.len inc this.len if this.size < this.len: this.grow() this.buffer[i].atom = JS_NewAtomUInt32(this.ctx, val) -proc add*(this: var JSPropertyEnumList, val: string) = +proc add*(this: var JSPropertyEnumList; val: string) = let i = this.len inc this.len if this.size < this.len: diff --git a/src/js/regex.nim b/src/js/regex.nim index e189b430..f24633d1 100644 --- a/src/js/regex.nim +++ b/src/js/regex.nim @@ -49,7 +49,7 @@ proc compileRegex*(buf: string; flags: LREFlags = {}): Result[Regex, string] = ) return ok(regex) -func countBackslashes(buf: string, i: int): int = +func countBackslashes(buf: string; i: int): int = var j = 0 for i in countdown(i, 0): if buf[i] != '\\': diff --git a/src/js/tojs.nim b/src/js/tojs.nim index 807c85f5..4cbd2045 100644 --- a/src/js/tojs.nim +++ b/src/js/tojs.nim @@ -50,33 +50,33 @@ import types/opt # Convert Nim types to the corresponding JavaScript type. # This does not work with var objects. -proc toJS*(ctx: JSContext, s: string): JSValue -proc toJS*(ctx: JSContext, r: Rune): JSValue -proc toJS*(ctx: JSContext, n: int64): JSValue -proc toJS*(ctx: JSContext, n: int32): JSValue -proc toJS*(ctx: JSContext, n: int): JSValue -proc toJS*(ctx: JSContext, n: uint16): JSValue -proc toJS*(ctx: JSContext, n: uint32): JSValue -proc toJS*(ctx: JSContext, n: uint64): JSValue -proc toJS*(ctx: JSContext, n: float64): JSValue -proc toJS*(ctx: JSContext, b: bool): JSValue -proc toJS*[U, V](ctx: JSContext, t: Table[U, V]): JSValue -proc toJS*(ctx: JSContext, opt: Option): JSValue -proc toJS*[T, E](ctx: JSContext, opt: Result[T, E]): JSValue -proc toJS*(ctx: JSContext, s: seq): JSValue -proc toJS*[T](ctx: JSContext, s: set[T]): JSValue -proc toJS*(ctx: JSContext, t: tuple): JSValue -proc toJS*(ctx: JSContext, e: enum): JSValue -proc toJS*(ctx: JSContext, j: JSValue): JSValue -proc toJS*[T](ctx: JSContext, promise: Promise[T]): JSValue -proc toJS*[T, E](ctx: JSContext, promise: Promise[Result[T, E]]): JSValue -proc toJS*(ctx: JSContext, promise: EmptyPromise): JSValue -proc toJS*(ctx: JSContext, obj: ref object): JSValue -proc toJS*(ctx: JSContext, err: JSError): JSValue -proc toJS*(ctx: JSContext, abuf: JSArrayBuffer): JSValue -proc toJS*(ctx: JSContext, u8a: JSUint8Array): JSValue -proc toJS*(ctx: JSContext, ns: NarrowString): JSValue -proc toJS*(ctx: JSContext, dict: JSDict): JSValue +proc toJS*(ctx: JSContext; s: string): JSValue +proc toJS*(ctx: JSContext; r: Rune): JSValue +proc toJS*(ctx: JSContext; n: int64): JSValue +proc toJS*(ctx: JSContext; n: int32): JSValue +proc toJS*(ctx: JSContext; n: int): JSValue +proc toJS*(ctx: JSContext; n: uint16): JSValue +proc toJS*(ctx: JSContext; n: uint32): JSValue +proc toJS*(ctx: JSContext; n: uint64): JSValue +proc toJS*(ctx: JSContext; n: float64): JSValue +proc toJS*(ctx: JSContext; b: bool): JSValue +proc toJS*[U, V](ctx: JSContext; t: Table[U, V]): JSValue +proc toJS*(ctx: JSContext; opt: Option): JSValue +proc toJS*[T, E](ctx: JSContext; opt: Result[T, E]): JSValue +proc toJS*(ctx: JSContext; s: seq): JSValue +proc toJS*[T](ctx: JSContext; s: set[T]): JSValue +proc toJS*(ctx: JSContext; t: tuple): JSValue +proc toJS*(ctx: JSContext; e: enum): JSValue +proc toJS*(ctx: JSContext; j: JSValue): JSValue +proc toJS*[T](ctx: JSContext; promise: Promise[T]): JSValue +proc toJS*[T, E](ctx: JSContext; promise: Promise[Result[T, E]]): JSValue +proc toJS*(ctx: JSContext; promise: EmptyPromise): JSValue +proc toJS*(ctx: JSContext; obj: ref object): JSValue +proc toJS*(ctx: JSContext; err: JSError): JSValue +proc toJS*(ctx: JSContext; abuf: JSArrayBuffer): JSValue +proc toJS*(ctx: JSContext; u8a: JSUint8Array): JSValue +proc toJS*(ctx: JSContext; ns: NarrowString): JSValue +proc toJS*(ctx: JSContext; dict: JSDict): JSValue # Convert Nim types to the corresponding JavaScript type, with knowledge of # the parent object. @@ -85,20 +85,20 @@ proc toJS*(ctx: JSContext, dict: JSDict): JSValue # The idea here is to allow conversion of var objects to quasi-reference types # by saving a pointer to their ancestor and incrementing/decrementing the # ancestor's reference count instead. -proc toJSP*(ctx: JSContext, parent: ref object, child: var object): JSValue -proc toJSP*(ctx: JSContext, parent: ptr object, child: var object): JSValue +proc toJSP*(ctx: JSContext; parent: ref object; child: var object): JSValue +proc toJSP*(ctx: JSContext; parent: ptr object; child: var object): JSValue # Same as toJS, but used in constructors. ctor contains the target prototype, # used for subclassing from JS. -proc toJSNew*(ctx: JSContext, obj: ref object, ctor: JSValue): JSValue -proc toJSNew*[T, E](ctx: JSContext, opt: Result[T, E], ctor: JSValue): JSValue +proc toJSNew*(ctx: JSContext; obj: ref object; ctor: JSValue): JSValue +proc toJSNew*[T, E](ctx: JSContext; opt: Result[T, E]; ctor: JSValue): JSValue # Avoid accidentally calling toJSP on objects that we have explicit toJS # converters for. template makeToJSP(typ: untyped) = - template toJSP*(ctx: JSContext, parent: ref object, child: var typ): JSValue = + template toJSP*(ctx: JSContext; parent: ref object; child: var typ): JSValue = toJS(ctx, child) - template toJSP*(ctx: JSContext, parent: ptr object, child: var typ): JSValue = + template toJSP*(ctx: JSContext; parent: ptr object; child: var typ): JSValue = toJS(ctx, child) makeToJSP(Table) makeToJSP(Option) @@ -106,42 +106,42 @@ makeToJSP(Result) makeToJSP(JSValue) makeToJSP(JSDict) -proc defineProperty(ctx: JSContext, this: JSValue, name: JSAtom, - prop: JSValue, flags = cint(0)) = +proc defineProperty(ctx: JSContext; this: JSValue; name: JSAtom; + prop: JSValue; flags = cint(0)) = if JS_DefinePropertyValue(ctx, this, name, prop, flags) <= 0: raise newException(Defect, "Failed to define property string") -proc definePropertyC*(ctx: JSContext, this: JSValue, name: JSAtom, +proc definePropertyC*(ctx: JSContext; this: JSValue; name: JSAtom; prop: JSValue) = ctx.defineProperty(this, name, prop, JS_PROP_CONFIGURABLE) -proc defineProperty(ctx: JSContext, this: JSValue, name: string, - prop: JSValue, flags = cint(0)) = +proc defineProperty(ctx: JSContext; this: JSValue; name: string; + prop: JSValue; flags = cint(0)) = if JS_DefinePropertyValueStr(ctx, this, cstring(name), prop, flags) <= 0: raise newException(Defect, "Failed to define property string: " & name) -proc definePropertyC*(ctx: JSContext, this: JSValue, name: string, +proc definePropertyC*(ctx: JSContext; this: JSValue; name: string; prop: JSValue) = ctx.defineProperty(this, name, prop, JS_PROP_CONFIGURABLE) -proc defineProperty*[T](ctx: JSContext, this: JSValue, name: string, prop: T, +proc defineProperty*[T](ctx: JSContext; this: JSValue; name: string; prop: T; flags = cint(0)) = defineProperty(ctx, this, name, toJS(ctx, prop), flags) -proc definePropertyE*[T](ctx: JSContext, this: JSValue, name: string, +proc definePropertyE*[T](ctx: JSContext; this: JSValue; name: string; prop: T) = defineProperty(ctx, this, name, prop, JS_PROP_ENUMERABLE) -proc definePropertyCW*[T](ctx: JSContext, this: JSValue, name: string, +proc definePropertyCW*[T](ctx: JSContext; this: JSValue; name: string; prop: T) = defineProperty(ctx, this, name, prop, JS_PROP_CONFIGURABLE or JS_PROP_WRITABLE) -proc definePropertyCWE*[T](ctx: JSContext, this: JSValue, name: string, +proc definePropertyCWE*[T](ctx: JSContext; this: JSValue; name: string; prop: T) = defineProperty(ctx, this, name, prop, JS_PROP_C_W_E) -proc newFunction*(ctx: JSContext, args: openArray[string], body: string): +proc newFunction*(ctx: JSContext; args: openArray[string]; body: string): JSValue = var paramList: seq[JSValue] = @[] for arg in args: @@ -153,54 +153,54 @@ proc newFunction*(ctx: JSContext, args: openArray[string], body: string): JS_FreeValue(ctx, param) return fun -proc toJS*(ctx: JSContext, s: cstring): JSValue = +proc toJS*(ctx: JSContext; s: cstring): JSValue = return JS_NewString(ctx, s) -proc toJS*(ctx: JSContext, s: string): JSValue = +proc toJS*(ctx: JSContext; s: string): JSValue = return toJS(ctx, cstring(s)) -proc toJS*(ctx: JSContext, r: Rune): JSValue = +proc toJS*(ctx: JSContext; r: Rune): JSValue = return toJS(ctx, $r) -proc toJS*(ctx: JSContext, n: int32): JSValue = +proc toJS*(ctx: JSContext; n: int32): JSValue = return JS_NewInt32(ctx, n) -proc toJS*(ctx: JSContext, n: int64): JSValue = +proc toJS*(ctx: JSContext; n: int64): JSValue = return JS_NewInt64(ctx, n) # Always int32, so we don't risk 32-bit only breakage. -proc toJS*(ctx: JSContext, n: int): JSValue = +proc toJS*(ctx: JSContext; n: int): JSValue = return toJS(ctx, int32(n)) -proc toJS*(ctx: JSContext, n: uint16): JSValue = +proc toJS*(ctx: JSContext; n: uint16): JSValue = return JS_NewUint32(ctx, uint32(n)) -proc toJS*(ctx: JSContext, n: uint32): JSValue = +proc toJS*(ctx: JSContext; n: uint32): JSValue = return JS_NewUint32(ctx, n) -proc toJS*(ctx: JSContext, n: uint64): JSValue = +proc toJS*(ctx: JSContext; n: uint64): JSValue = #TODO this is incorrect return JS_NewFloat64(ctx, float64(n)) -proc toJS*(ctx: JSContext, n: float64): JSValue = +proc toJS*(ctx: JSContext; n: float64): JSValue = return JS_NewFloat64(ctx, n) -proc toJS*(ctx: JSContext, b: bool): JSValue = +proc toJS*(ctx: JSContext; b: bool): JSValue = return JS_NewBool(ctx, b) -proc toJS*[U, V](ctx: JSContext, t: Table[U, V]): JSValue = +proc toJS*[U, V](ctx: JSContext; t: Table[U, V]): JSValue = let obj = JS_NewObject(ctx) if not JS_IsException(obj): for k, v in t: definePropertyCWE(ctx, obj, k, v) return obj -proc toJS*(ctx: JSContext, opt: Option): JSValue = +proc toJS*(ctx: JSContext; opt: Option): JSValue = if opt.isSome: return toJS(ctx, opt.get) return JS_NULL -proc toJS[T, E](ctx: JSContext, opt: Result[T, E]): JSValue = +proc toJS[T, E](ctx: JSContext; opt: Result[T, E]): JSValue = if opt.isSome: when not (T is void): return toJS(ctx, opt.get) @@ -213,7 +213,7 @@ proc toJS[T, E](ctx: JSContext, opt: Result[T, E]): JSValue = return JS_Throw(ctx, res) return JS_EXCEPTION -proc toJS(ctx: JSContext, s: seq): JSValue = +proc toJS(ctx: JSContext; s: seq): JSValue = let a = JS_NewArray(ctx) if not JS_IsException(a): for i in 0..s.high: @@ -225,7 +225,7 @@ proc toJS(ctx: JSContext, s: seq): JSValue = return JS_EXCEPTION return a -proc toJS*[T](ctx: JSContext, s: set[T]): JSValue = +proc toJS*[T](ctx: JSContext; s: set[T]): JSValue = #TODO this is a bit lazy :p var x = newSeq[T]() for e in s: @@ -237,7 +237,7 @@ proc toJS*[T](ctx: JSContext, s: set[T]): JSValue = JS_FreeValue(ctx, a) return ret -proc toJS(ctx: JSContext, t: tuple): JSValue = +proc toJS(ctx: JSContext; t: tuple): JSValue = let a = JS_NewArray(ctx) if not JS_IsException(a): var i = 0 @@ -251,7 +251,7 @@ proc toJS(ctx: JSContext, t: tuple): JSValue = inc i return a -proc toJSP0(ctx: JSContext, p, tp: pointer, ctor: JSValue, +proc toJSP0(ctx: JSContext; p, tp: pointer; ctor: JSValue; needsref: var bool): JSValue = JS_GetRuntime(ctx).getOpaque().plist.withValue(p, obj): # a JSValue already points to this object. @@ -271,7 +271,7 @@ proc toJSP0(ctx: JSContext, p, tp: pointer, ctor: JSValue, JS_SetIsHTMLDDA(ctx, jsObj) return jsObj -proc toJSRefObj(ctx: JSContext, obj: ref object): JSValue = +proc toJSRefObj(ctx: JSContext; obj: ref object): JSValue = if obj == nil: return JS_NULL let p = cast[pointer](obj) @@ -282,10 +282,10 @@ proc toJSRefObj(ctx: JSContext, obj: ref object): JSValue = GC_ref(obj) return val -proc toJS*(ctx: JSContext, obj: ref object): JSValue = +proc toJS*(ctx: JSContext; obj: ref object): JSValue = return toJSRefObj(ctx, obj) -proc toJSNew*(ctx: JSContext, obj: ref object, ctor: JSValue): JSValue = +proc toJSNew*(ctx: JSContext; obj: ref object; ctor: JSValue): JSValue = if obj == nil: return JS_NULL let p = cast[pointer](obj) @@ -296,7 +296,7 @@ proc toJSNew*(ctx: JSContext, obj: ref object, ctor: JSValue): JSValue = GC_ref(obj) return val -proc toJSNew[T, E](ctx: JSContext, opt: Result[T, E], ctor: JSValue): JSValue = +proc toJSNew[T, E](ctx: JSContext; opt: Result[T, E], ctor: JSValue): JSValue = if opt.isSome: when not (T is void): return toJSNew(ctx, opt.get, ctor) @@ -310,13 +310,13 @@ proc toJSNew[T, E](ctx: JSContext, opt: Result[T, E], ctor: JSValue): JSValue = else: return JS_NULL -proc toJS(ctx: JSContext, e: enum): JSValue = +proc toJS(ctx: JSContext; e: enum): JSValue = return toJS(ctx, $e) -proc toJS(ctx: JSContext, j: JSValue): JSValue = +proc toJS(ctx: JSContext; j: JSValue): JSValue = return j -proc toJS(ctx: JSContext, promise: EmptyPromise): JSValue = +proc toJS(ctx: JSContext; promise: EmptyPromise): JSValue = var resolving_funcs: array[2, JSValue] let jsPromise = JS_NewPromiseCapability(ctx, addr resolving_funcs[0]) if JS_IsException(jsPromise): @@ -329,7 +329,7 @@ proc toJS(ctx: JSContext, promise: EmptyPromise): JSValue = JS_FreeValue(ctx, resolving_funcs[1])) return jsPromise -proc toJS[T](ctx: JSContext, promise: Promise[T]): JSValue = +proc toJS[T](ctx: JSContext; promise: Promise[T]): JSValue = var resolving_funcs: array[2, JSValue] let jsPromise = JS_NewPromiseCapability(ctx, addr resolving_funcs[0]) if JS_IsException(jsPromise): @@ -343,7 +343,7 @@ proc toJS[T](ctx: JSContext, promise: Promise[T]): JSValue = JS_FreeValue(ctx, resolving_funcs[1])) return jsPromise -proc toJS[T, E](ctx: JSContext, promise: Promise[Result[T, E]]): JSValue = +proc toJS[T, E](ctx: JSContext; promise: Promise[Result[T, E]]): JSValue = var resolving_funcs: array[2, JSValue] let jsPromise = JS_NewPromiseCapability(ctx, addr resolving_funcs[0]) if JS_IsException(jsPromise): @@ -369,7 +369,7 @@ proc toJS[T, E](ctx: JSContext, promise: Promise[Result[T, E]]): JSValue = JS_FreeValue(ctx, resolving_funcs[1])) return jsPromise -proc toJS*(ctx: JSContext, err: JSError): JSValue = +proc toJS*(ctx: JSContext; err: JSError): JSValue = if err.e notin QuickJSErrors: return toJSRefObj(ctx, err) var msg = toJS(ctx, err.message) @@ -380,20 +380,20 @@ proc toJS*(ctx: JSContext, err: JSError): JSValue = JS_FreeValue(ctx, msg) return ret -proc toJS*(ctx: JSContext, abuf: JSArrayBuffer): JSValue = +proc toJS*(ctx: JSContext; abuf: JSArrayBuffer): JSValue = return JS_NewArrayBuffer(ctx, abuf.p, abuf.len, abuf.dealloc, nil, false) -proc toJS*(ctx: JSContext, u8a: JSUint8Array): JSValue = +proc toJS*(ctx: JSContext; u8a: JSUint8Array): JSValue = var jsabuf = toJS(ctx, u8a.abuf) let ctor = ctx.getOpaque().Uint8Array_ctor let ret = JS_CallConstructor(ctx, ctor, 1, addr jsabuf) JS_FreeValue(ctx, jsabuf) return ret -proc toJS*(ctx: JSContext, ns: NarrowString): JSValue = +proc toJS*(ctx: JSContext; ns: NarrowString): JSValue = return JS_NewNarrowStringLen(ctx, cstring(ns), csize_t(string(ns).len)) -proc toJS*(ctx: JSContext, dict: JSDict): JSValue = +proc toJS*(ctx: JSContext; dict: JSDict): JSValue = let obj = JS_NewObject(ctx) if JS_IsException(obj): return obj @@ -401,7 +401,7 @@ proc toJS*(ctx: JSContext, dict: JSDict): JSValue = ctx.defineProperty(obj, k, v) return obj -proc toJSP(ctx: JSContext, parent: ref object, child: var object): JSValue = +proc toJSP(ctx: JSContext; parent: ref object; child: var object): JSValue = let p = addr child # Save parent as the original ancestor for this tree. JS_GetRuntime(ctx).getOpaque().refmap[p] = ( @@ -417,7 +417,7 @@ proc toJSP(ctx: JSContext, parent: ref object, child: var object): JSValue = GC_ref(parent) return val -proc toJSP(ctx: JSContext, parent: ptr object, child: var object): JSValue = +proc toJSP(ctx: JSContext; parent: ptr object; child: var object): JSValue = let p = addr child # Increment the reference count of parent's root ancestor, and save the # increment/decrement callbacks for the child as well. diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 788824da..f0e11265 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -26,7 +26,7 @@ type # in other words, as wide as needed, but wrap if wider than allowed # (note: I write width here, but it can apply for any constraint) SizeConstraintType = enum - STRETCH, FIT_CONTENT, MIN_CONTENT, MAX_CONTENT + scStretch, scFitContent, scMinContent, scMaxContent SizeConstraint = object t: SizeConstraintType @@ -49,13 +49,13 @@ template attrs(state: LayoutState): WindowAttributes = state.attrsp[] func maxContent(): SizeConstraint = - return SizeConstraint(t: MAX_CONTENT) + return SizeConstraint(t: scMaxContent) func stretch(u: LayoutUnit): SizeConstraint = - return SizeConstraint(t: STRETCH, u: u) + return SizeConstraint(t: scStretch, u: u) func fitContent(u: LayoutUnit): SizeConstraint = - return SizeConstraint(t: FIT_CONTENT, u: u) + return SizeConstraint(t: scFitContent, u: u) type BoxBuilder = ref object of RootObj @@ -90,52 +90,52 @@ type func fitContent(sc: SizeConstraint): SizeConstraint = case sc.t - of MIN_CONTENT, MAX_CONTENT: + of scMinContent, scMaxContent: return sc - of STRETCH, FIT_CONTENT: - return SizeConstraint(t: FIT_CONTENT, u: sc.u) + of scStretch, scFitContent: + return SizeConstraint(t: scFitContent, u: sc.u) func isDefinite(sc: SizeConstraint): bool = - return sc.t in {STRETCH, FIT_CONTENT} + return sc.t in {scStretch, scFitContent} # Layout (2nd pass) -func px(l: CSSLength, lctx: LayoutState, p: LayoutUnit = 0): +func px(l: CSSLength; lctx: LayoutState; p: LayoutUnit = 0): LayoutUnit {.inline.} = return px(l, lctx.attrs, p) -func px(l: CSSLength, lctx: LayoutState, p: Option[LayoutUnit]): +func px(l: CSSLength; lctx: LayoutState; p: Option[LayoutUnit]): Option[LayoutUnit] {.inline.} = - if l.unit == UNIT_PERC and p.isNone: + if l.unit == cuPerc and p.isNone: return none(LayoutUnit) return some(px(l, lctx.attrs, p.get(0))) -func canpx(l: CSSLength, sc: SizeConstraint): bool = - return not l.auto and (l.unit != UNIT_PERC or sc.isDefinite()) +func canpx(l: CSSLength; sc: SizeConstraint): bool = + return not l.auto and (l.unit != cuPerc or sc.isDefinite()) -func canpx(l: CSSLength, p: Option[LayoutUnit]): bool = - return not l.auto and (l.unit != UNIT_PERC or p.isSome) +func canpx(l: CSSLength; p: Option[LayoutUnit]): bool = + return not l.auto and (l.unit != cuPerc or p.isSome) # Note: for margins only # For percentages, use 0 for indefinite, and containing box's size for # definite. -func px(l: CSSLength, lctx: LayoutState, p: SizeConstraint): LayoutUnit = - if l.unit == UNIT_PERC: +func px(l: CSSLength; lctx: LayoutState; p: SizeConstraint): LayoutUnit = + if l.unit == cuPerc: case p.t - of MIN_CONTENT, MAX_CONTENT: + of scMinContent, scMaxContent: return 0 - of STRETCH, FIT_CONTENT: + of scStretch, scFitContent: return l.px(lctx, p.u) return px(l, lctx.attrs, 0) -func applySizeConstraint(u: LayoutUnit, availableSize: SizeConstraint): +func applySizeConstraint(u: LayoutUnit; availableSize: SizeConstraint): LayoutUnit = case availableSize.t - of STRETCH: + of scStretch: return availableSize.u - of MIN_CONTENT, MAX_CONTENT: + of scMinContent, scMaxContent: # must be calculated elsewhere... return u - of FIT_CONTENT: + of scFitContent: return min(u, availableSize.u) type @@ -238,10 +238,11 @@ type prevrw: int # last processed rune's width func whitespacepre(computed: CSSComputedValues): bool = - computed{"white-space"} in {WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP} + computed{"white-space"} in {WhitespacePre, WhitespacePreLine, + WhitespacePreWrap} func nowrap(computed: CSSComputedValues): bool = - computed{"white-space"} in {WHITESPACE_NOWRAP, WHITESPACE_PRE} + computed{"white-space"} in {WhitespaceNowrap, WhitespacePre} func cellwidth(lctx: LayoutState): int = lctx.attrs.ppc @@ -309,24 +310,24 @@ proc newWord(ictx: var InlineContext; state: var InlineState) = proc horizontalAlignLines(ictx: var InlineContext; state: InlineState) = let width = case ictx.space.w.t - of MIN_CONTENT, MAX_CONTENT: + of scMinContent, scMaxContent: ictx.size.w - of FIT_CONTENT: + of scFitContent: min(ictx.size.w, ictx.space.w.u) - of STRETCH: + of scStretch: max(ictx.size.w, ictx.space.w.u) # we don't support directions for now so left = start and right = end case state.computed{"text-align"} - of TEXT_ALIGN_START, TEXT_ALIGN_LEFT, TEXT_ALIGN_CHA_LEFT, TEXT_ALIGN_JUSTIFY: + of TextAlignStart, TextAlignLeft, TextAlignChaLeft, TextAlignJustify: discard - of TEXT_ALIGN_END, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CHA_RIGHT: + of TextAlignEnd, TextAlignRight, TextAlignChaRight: # move everything for line in ictx.lines: let x = max(width, line.size.w) - line.size.w for atom in line.atoms: atom.offset.x += x ictx.size.w = max(atom.offset.x + atom.size.w, ictx.size.w) - of TEXT_ALIGN_CENTER, TEXT_ALIGN_CHA_CENTER: + of TextAlignCenter, TextAlignChaCenter: # NOTE if we need line x offsets, use: #let width = width - line.offset.x for line in ictx.lines: @@ -350,12 +351,12 @@ proc verticalAlignLine(ictx: var InlineContext) = for i, atom in ictx.currentLine.atoms: let iastate = ictx.currentLine.atomstates[i] case iastate.vertalign.keyword - of VERTICAL_ALIGN_BASELINE: + of VerticalAlignBaseline: let len = iastate.vertalign.length.px(ictx.lctx, lineheight) baseline = max(baseline, iastate.baseline + len) - of VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM: + of VerticalAlignTop, VerticalAlignBottom: baseline = max(baseline, atom.size.h) - of VERTICAL_ALIGN_MIDDLE: + of VerticalAlignMiddle: baseline = max(baseline, atom.size.h div 2) else: baseline = max(baseline, iastate.baseline) @@ -372,18 +373,18 @@ proc verticalAlignLine(ictx: var InlineContext) = # (Where the atom is actually placed is irrelevant here.) ictx.currentLine.size.h = max(ictx.currentLine.size.h, atom.size.h) case iastate.vertalign.keyword - of VERTICAL_ALIGN_BASELINE: + of VerticalAlignBaseline: # Line height must be at least as high as # (line baseline) - (atom baseline) + (atom height) + (extra height). let len = iastate.vertalign.length.px(ictx.lctx, lineheight) ictx.currentLine.size.h = max(baseline - iastate.baseline + atom.size.h + len, ictx.currentLine.size.h) - of VERTICAL_ALIGN_MIDDLE: + of VerticalAlignMiddle: # Line height must be at least # (line baseline) + (atom height / 2). ictx.currentLine.size.h = max(baseline + atom.size.h div 2, ictx.currentLine.size.h) - of VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM: + of VerticalAlignTop, VerticalAlignBottom: # Line height must be at least atom height (already ensured above.) discard else: @@ -395,17 +396,17 @@ proc verticalAlignLine(ictx: var InlineContext) = for i, atom in ictx.currentLine.atoms: let iastate = ictx.currentLine.atomstates[i] case iastate.vertalign.keyword - of VERTICAL_ALIGN_BASELINE: + of VerticalAlignBaseline: # Atom is placed at (line baseline) - (atom baseline) - len let len = iastate.vertalign.length.px(ictx.lctx, lineheight) atom.offset.y = baseline - iastate.baseline - len - of VERTICAL_ALIGN_MIDDLE: + of VerticalAlignMiddle: # Atom is placed at (line baseline) - ((atom height) / 2) atom.offset.y = baseline - atom.size.h div 2 - of VERTICAL_ALIGN_TOP: + of VerticalAlignTop: # Atom is placed at the top of the line. atom.offset.y = 0 - of VERTICAL_ALIGN_BOTTOM: + of VerticalAlignBottom: # Atom is placed at the bottom of the line. atom.offset.y = ictx.currentLine.size.h - atom.size.h else: @@ -489,7 +490,7 @@ proc initLine(ictx: var InlineContext) = for ex in bctx.exclusions: if ex.offset.y <= y and y < ex.offset.y + ex.size.h: ictx.currentLine.hasExclusion = true - if ex.t == FLOAT_LEFT: + if ex.t == FloatLeft: left = ex.offset.x + ex.size.w else: right = ex.offset.x @@ -500,9 +501,9 @@ proc finishLine(ictx: var InlineContext; state: var InlineState; wrap: bool; force = false) = if ictx.currentLine.atoms.len != 0 or force: let whitespace = state.computed{"white-space"} - if whitespace == WHITESPACE_PRE: + if whitespace == WhitespacePre: ictx.flushWhitespace(state) - elif whitespace == WHITESPACE_PRE_WRAP: + elif whitespace == WhitespacePreWrap: ictx.flushWhitespace(state, hang = true) else: ictx.whitespacenum = 0 @@ -625,9 +626,9 @@ func shouldWrap(ictx: InlineContext; w: LayoutUnit; pcomputed: CSSComputedValues): bool = if pcomputed != nil and pcomputed.nowrap: return false - if ictx.space.w.t == MAX_CONTENT: + if ictx.space.w.t == scMaxContent: return false # no wrap with max-content - if ictx.space.w.t == MIN_CONTENT: + if ictx.space.w.t == scMinContent: return true # always wrap with min-content return ictx.currentLine.size.w + w > ictx.currentLine.availableWidth @@ -658,7 +659,8 @@ proc addAtom(ictx: var InlineContext; state: var InlineState; #TODO this is inefficient while ictx.shouldWrap2(atom.size.w + shift): ictx.applyLineHeight(ictx.currentLine, state.computed) - ictx.currentLine.lineheight = max(ictx.currentLine.lineheight, ictx.cellheight) + ictx.currentLine.lineheight = max(ictx.currentLine.lineheight, + ictx.cellheight) ictx.finishLine(state, wrap = false, force = true) # Recompute on newline shift = ictx.computeShift(state) @@ -709,20 +711,20 @@ proc checkWrap(ictx: var InlineContext; state: var InlineState; r: Rune) = # of any dash inside CJK sentences) ictx.wrappos = -1 case state.computed{"word-break"} - of WORD_BREAK_NORMAL: + of WordBreakNormal: if rw == 2 or ictx.wrappos != -1: # break on cjk and wrap opportunities let plusWidth = ictx.word.size.w + shift + rw * ictx.cellwidth if ictx.shouldWrap(plusWidth, nil): if not ictx.addWordEOL(state): # no line wrapping occured in addAtom ictx.finishLine(state, wrap = true) ictx.whitespacenum = 0 - of WORD_BREAK_BREAK_ALL: + of WordBreakBreakAll: let plusWidth = ictx.word.size.w + shift + rw * ictx.cellwidth if ictx.shouldWrap(plusWidth, nil): if not ictx.addWordEOL(state): # no line wrapping occured in addAtom ictx.finishLine(state, wrap = true) ictx.whitespacenum = 0 - of WORD_BREAK_KEEP_ALL: + of WordBreakKeepAll: let plusWidth = ictx.word.size.w + shift + rw * ictx.cellwidth if ictx.shouldWrap(plusWidth, nil): ictx.finishLine(state, wrap = true) @@ -732,21 +734,21 @@ proc processWhitespace(ictx: var InlineContext; state: var InlineState; c: char) = discard ictx.addWord(state) case state.computed{"white-space"} - of WHITESPACE_NORMAL, WHITESPACE_NOWRAP: + of WhitespaceNormal, WhitespaceNowrap: if ictx.whitespacenum < 1: ictx.whitespacenum = 1 ictx.whitespaceFragment = state.fragment ictx.whitespaceIsLF = c == '\n' if c != '\n': ictx.whitespaceIsLF = false - of WHITESPACE_PRE_LINE: + of WhitespacePreLine: if c == '\n': ictx.flushLine(state) elif ictx.whitespacenum < 1: ictx.whitespaceIsLF = false ictx.whitespacenum = 1 ictx.whitespaceFragment = state.fragment - of WHITESPACE_PRE, WHITESPACE_PRE_WRAP: + of WhitespacePre, WhitespacePreWrap: #TODO whitespace type should be preserved here. (it isn't, because # it would break tabs in the current buffer model.) ictx.whitespaceIsLF = false @@ -818,41 +820,41 @@ proc layoutText(ictx: var InlineContext; state: var InlineState; str: string) = ictx.flushWhitespace(state) ictx.newWord(state) case state.computed{"text-transform"} - of TEXT_TRANSFORM_NONE: + of TextTransformNone: ictx.layoutTextLoop(state, str) {.linearScanEnd.} - of TEXT_TRANSFORM_CAPITALIZE: + of TextTransformCapitalize: ictx.layoutTextLoop(state, str.capitalize()) - of TEXT_TRANSFORM_UPPERCASE: + of TextTransformUppercase: ictx.layoutTextLoop(state, str.toUpper()) - of TEXT_TRANSFORM_LOWERCASE: + of TextTransformLowercase: ictx.layoutTextLoop(state, str.toLower()) - of TEXT_TRANSFORM_FULL_WIDTH: + of TextTransformFullWidth: ictx.layoutTextLoop(state, str.fullwidth()) - of TEXT_TRANSFORM_FULL_SIZE_KANA: + of TextTransformFullSizeKana: ictx.layoutTextLoop(state, str.fullsize()) - of TEXT_TRANSFORM_CHA_HALF_WIDTH: + of TextTransformChaHalfWidth: ictx.layoutTextLoop(state, str.halfwidth()) -func spx(l: CSSLength, lctx: LayoutState, p: SizeConstraint, - computed: CSSComputedValues, padding: LayoutUnit): LayoutUnit = +func spx(l: CSSLength; lctx: LayoutState; p: SizeConstraint; + computed: CSSComputedValues; padding: LayoutUnit): LayoutUnit = let u = l.px(lctx, p) - if computed{"box-sizing"} == BOX_SIZING_BORDER_BOX: + if computed{"box-sizing"} == BoxSizingBorderBox: return max(u - padding, 0) return max(u, 0) -func spx(l: CSSLength, lctx: LayoutState, p: Option[LayoutUnit], - computed: CSSComputedValues, padding: LayoutUnit): Option[LayoutUnit] = +func spx(l: CSSLength; lctx: LayoutState; p: Option[LayoutUnit]; + computed: CSSComputedValues; padding: LayoutUnit): Option[LayoutUnit] = let u = l.px(lctx, p) if u.isSome: let u = u.get - if computed{"box-sizing"} == BOX_SIZING_BORDER_BOX: + if computed{"box-sizing"} == BoxSizingBorderBox: return some(max(u - padding, 0)) return some(max(u, 0)) return u -proc resolveContentWidth(sizes: var ResolvedSizes, widthpx: LayoutUnit, - containingWidth: SizeConstraint, computed: CSSComputedValues, +proc resolveContentWidth(sizes: var ResolvedSizes; widthpx: LayoutUnit; + containingWidth: SizeConstraint; computed: CSSComputedValues; isauto = false) = if not sizes.space.w.isDefinite(): # width is indefinite, so no conflicts can be resolved here. @@ -860,7 +862,7 @@ proc resolveContentWidth(sizes: var ResolvedSizes, widthpx: LayoutUnit, let total = widthpx + sizes.margin.left + sizes.margin.right + sizes.padding.left + sizes.padding.right let underflow = containingWidth.u - total - if isauto or sizes.space.w.t == FIT_CONTENT: + if isauto or sizes.space.w.t == scFitContent: if underflow >= 0: sizes.space.w = SizeConstraint(t: sizes.space.w.t, u: underflow) else: @@ -876,7 +878,7 @@ proc resolveContentWidth(sizes: var ResolvedSizes, widthpx: LayoutUnit, sizes.margin.left = underflow div 2 sizes.margin.right = underflow div 2 -proc resolveMargins(availableWidth: SizeConstraint, lctx: LayoutState, +proc resolveMargins(availableWidth: SizeConstraint; lctx: LayoutState; computed: CSSComputedValues): RelativeRect = # Note: we use availableWidth for percentage resolution intentionally. return RelativeRect( @@ -886,7 +888,7 @@ proc resolveMargins(availableWidth: SizeConstraint, lctx: LayoutState, right: computed{"margin-right"}.px(lctx, availableWidth) ) -proc resolvePadding(availableWidth: SizeConstraint, lctx: LayoutState, +proc resolvePadding(availableWidth: SizeConstraint; lctx: LayoutState; computed: CSSComputedValues): RelativeRect = # Note: we use availableWidth for percentage resolution intentionally. return RelativeRect( @@ -896,8 +898,8 @@ proc resolvePadding(availableWidth: SizeConstraint, lctx: LayoutState, right: computed{"padding-right"}.px(lctx, availableWidth) ) -proc resolveBlockWidth(sizes: var ResolvedSizes, - containingWidth: SizeConstraint, computed: CSSComputedValues, +proc resolveBlockWidth(sizes: var ResolvedSizes; + containingWidth: SizeConstraint; computed: CSSComputedValues; lctx: LayoutState) = let width = computed{"width"} let padding = sizes.padding.left + sizes.padding.right @@ -910,13 +912,13 @@ proc resolveBlockWidth(sizes: var ResolvedSizes, let maxWidth = computed{"max-width"}.spx(lctx, containingWidth, computed, padding) sizes.maxWidth = maxWidth - if sizes.space.w.t in {STRETCH, FIT_CONTENT} and - maxWidth < sizes.space.w.u or sizes.space.w.t == MAX_CONTENT: + if sizes.space.w.t in {scStretch, scFitContent} and + maxWidth < sizes.space.w.u or sizes.space.w.t == scMaxContent: sizes.space.w = stretch(maxWidth) #TODO is stretch ok here? - if sizes.space.w.t == STRETCH: + if sizes.space.w.t == scStretch: # available width would stretch over max-width sizes.space.w = stretch(maxWidth) - else: # FIT_CONTENT + else: # scFitContent # available width could be higher than max-width (but not necessarily) sizes.space.w = fitContent(maxWidth) sizes.resolveContentWidth(maxWidth, containingWidth, computed) @@ -924,8 +926,8 @@ proc resolveBlockWidth(sizes: var ResolvedSizes, let minWidth = computed{"min-width"}.spx(lctx, containingWidth, computed, padding) sizes.minWidth = minWidth - if sizes.space.w.t in {STRETCH, FIT_CONTENT} and - minWidth > sizes.space.w.u or sizes.space.w.t == MIN_CONTENT: + if sizes.space.w.t in {scStretch, scFitContent} and + minWidth > sizes.space.w.u or sizes.space.w.t == scMinContent: # two cases: # * available width is stretched under min-width. in this case, # stretch to min-width instead. @@ -934,9 +936,9 @@ proc resolveBlockWidth(sizes: var ResolvedSizes, sizes.space.w = stretch(minWidth) sizes.resolveContentWidth(minWidth, containingWidth, computed) -proc resolveBlockHeight(sizes: var ResolvedSizes, - containingHeight: SizeConstraint, percHeight: Option[LayoutUnit], - computed: CSSComputedValues, lctx: LayoutState) = +proc resolveBlockHeight(sizes: var ResolvedSizes; + containingHeight: SizeConstraint; percHeight: Option[LayoutUnit]; + computed: CSSComputedValues; lctx: LayoutState) = let height = computed{"height"} let padding = sizes.padding.top + sizes.padding.bottom var heightpx: LayoutUnit = 0 @@ -949,12 +951,12 @@ proc resolveBlockHeight(sizes: var ResolvedSizes, sizes.maxHeight = maxHeight.get(high(LayoutUnit)) if maxHeight.isSome: let maxHeight = maxHeight.get - if sizes.space.h.t in {STRETCH, FIT_CONTENT} and - maxHeight < sizes.space.h.u or sizes.space.h.t == MAX_CONTENT: + if sizes.space.h.t in {scStretch, scFitContent} and + maxHeight < sizes.space.h.u or sizes.space.h.t == scMaxContent: # same reasoning as for width. - if sizes.space.h.t == STRETCH: + if sizes.space.h.t == scStretch: sizes.space.h = stretch(maxHeight) - else: # FIT_CONTENT + else: # scFitContent sizes.space.h = fitContent(maxHeight) if not computed{"min-height"}.auto: let minHeight = computed{"min-height"}.spx(lctx, percHeight, computed, @@ -962,8 +964,8 @@ proc resolveBlockHeight(sizes: var ResolvedSizes, sizes.minHeight = minHeight.get(0) if minHeight.isSome: let minHeight = minHeight.get - if sizes.space.h.t in {STRETCH, FIT_CONTENT} and - minHeight > sizes.space.h.u or sizes.space.h.t == MIN_CONTENT: + if sizes.space.h.t in {scStretch, scFitContent} and + minHeight > sizes.space.h.u or sizes.space.h.t == scMinContent: # same reasoning as for width. sizes.space.h = stretch(minHeight) @@ -1116,7 +1118,7 @@ proc resolveFloatSizes(lctx: LayoutState; space: AvailableSpace; # Calculate and resolve available width & height for box children. # containingWidth: width of the containing box -# containingHeight: ditto, but with height. +# containingHeight: ditto; but with height. # Note that this is not the final content size, just the amount of space # available for content. # The percentage width/height is generally @@ -1127,9 +1129,9 @@ proc resolveFloatSizes(lctx: LayoutState; space: AvailableSpace; proc resolveSizes(lctx: LayoutState; space: AvailableSpace; percHeight: Option[LayoutUnit]; computed: CSSComputedValues): ResolvedSizes = - if computed{"position"} == POSITION_ABSOLUTE: + if computed{"position"} == PositionAbsolute: return lctx.resolveAbsoluteSizes(computed) - elif computed{"float"} != FLOAT_NONE: + elif computed{"float"} != FloatNone: return lctx.resolveFloatSizes(space, percHeight, computed) else: return lctx.resolveBlockSizes(space, percHeight, computed) @@ -1139,7 +1141,7 @@ func toPercSize(sc: SizeConstraint): Option[LayoutUnit] = return some(sc.u) return none(LayoutUnit) -proc append(a: var Strut, b: LayoutUnit) = +proc append(a: var Strut; b: LayoutUnit) = if b < 0: a.neg = min(b, a.neg) else: @@ -1184,7 +1186,7 @@ func bfcOffset(bctx: BlockContext): Offset = return bctx.parentBps.offset return Offset() -proc layoutInline(bctx: var BlockContext, box: BlockBox, +proc layoutInline(bctx: var BlockContext; box: BlockBox; children: seq[BoxBuilder], sizes: ResolvedSizes) = var bfcOffset = bctx.bfcOffset let offset = Offset(x: sizes.padding.left, y: sizes.padding.top) @@ -1200,17 +1202,16 @@ proc layoutInline(bctx: var BlockContext, box: BlockBox, box.baseline = offset.y + box.inline.baseline box.firstBaseline = offset.y + box.inline.firstBaseline -const DisplayBlockLike = {DISPLAY_BLOCK, DISPLAY_LIST_ITEM, - DISPLAY_INLINE_BLOCK} +const DisplayBlockLike = {DisplayBlock, DisplayListItem, DisplayInlineBlock} # Return true if no more margin collapsing can occur for the current strut. -func canFlushMargins(builder: BlockBoxBuilder, sizes: ResolvedSizes): bool = - if builder.computed{"position"} == POSITION_ABSOLUTE: +func canFlushMargins(builder: BlockBoxBuilder; sizes: ResolvedSizes): bool = + if builder.computed{"position"} == PositionAbsolute: return false return sizes.padding.top != 0 or sizes.padding.bottom != 0 or builder.inlinelayout or builder.computed{"display"} notin DisplayBlockLike -proc flushMargins(bctx: var BlockContext, box: BlockBox) = +proc flushMargins(bctx: var BlockContext; box: BlockBox) = # Apply uncommitted margins. let margin = bctx.marginTodo.sum() if bctx.marginTarget == nil: @@ -1227,21 +1228,21 @@ proc flushMargins(bctx: var BlockContext, box: BlockBox) = bctx.marginTarget = nil bctx.marginTodo = Strut() -proc clearFloats(offset: var Offset, bctx: var BlockContext, clear: CSSClear) = +proc clearFloats(offset: var Offset; bctx: var BlockContext; clear: CSSClear) = var y = bctx.bfcOffset.y + offset.y case clear - of CLEAR_LEFT, CLEAR_INLINE_START: + of ClearLeft, ClearInlineStart: for ex in bctx.exclusions: - if ex.t == FLOAT_LEFT: + if ex.t == FloatLeft: y = max(ex.offset.y + ex.size.h, y) - of CLEAR_RIGHT, CLEAR_INLINE_END: + of ClearRight, ClearInlineEnd: for ex in bctx.exclusions: - if ex.t == FLOAT_RIGHT: + if ex.t == FloatRight: y = max(ex.offset.y + ex.size.h, y) - of CLEAR_BOTH: + of ClearBoth: for ex in bctx.exclusions: y = max(ex.offset.y + ex.size.h, y) - of CLEAR_NONE: assert false + of ClearNone: assert false bctx.clearOffset = y offset.y = y - bctx.bfcOffset.y @@ -1276,16 +1277,16 @@ func findNextFloatOffset(bctx: BlockContext; offset: Offset; size: Size; let ey2 = ex.offset.y + ex.size.h if cy2 >= ex.offset.y and y < ey2: let ex2 = ex.offset.x + ex.size.w - if ex.t == FLOAT_LEFT and left < ex2: + if ex.t == FloatLeft and left < ex2: left = ex2 - if ex.t == FLOAT_RIGHT and right > ex.offset.x: + if ex.t == FloatRight and right > ex.offset.x: right = ex.offset.x miny = min(ey2, miny) if right - left >= size.w or miny == high(LayoutUnit): # Enough space, or no other exclusions found at this y offset. - if float == FLOAT_LEFT: + if float == FloatLeft: return Offset(x: left, y: y) - else: # FLOAT_RIGHT + else: # FloatRight return Offset(x: right - size.w, y: y) # Move y to the bottom exclusion edge at the lowest y (where the exclusion # still intersects with the previous y). @@ -1295,7 +1296,7 @@ func findNextFloatOffset(bctx: BlockContext; offset: Offset; size: Size; proc positionFloat(bctx: var BlockContext; child: BlockBox; space: AvailableSpace; bfcOffset: Offset) = let clear = child.computed{"clear"} - if clear != CLEAR_NONE: + if clear != ClearNone: child.offset.clearFloats(bctx, clear) let size = Size( w: child.margin.left + child.margin.right + child.size.w, @@ -1305,9 +1306,9 @@ proc positionFloat(bctx: var BlockContext; child: BlockBox; x: bfcOffset.x + child.offset.x - child.margin.left, y: max(bfcOffset.y + child.offset.y - child.margin.top, bctx.clearOffset) ) - assert space.w.t != FIT_CONTENT + assert space.w.t != scFitContent let ft = child.computed{"float"} - assert ft != FLOAT_NONE + assert ft != FloatNone let offset = bctx.findNextFloatOffset(childBfcOffset, size, space, ft) child.offset = Offset( x: offset.x - bfcOffset.x + child.margin.left, @@ -1322,11 +1323,19 @@ proc positionFloats(bctx: var BlockContext) = bctx.positionFloat(f.box, f.space, f.parentBps.offset) bctx.unpositionedFloats.setLen(0) +const RowGroupBox = { + DisplayTableRowGroup, DisplayTableHeaderGroup, DisplayTableFooterGroup +} +const InternalTableBox = RowGroupBox + { + DisplayTableCell, DisplayTableRow, DisplayTableColumn, + DisplayTableColumnGroup +} + func establishesBFC(computed: CSSComputedValues): bool = - return computed{"float"} != FLOAT_NONE or - computed{"position"} == POSITION_ABSOLUTE or - computed{"display"} in {DISPLAY_INLINE_BLOCK, DISPLAY_FLOW_ROOT} + - InternalTableBox + {DISPLAY_FLEX, DISPLAY_INLINE_FLEX} + return computed{"float"} != FloatNone or + computed{"position"} == PositionAbsolute or + computed{"display"} in {DisplayInlineBlock, DisplayFlowRoot} + + InternalTableBox + {DisplayFlex, DisplayInlineFlex} #TODO overflow, contain, grid, multicol, column-span proc layoutFlow(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder; @@ -1334,7 +1343,7 @@ proc layoutFlow(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder; if builder.canFlushMargins(sizes): bctx.flushMargins(box) bctx.positionFloats() - if builder.computed{"clear"} != CLEAR_NONE: + if builder.computed{"clear"} != ClearNone: box.offset.clearFloats(bctx, builder.computed{"clear"}) if builder.inlinelayout: # Builder only contains inline boxes. @@ -1397,11 +1406,11 @@ proc addInlineBlock(ictx: var InlineContext; state: var InlineState; var bctx = BlockContext(lctx: lctx) bctx.marginTodo.append(sizes.margin.top) case builder.computed{"display"} - of DISPLAY_INLINE_BLOCK: + of DisplayInlineBlock: bctx.layoutFlow(box, builder, sizes) - of DISPLAY_INLINE_TABLE: + of DisplayInlineTable: lctx.layoutTable(box, TableBoxBuilder(builder), sizes) - of DISPLAY_INLINE_FLEX: + of DisplayInlineFlex: bctx.layoutFlex(box, builder, sizes) else: assert false, $builder.computed{"display"} @@ -1470,10 +1479,10 @@ proc layoutInline(ictx: var InlineContext; box: InlineBoxBuilder): for child in box.children: case child.computed{"display"} - of DISPLAY_INLINE: + of DisplayInline: let child = ictx.layoutInline(InlineBoxBuilder(child)) state.fragment.children.add(child) - of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE, DISPLAY_INLINE_FLEX: + of DisplayInlineBlock, DisplayInlineTable, DisplayInlineFlex: # Note: we do not need a separate inline fragment here, because the tree # generator already does an iflush() before adding inline blocks. let w = fitContent(ictx.space.w) @@ -1502,9 +1511,9 @@ proc layoutInline(ictx: var InlineContext; box: InlineBoxBuilder): ) return fragment -proc layoutRootInline(bctx: var BlockContext, inlines: seq[BoxBuilder], - space: AvailableSpace, computed: CSSComputedValues, offset, - bfcOffset: Offset): RootInlineFragment = +proc layoutRootInline(bctx: var BlockContext; inlines: seq[BoxBuilder]; + space: AvailableSpace; computed: CSSComputedValues; + offset, bfcOffset: Offset): RootInlineFragment = let root = RootInlineFragment( offset: offset, fragment: InlineFragment(computed: computed) @@ -1512,10 +1521,10 @@ proc layoutRootInline(bctx: var BlockContext, inlines: seq[BoxBuilder], var ictx = bctx.initInlineContext(space, bfcOffset, root) for child in inlines: case child.computed{"display"} - of DISPLAY_INLINE: + of DisplayInline: let childFragment = ictx.layoutInline(InlineBoxBuilder(child)) root.fragment.children.add(childFragment) - of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE, DISPLAY_INLINE_FLEX: + of DisplayInlineBlock, DisplayInlineTable, DisplayInlineFlex: # add an anonymous fragment to contain this var state = InlineState( computed: computed, @@ -1541,7 +1550,7 @@ proc layoutRootInline(bctx: var BlockContext, inlines: seq[BoxBuilder], root.xminwidth = ictx.minwidth return root -proc positionAbsolute(lctx: LayoutState, box: BlockBox, margin: RelativeRect) = +proc positionAbsolute(lctx: LayoutState; box: BlockBox; margin: RelativeRect) = let last = lctx.positioned[^1] let left = box.computed{"left"} let right = box.computed{"right"} @@ -1562,7 +1571,7 @@ proc positionAbsolute(lctx: LayoutState, box: BlockBox, margin: RelativeRect) = box.offset.y = parentHeight - bottom.px(lctx, parentHeight) - box.size.h box.offset.y -= margin.bottom -proc positionRelative(parent, box: BlockBox, lctx: LayoutState) = +proc positionRelative(parent, box: BlockBox; lctx: LayoutState) = let left = box.computed{"left"} let right = box.computed{"right"} let top = box.computed{"top"} @@ -1576,6 +1585,14 @@ proc positionRelative(parent, box: BlockBox, lctx: LayoutState) = elif not top.auto: box.offset.y -= parent.size.h - bottom.px(lctx) - box.size.h +const ProperTableChild = RowGroupBox + { + DisplayTableRow, DisplayTableColumn, DisplayTableColumnGroup, + DisplayTableCaption +} +const ProperTableRowParent = RowGroupBox + { + DisplayTable, DisplayInlineTable +} + type CellWrapper = ref object builder: TableCellBoxBuilder @@ -1659,8 +1676,8 @@ proc sortGrowing(pctx: var TableContext) = cmp(a.coli, b.coli)) # Grow cells with a rowspan > 1 (to occupy their place in a new row). -proc growRowspan(pctx: var TableContext, ctx: var RowContext, - growi, i, n: var int, growlen: int) = +proc growRowspan(pctx: var TableContext; ctx: var RowContext; + growi, i, n: var int; growlen: int) = while growi < growlen: let cellw = pctx.growing[growi] if cellw.coli > n: @@ -1682,9 +1699,12 @@ proc growRowspan(pctx: var TableContext, ctx: var RowContext, inc i inc growi -proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, - parent: BlockBox, rowi, numrows: int): RowContext = - var ctx = RowContext(builder: box, cells: newSeq[CellWrapper](box.children.len)) +proc preBuildTableRow(pctx: var TableContext; box: TableRowBoxBuilder; + parent: BlockBox; rowi, numrows: int): RowContext = + var ctx = RowContext( + builder: box, + cells: newSeq[CellWrapper](box.children.len) + ) var n = 0 var i = 0 var growi = 0 @@ -1693,7 +1713,7 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, let growlen = pctx.growing.len for child in box.children: pctx.growRowspan(ctx, growi, i, n, growlen) - assert child.computed{"display"} == DISPLAY_TABLE_CELL + assert child.computed{"display"} == DisplayTableCell let cellbuilder = TableCellBoxBuilder(child) let colspan = cellbuilder.computed{"-cha-colspan"} let rowspan = min(cellbuilder.computed{"-cha-rowspan"}, numrows - rowi) @@ -1772,18 +1792,18 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, ctx.ncols = n return ctx -proc alignTableCell(cell: BlockBox, availableHeight, baseline: LayoutUnit) = +proc alignTableCell(cell: BlockBox; availableHeight, baseline: LayoutUnit) = case cell.computed{"vertical-align"}.keyword - of VERTICAL_ALIGN_TOP: + of VerticalAlignTop: cell.offset.y = 0 - of VERTICAL_ALIGN_MIDDLE: + of VerticalAlignMiddle: cell.offset.y = availableHeight div 2 - cell.size.h div 2 - of VERTICAL_ALIGN_BOTTOM: + of VerticalAlignBottom: cell.offset.y = availableHeight - cell.size.h else: cell.offset.y = baseline - cell.firstBaseline -proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, +proc buildTableRow(pctx: TableContext; ctx: RowContext; parent: BlockBox; builder: TableRowBoxBuilder): BlockBox = var x: LayoutUnit = 0 var n = 0 @@ -1827,7 +1847,7 @@ proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, x += w n += cellw.colspan const HasNoBaseline = { - VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_MIDDLE, VERTICAL_ALIGN_BOTTOM + VerticalAlignTop, VerticalAlignMiddle, VerticalAlignBottom } if cell != nil: if cell.computed{"vertical-align"}.keyword notin HasNoBaseline: # baseline @@ -1855,7 +1875,7 @@ proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, row.size.w = x return row -proc preBuildTableRows(ctx: var TableContext, rows: seq[TableRowBoxBuilder], +proc preBuildTableRows(ctx: var TableContext; rows: seq[TableRowBoxBuilder]; table: BlockBox) = for i in 0 ..< rows.len: let row = rows[i] @@ -1863,7 +1883,7 @@ proc preBuildTableRows(ctx: var TableContext, rows: seq[TableRowBoxBuilder], ctx.rows.add(rctx) ctx.maxwidth = max(rctx.width, ctx.maxwidth) -proc preBuildTableRows(ctx: var TableContext, builder: TableBoxBuilder, +proc preBuildTableRows(ctx: var TableContext; builder: TableBoxBuilder; table: BlockBox) = # Use separate seqs for different row groups, so that e.g. this HTML: # echo '<TABLE><TBODY><TR><TD>world<THEAD><TR><TD>hello'|cha -T text/html @@ -1877,21 +1897,21 @@ proc preBuildTableRows(ctx: var TableContext, builder: TableBoxBuilder, for child in builder.children: assert child.computed{"display"} in ProperTableChild case child.computed{"display"} - of DISPLAY_TABLE_ROW: + of DisplayTableRow: tbody.add(TableRowBoxBuilder(child)) - of DISPLAY_TABLE_HEADER_GROUP: + of DisplayTableHeaderGroup: for child in child.children: - assert child.computed{"display"} == DISPLAY_TABLE_ROW + assert child.computed{"display"} == DisplayTableRow thead.add(TableRowBoxBuilder(child)) - of DISPLAY_TABLE_ROW_GROUP: + of DisplayTableRowGroup: for child in child.children: - assert child.computed{"display"} == DISPLAY_TABLE_ROW + assert child.computed{"display"} == DisplayTableRow tbody.add(TableRowBoxBuilder(child)) - of DISPLAY_TABLE_FOOTER_GROUP: + of DisplayTableFooterGroup: for child in child.children: - assert child.computed{"display"} == DISPLAY_TABLE_ROW + assert child.computed{"display"} == DisplayTableRow tfoot.add(TableRowBoxBuilder(child)) - of DISPLAY_TABLE_CAPTION: + of DisplayTableCaption: if caption == nil: caption = TableCaptionBoxBuilder(child) else: discard @@ -1901,7 +1921,7 @@ proc preBuildTableRows(ctx: var TableContext, builder: TableBoxBuilder, ctx.preBuildTableRows(tbody, table) ctx.preBuildTableRows(tfoot, table) -proc calcUnspecifiedColIndices(ctx: var TableContext, W: var LayoutUnit, +proc calcUnspecifiedColIndices(ctx: var TableContext; W: var LayoutUnit; weight: var float64): seq[int] = # Spacing for each column: var avail = newSeqUninitialized[int](ctx.cols.len) @@ -1922,15 +1942,15 @@ proc calcUnspecifiedColIndices(ctx: var TableContext, W: var LayoutUnit, avail.del(j) return avail -func needsRedistribution(ctx: TableContext, computed: CSSComputedValues): bool = +func needsRedistribution(ctx: TableContext; computed: CSSComputedValues): bool = case ctx.space.w.t - of MIN_CONTENT, MAX_CONTENT: + of scMinContent, scMaxContent: # bleh return false - of STRETCH: + of scStretch: let u = ctx.space.w.u return u > ctx.maxwidth or u < ctx.maxwidth - of FIT_CONTENT: + of scFitContent: let u = ctx.space.w.u return u > ctx.maxwidth and not computed{"width"}.auto or u < ctx.maxwidth @@ -1976,10 +1996,10 @@ proc reflowTableCells(ctx: var TableContext) = ctx.reflow[n] = true dec n -proc buildTableRows(ctx: TableContext, table: BlockBox, sizes: ResolvedSizes) = +proc buildTableRows(ctx: TableContext; table: BlockBox; sizes: ResolvedSizes) = var y: LayoutUnit = 0 for roww in ctx.rows: - if roww.builder.computed{"visibility"} == VISIBILITY_COLLAPSE: + if roww.builder.computed{"visibility"} == VisibilityCollapse: continue y += ctx.blockspacing let row = ctx.buildTableRow(roww, table, roww.builder) @@ -2009,11 +2029,11 @@ proc addTableCaption(ctx: TableContext; table: BlockBox) = table.size.h += outerHeight table.size.w = max(table.size.w, box.size.w) case builder.computed{"caption-side"} - of CAPTION_SIDE_TOP, CAPTION_SIDE_BLOCK_START: + of CaptionSideTop, CaptionSideBlockStart: for r in table.nested: r.offset.y += outerHeight table.nested.insert(box, 0) - of CAPTION_SIDE_BOTTOM, CAPTION_SIDE_BLOCK_END: + of CaptionSideBottom, CaptionSideBlockEnd: box.offset.y += outerHeight table.nested.add(box) @@ -2026,9 +2046,9 @@ proc addTableCaption(ctx: TableContext; table: BlockBox) = # Distribute the table's content width among cells with an unspecified # width. If this would give any cell a width < min_width, set that # cell's width to min_width, then re-do the distribution. -proc layoutTable(lctx: LayoutState, table: BlockBox, builder: TableBoxBuilder, +proc layoutTable(lctx: LayoutState; table: BlockBox; builder: TableBoxBuilder; sizes: ResolvedSizes) = - let collapse = table.computed{"border-collapse"} == BORDER_COLLAPSE_COLLAPSE + let collapse = table.computed{"border-collapse"} == BorderCollapseCollapse var ctx = TableContext(lctx: lctx, collapse: collapse, space: sizes.space) if not ctx.collapse: ctx.inlinespacing = table.computed{"border-spacing"}.a.px(lctx) @@ -2044,13 +2064,13 @@ proc layoutTable(lctx: LayoutState, table: BlockBox, builder: TableBoxBuilder, if ctx.caption != nil: ctx.addTableCaption(table) -proc postAlignChild(box, child: BlockBox, width: LayoutUnit) = +proc postAlignChild(box, child: BlockBox; width: LayoutUnit) = case box.computed{"text-align"} - of TEXT_ALIGN_CHA_CENTER: + of TextAlignChaCenter: child.offset.x += max(width div 2 - child.size.w div 2, 0) - of TEXT_ALIGN_CHA_RIGHT: + of TextAlignChaRight: child.offset.x += max(width - child.size.w - child.margin.right, 0) - of TEXT_ALIGN_CHA_LEFT: + of TextAlignChaLeft: discard # default else: discard @@ -2058,13 +2078,13 @@ proc postAlignChild(box, child: BlockBox, width: LayoutUnit) = proc layout(bctx: var BlockContext; box: BlockBox; builder: BoxBuilder; sizes: ResolvedSizes) = case builder.computed{"display"} - of DISPLAY_BLOCK, DISPLAY_FLOW_ROOT: + of DisplayBlock, DisplayFlowRoot: bctx.layoutFlow(box, BlockBoxBuilder(builder), sizes) - of DISPLAY_LIST_ITEM: + of DisplayListItem: bctx.layoutListItem(box, ListItemBoxBuilder(builder), sizes) - of DISPLAY_TABLE: + of DisplayTable: bctx.lctx.layoutTable(box, TableBoxBuilder(builder), sizes) - of DISPLAY_FLEX: + of DisplayFlex: bctx.layoutFlex(box, BlockBoxBuilder(builder), sizes) else: assert false, "builder.t is " & $builder.computed{"display"} @@ -2101,8 +2121,8 @@ type lctx: LayoutState pending: seq[FlexPendingItem] -const FlexReverse = {FLEX_DIRECTION_ROW_REVERSE, FLEX_DIRECTION_COLUMN_REVERSE} -const FlexRow = {FLEX_DIRECTION_ROW, FLEX_DIRECTION_ROW_REVERSE} +const FlexReverse = {FlexDirectionRowReverse, FlexDirectionColumnReverse} +const FlexRow = {FlexDirectionRow, FlexDirectionRowReverse} proc redistributeWidth(mctx: var FlexMainContext; sizes: ResolvedSizes) = #TODO actually use flex-basis @@ -2115,7 +2135,8 @@ proc redistributeWidth(mctx: var FlexMainContext; sizes: ResolvedSizes) = totalWeight > 0: mctx.maxSize.h = 0 # redo maxSize calculation; we only need height here let unit = diff / totalWeight - # reset total weight & available diff for the next iteration (if there is one) + # reset total weight & available diff for the next iteration (if there is + # one) totalWeight = 0 diff = 0 for it in mctx.pending.mitems: @@ -2156,7 +2177,8 @@ proc redistributeHeight(mctx: var FlexMainContext; sizes: ResolvedSizes) = totalWeight > 0: mctx.maxSize.w = 0 # redo maxSize calculation; we only need height here let unit = diff / totalWeight - # reset total weight & available diff for the next iteration (if there is one) + # reset total weight & available diff for the next iteration (if there is + # one) totalWeight = 0 diff = 0 for it in mctx.pending.mitems: @@ -2256,7 +2278,7 @@ proc layoutFlex(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder; else: builder.children var totalMaxSize = Size() #TODO find a better name for this - let canWrap = box.computed{"flex-wrap"} != FLEX_WRAP_NOWRAP + let canWrap = box.computed{"flex-wrap"} != FlexWrapNowrap let percHeight = sizes.space.h.toPercSize() while i < children.len: let builder = children[i] @@ -2283,13 +2305,13 @@ proc layoutFlex(bctx: var BlockContext; box: BlockBox; builder: BlockBoxBuilder; childSizes.space.w = stretch(child.xminwidth) child = lctx.layoutFlexChild(builder, childSizes) if flexDir in FlexRow: - if canWrap and (sizes.space.w.t == MIN_CONTENT or + if canWrap and (sizes.space.w.t == scMinContent or sizes.space.w.isDefinite and mctx.totalSize.w + child.size.w > sizes.space.w.u): mctx.flushRow(box, sizes, totalMaxSize) mctx.totalSize.w += child.size.w else: - if canWrap and (sizes.space.h.t == MIN_CONTENT or + if canWrap and (sizes.space.h.t == scMinContent or sizes.space.h.isDefinite and mctx.totalSize.h + child.size.h > sizes.space.h.u): mctx.flushRow(box, sizes, totalMaxSize) @@ -2326,7 +2348,7 @@ proc layoutBlockChild(bctx: var BlockContext; builder: BoxBuilder; w: space.w, h: maxContent() #TODO fit-content when clip ) - if builder.computed{"display"} == DISPLAY_TABLE: + if builder.computed{"display"} == DisplayTable: space.w = fitContent(space.w) let sizes = bctx.lctx.resolveSizes(space, percHeight, builder.computed) if appendMargins: @@ -2358,7 +2380,7 @@ proc layoutRootBlock(lctx: LayoutState; builder: BoxBuilder; box.size.h = bctx.maxFloatHeight - box.offset.y - marginBottomOut return box -proc initBlockPositionStates(state: var BlockState, bctx: var BlockContext, +proc initBlockPositionStates(state: var BlockState; bctx: var BlockContext; box: BlockBox) = let prevBps = bctx.ancestorsHead bctx.ancestorsHead = BlockPositionState( @@ -2389,7 +2411,7 @@ proc initBlockPositionStates(state: var BlockState, bctx: var BlockContext, bctx.parentBps = bctx.ancestorsHead state.initialParentOffset = bctx.parentBps.offset -func isParentResolved(state: BlockState, bctx: BlockContext): bool = +func isParentResolved(state: BlockState; bctx: BlockContext): bool = return bctx.marginTarget != state.initialMarginTarget or state.prevParentBps != nil and state.prevParentBps.resolved @@ -2397,13 +2419,13 @@ func isParentResolved(state: BlockState, bctx: BlockContext): bool = # Box placement must occur during this pass, since child box layout in the # same block formatting context depends on knowing where the box offset is # (because of floats). -proc layoutBlockChildren(state: var BlockState, bctx: var BlockContext, +proc layoutBlockChildren(state: var BlockState; bctx: var BlockContext; children: seq[BoxBuilder]) = for builder in children: var dy: LayoutUnit = 0 # delta var child: BlockBox - let isfloat = builder.computed{"float"} != FLOAT_NONE - let isinflow = builder.computed{"position"} != POSITION_ABSOLUTE and + let isfloat = builder.computed{"float"} != FloatNone + let isinflow = builder.computed{"position"} != PositionAbsolute and not isfloat if builder.computed.establishesBFC(): var marginBottomOut: LayoutUnit @@ -2434,11 +2456,11 @@ proc layoutBlockChildren(state: var BlockState, bctx: var BlockContext, let childWidth = child.margin.left + child.size.w + child.margin.right state.maxChildWidth = max(state.maxChildWidth, childWidth) state.xminwidth = max(state.xminwidth, child.xminwidth) - if child.computed{"position"} != POSITION_ABSOLUTE and not isfloat: + if child.computed{"position"} != PositionAbsolute and not isfloat: # Not absolute, and not a float. state.offset.y += dy elif isfloat: - if state.space.w.t == FIT_CONTENT: + if state.space.w.t == scFitContent: # Float position depends on the available width, but in this case # the parent width is not known. # Set the "re-layout" flag, and skip this box. @@ -2474,8 +2496,8 @@ proc layoutBlockChildren(state: var BlockState, bctx: var BlockContext, # Unlucky path, where we have floating blocks and a fit-content width. # Reset marginTodo & the starting offset, and stretch the box to the # max child width. -proc initReLayout(state: var BlockState, bctx: var BlockContext, - box: BlockBox, sizes: ResolvedSizes) = +proc initReLayout(state: var BlockState; bctx: var BlockContext; + box: BlockBox; sizes: ResolvedSizes) = bctx.marginTodo = state.oldMarginTodo # Note: we do not reset our own BlockPositionState's offset; we assume it # has already been resolved in the previous pass. @@ -2512,22 +2534,22 @@ proc initReLayout(state: var BlockState, bctx: var BlockContext, # Re-position the children. # The x offset with a fit-content width depends on the parent box's width, # so we cannot do this in the first pass. -proc repositionChildren(state: BlockState, box: BlockBox, lctx: LayoutState) = +proc repositionChildren(state: BlockState; box: BlockBox; lctx: LayoutState) = for child in state.nested: - if child.computed{"position"} != POSITION_ABSOLUTE: + if child.computed{"position"} != PositionAbsolute: box.postAlignChild(child, box.size.w) case child.computed{"position"} - of POSITION_RELATIVE: + of PositionRelative: box.positionRelative(child, lctx) - of POSITION_ABSOLUTE: + of PositionAbsolute: lctx.positionAbsolute(child, child.margin) else: discard #TODO -proc layoutBlock(bctx: var BlockContext, box: BlockBox, - builder: BlockBoxBuilder, sizes: ResolvedSizes) = +proc layoutBlock(bctx: var BlockContext; box: BlockBox; + builder: BlockBoxBuilder; sizes: ResolvedSizes) = let lctx = bctx.lctx let positioned = box.computed{"position"} notin { - POSITION_STATIC, POSITION_FIXED, POSITION_STICKY + PositionStatic, PositionFixed, PositionSticky } if positioned: lctx.positioned.add(sizes.space) @@ -2572,12 +2594,12 @@ proc layoutBlock(bctx: var BlockContext, box: BlockBox, # Tree generation (1st pass) -proc newMarkerBox(computed: CSSComputedValues, listItemCounter: int): +proc newMarkerBox(computed: CSSComputedValues; listItemCounter: int): MarkerBoxBuilder = let computed = computed.inheritProperties() - computed{"display"} = DISPLAY_INLINE + computed{"display"} = DisplayInline # Use pre, so the space at the end of the default markers isn't ignored. - computed{"white-space"} = WHITESPACE_PRE + computed{"white-space"} = WhitespacePre return MarkerBoxBuilder( computed: computed, text: @[computed{"list-style-type"}.listMarker(listItemCounter)] @@ -2601,16 +2623,16 @@ type InnerBlockContext = object parent: ptr InnerBlockContext inlineStack: seq[StyledNode] -proc add(blockgroup: var BlockGroup, box: BoxBuilder) {.inline.} = - assert box.computed{"display"} in {DISPLAY_INLINE, DISPLAY_INLINE_TABLE, - DISPLAY_INLINE_BLOCK}, $box.computed{"display"} +proc add(blockgroup: var BlockGroup; box: BoxBuilder) {.inline.} = + assert box.computed{"display"} in {DisplayInline, DisplayInlineTable, + DisplayInlineBlock}, $box.computed{"display"} blockgroup.boxes.add(box) proc flush(blockgroup: var BlockGroup) = if blockgroup.boxes.len > 0: - assert blockgroup.parent.computed{"display"} != DISPLAY_INLINE + assert blockgroup.parent.computed{"display"} != DisplayInline let computed = blockgroup.parent.computed.inheritProperties() - computed{"display"} = DISPLAY_BLOCK + computed{"display"} = DisplayBlock let bbox = BlockBoxBuilder(computed: computed) bbox.inlinelayout = true bbox.children = blockgroup.boxes @@ -2618,32 +2640,32 @@ proc flush(blockgroup: var BlockGroup) = blockgroup.boxes.setLen(0) # Don't generate empty anonymous inline blocks between block boxes -func canGenerateAnonymousInline(blockgroup: BlockGroup, - computed: CSSComputedValues, str: string): bool = +func canGenerateAnonymousInline(blockgroup: BlockGroup; + computed: CSSComputedValues; str: string): bool = return blockgroup.boxes.len > 0 and - blockgroup.boxes[^1].computed{"display"} == DISPLAY_INLINE or + blockgroup.boxes[^1].computed{"display"} == DisplayInline or computed.whitespacepre or not str.onlyWhitespace() proc newBlockGroup(parent: BlockBoxBuilder): BlockGroup = - assert parent.computed{"display"} != DISPLAY_INLINE + assert parent.computed{"display"} != DisplayInline return BlockGroup(parent: parent) -proc generateTableBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableBoxBuilder -proc generateTableRowGroupBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableRowGroupBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableRowGroupBoxBuilder -proc generateTableRowBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableRowBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableRowBoxBuilder -proc generateTableCellBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableCellBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableCellBoxBuilder -proc generateTableCaptionBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableCaptionBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableCaptionBoxBuilder -proc generateBlockBox(styledNode: StyledNode, lctx: LayoutState, +proc generateBlockBox(styledNode: StyledNode; lctx: LayoutState; marker = none(MarkerBoxBuilder), parent: ptr InnerBlockContext = nil): BlockBoxBuilder proc generateFlexBox(styledNode: StyledNode; lctx: LayoutState; parent: ptr InnerBlockContext = nil): BlockBoxBuilder -proc generateInlineBoxes(ctx: var InnerBlockContext, styledNode: StyledNode) +proc generateInlineBoxes(ctx: var InnerBlockContext; styledNode: StyledNode) proc generateBlockBox(pctx: var InnerBlockContext; styledNode: StyledNode; marker = none(MarkerBoxBuilder)): BlockBoxBuilder = @@ -2655,12 +2677,12 @@ proc generateFlexBox(pctx: var InnerBlockContext; styledNode: StyledNode): proc flushTableRow(ctx: var InnerBlockContext) = if ctx.anonRow != nil: - if ctx.blockgroup.parent.computed{"display"} == DISPLAY_TABLE_ROW: + if ctx.blockgroup.parent.computed{"display"} == DisplayTableRow: ctx.blockgroup.parent.children.add(ctx.anonRow) else: if ctx.anonTable == nil: var wrappervals = ctx.styledNode.computed.inheritProperties() - wrappervals{"display"} = DISPLAY_TABLE + wrappervals{"display"} = DisplayTable ctx.anonTable = TableBoxBuilder(computed: wrappervals) ctx.anonTable.children.add(ctx.anonRow) ctx.anonRow = nil @@ -2672,8 +2694,8 @@ proc flushTable(ctx: var InnerBlockContext) = proc iflush(ctx: var InnerBlockContext) = if ctx.iroot != nil: - assert ctx.iroot.computed{"display"} in {DISPLAY_INLINE, - DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE} + assert ctx.iroot.computed{"display"} in {DisplayInline, DisplayInlineBlock, + DisplayInlineTable} ctx.blockgroup.add(ctx.iroot) ctx.iroot = nil ctx.ibox = nil @@ -2711,34 +2733,34 @@ proc reconstructInlineParents(ctx: var InnerBlockContext): InlineBoxBuilder = proc generateFromElem(ctx: var InnerBlockContext; styledNode: StyledNode) = let box = ctx.blockgroup.parent case styledNode.computed{"display"} - of DISPLAY_BLOCK, DISPLAY_FLOW_ROOT: + of DisplayBlock, DisplayFlowRoot: ctx.iflush() ctx.flush() let childbox = ctx.generateBlockBox(styledNode) box.children.add(childbox) - of DISPLAY_FLEX: + of DisplayFlex: ctx.iflush() ctx.flush() let childbox = ctx.generateFlexBox(styledNode) box.children.add(childbox) - of DISPLAY_LIST_ITEM: + of DisplayListItem: ctx.flush() inc ctx.listItemCounter let childbox = ListItemBoxBuilder( computed: styledNode.computed, marker: newMarkerBox(styledNode.computed, ctx.listItemCounter) ) - if childbox.computed{"list-style-position"} == LIST_STYLE_POSITION_INSIDE: + if childbox.computed{"list-style-position"} == ListStylePositionInside: childbox.content = ctx.generateBlockBox(styledNode, some(childbox.marker)) childbox.marker = nil else: childbox.content = ctx.generateBlockBox(styledNode) childbox.content.computed = childbox.content.computed.copyProperties() - childbox.content.computed{"display"} = DISPLAY_BLOCK + childbox.content.computed{"display"} = DisplayBlock box.children.add(childbox) - of DISPLAY_INLINE: + of DisplayInline: ctx.generateInlineBoxes(styledNode) - of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE, DISPLAY_INLINE_FLEX: + of DisplayInlineBlock, DisplayInlineTable, DisplayInlineFlex: # create a new inline box that we can safely put our inline block into ctx.iflush() let computed = styledNode.computed.inheritProperties() @@ -2750,20 +2772,20 @@ proc generateFromElem(ctx: var InnerBlockContext; styledNode: StyledNode) = else: ctx.iroot = ctx.ibox var childbox: BoxBuilder - if styledNode.computed{"display"} == DISPLAY_INLINE_BLOCK: + if styledNode.computed{"display"} == DisplayInlineBlock: childbox = ctx.generateBlockBox(styledNode) - elif styledNode.computed{"display"} == DISPLAY_INLINE_TABLE: + elif styledNode.computed{"display"} == DisplayInlineTable: childbox = styledNode.generateTableBox(ctx.lctx, ctx) else: - assert styledNode.computed{"display"} == DISPLAY_INLINE_FLEX + assert styledNode.computed{"display"} == DisplayInlineFlex childbox = ctx.generateFlexBox(styledNode) ctx.ibox.children.add(childbox) ctx.iflush() - of DISPLAY_TABLE: + of DisplayTable: ctx.flush() let childbox = styledNode.generateTableBox(ctx.lctx, ctx) box.children.add(childbox) - of DISPLAY_TABLE_ROW: + of DisplayTableRow: ctx.bflush() ctx.flushTableRow() let childbox = styledNode.generateTableRowBox(ctx.lctx, ctx) @@ -2773,54 +2795,53 @@ proc generateFromElem(ctx: var InnerBlockContext; styledNode: StyledNode) = if ctx.anonTable == nil: var wrappervals = box.computed.inheritProperties() #TODO make this an inline-table if we're in an inline context - wrappervals{"display"} = DISPLAY_TABLE + wrappervals{"display"} = DisplayTable ctx.anonTable = TableBoxBuilder(computed: wrappervals) ctx.anonTable.children.add(childbox) - of DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP, - DISPLAY_TABLE_FOOTER_GROUP: + of DisplayTableRowGroup, DisplayTableHeaderGroup, DisplayTableFooterGroup: ctx.bflush() ctx.flushTableRow() let childbox = styledNode.generateTableRowGroupBox(ctx.lctx, ctx) - if box.computed{"display"} in {DISPLAY_TABLE, DISPLAY_INLINE_TABLE}: + if box.computed{"display"} in {DisplayTable, DisplayInlineTable}: box.children.add(childbox) else: if ctx.anonTable == nil: var wrappervals = box.computed.inheritProperties() #TODO make this an inline-table if we're in an inline context - wrappervals{"display"} = DISPLAY_TABLE + wrappervals{"display"} = DisplayTable ctx.anonTable = TableBoxBuilder(computed: wrappervals) ctx.anonTable.children.add(childbox) - of DISPLAY_TABLE_CELL: + of DisplayTableCell: ctx.bflush() let childbox = styledNode.generateTableCellBox(ctx.lctx, ctx) - if box.computed{"display"} == DISPLAY_TABLE_ROW: + if box.computed{"display"} == DisplayTableRow: box.children.add(childbox) else: if ctx.anonRow == nil: var wrappervals = box.computed.inheritProperties() - wrappervals{"display"} = DISPLAY_TABLE_ROW + wrappervals{"display"} = DisplayTableRow ctx.anonRow = TableRowBoxBuilder(computed: wrappervals) ctx.anonRow.children.add(childbox) - of DISPLAY_TABLE_CAPTION: + of DisplayTableCaption: ctx.bflush() ctx.flushTableRow() let childbox = styledNode.generateTableCaptionBox(ctx.lctx, ctx) - if box.computed{"display"} in {DISPLAY_TABLE, DISPLAY_INLINE_TABLE}: + if box.computed{"display"} in {DisplayTable, DisplayInlineTable}: box.children.add(childbox) else: if ctx.anonTable == nil: var wrappervals = box.computed.inheritProperties() #TODO make this an inline-table if we're in an inline context - wrappervals{"display"} = DISPLAY_TABLE + wrappervals{"display"} = DisplayTable ctx.anonTable = TableBoxBuilder(computed: wrappervals) ctx.anonTable.children.add(childbox) - of DISPLAY_TABLE_COLUMN: + of DisplayTableColumn: discard #TODO - of DISPLAY_TABLE_COLUMN_GROUP: + of DisplayTableColumnGroup: discard #TODO - of DISPLAY_NONE: discard + of DisplayNone: discard -proc generateAnonymousInlineText(ctx: var InnerBlockContext, text: string, +proc generateAnonymousInlineText(ctx: var InnerBlockContext; text: string; styledNode: StyledNode) = if ctx.iroot == nil: let computed = styledNode.computed.inheritProperties() @@ -2833,9 +2854,10 @@ proc generateAnonymousInlineText(ctx: var InnerBlockContext, text: string, ctx.iroot = ctx.ibox ctx.ibox.text.add(text) -proc generateReplacement(ctx: var InnerBlockContext, child, parent: StyledNode) = +proc generateReplacement(ctx: var InnerBlockContext; + child, parent: StyledNode) = case child.content.t - of CONTENT_OPEN_QUOTE: + of ContentOpenQuote: let quotes = parent.computed{"quotes"} var text: string if quotes.qs.len > 0: @@ -2845,7 +2867,7 @@ proc generateReplacement(ctx: var InnerBlockContext, child, parent: StyledNode) else: return ctx.generateAnonymousInlineText(text, parent) inc ctx.quoteLevel - of CONTENT_CLOSE_QUOTE: + of ContentCloseQuote: if ctx.quoteLevel > 0: dec ctx.quoteLevel let quotes = parent.computed{"quotes"} var text: string @@ -2855,21 +2877,21 @@ proc generateReplacement(ctx: var InnerBlockContext, child, parent: StyledNode) text = quoteEnd(ctx.quoteLevel) else: return ctx.generateAnonymousInlineText(text, parent) - of CONTENT_NO_OPEN_QUOTE: + of ContentNoOpenQuote: inc ctx.quoteLevel - of CONTENT_NO_CLOSE_QUOTE: + of ContentNoCloseQuote: if ctx.quoteLevel > 0: dec ctx.quoteLevel - of CONTENT_STRING: + of ContentString: #TODO canGenerateAnonymousInline? ctx.generateAnonymousInlineText(child.content.s, parent) - of CONTENT_IMAGE: + of ContentImage: #TODO idk ctx.generateAnonymousInlineText("[img]", parent) - of CONTENT_VIDEO: + of ContentVideo: ctx.generateAnonymousInlineText("[video]", parent) - of CONTENT_AUDIO: + of ContentAudio: ctx.generateAnonymousInlineText("[audio]", parent) - of CONTENT_NEWLINE: + of ContentNewline: ctx.iflush() #TODO ?? # this used to set ibox (before we had iroot), now I'm not sure if we @@ -2878,7 +2900,7 @@ proc generateReplacement(ctx: var InnerBlockContext, child, parent: StyledNode) ctx.iroot.newline = true ctx.iflush() -proc generateInlineBoxes(ctx: var InnerBlockContext, styledNode: StyledNode) = +proc generateInlineBoxes(ctx: var InnerBlockContext; styledNode: StyledNode) = ctx.iflush() ctx.inlineStack.add(styledNode) var lbox = ctx.reconstructInlineParents() @@ -2886,15 +2908,15 @@ proc generateInlineBoxes(ctx: var InnerBlockContext, styledNode: StyledNode) = ctx.ibox = lbox for child in styledNode.children: case child.t - of STYLED_ELEMENT: + of stElement: ctx.generateFromElem(child) - of STYLED_TEXT: + of stText: if ctx.ibox != lbox: ctx.iflush() lbox = ctx.reconstructInlineParents() ctx.ibox = lbox lbox.text.add(child.text) - of STYLED_REPLACEMENT: + of stReplacement: ctx.generateReplacement(child, styledNode) if ctx.ibox != lbox: ctx.iflush() @@ -2904,8 +2926,8 @@ proc generateInlineBoxes(ctx: var InnerBlockContext, styledNode: StyledNode) = ctx.inlineStack.setLen(ctx.inlineStack.len - 1) ctx.iflush() -proc newInnerBlockContext(styledNode: StyledNode, box: BlockBoxBuilder, - lctx: LayoutState, parent: ptr InnerBlockContext): InnerBlockContext = +proc newInnerBlockContext(styledNode: StyledNode; box: BlockBoxBuilder; + lctx: LayoutState; parent: ptr InnerBlockContext): InnerBlockContext = var ctx = InnerBlockContext( styledNode: styledNode, blockgroup: newBlockGroup(box), @@ -2923,16 +2945,16 @@ proc newInnerBlockContext(styledNode: StyledNode, box: BlockBoxBuilder, proc generateInnerBlockBox(ctx: var InnerBlockContext) = let box = ctx.blockgroup.parent - assert box.computed{"display"} != DISPLAY_INLINE + assert box.computed{"display"} != DisplayInline for child in ctx.styledNode.children: case child.t - of STYLED_ELEMENT: + of stElement: ctx.iflush() ctx.generateFromElem(child) - of STYLED_TEXT: + of stText: if canGenerateAnonymousInline(ctx.blockgroup, box.computed, child.text): ctx.generateAnonymousInlineText(child.text, ctx.styledNode) - of STYLED_REPLACEMENT: + of stReplacement: ctx.generateReplacement(child, ctx.styledNode) ctx.iflush() @@ -2964,10 +2986,10 @@ proc generateFlexBox(styledNode: StyledNode; lctx: LayoutState; parent: ptr InnerBlockContext = nil): BlockBoxBuilder = let box = BlockBoxBuilder(computed: styledNode.computed, node: styledNode) var ctx = newInnerBlockContext(styledNode, box, lctx, parent) - assert box.computed{"display"} != DISPLAY_INLINE + assert box.computed{"display"} != DisplayInline for child in ctx.styledNode.children: case child.t - of STYLED_ELEMENT: + of stElement: ctx.iflush() let display = child.computed{"display"}.blockify() if display != child.computed{"display"}: @@ -2981,10 +3003,10 @@ proc generateFlexBox(styledNode: StyledNode; lctx: LayoutState; ctx.generateFromElem(newChild) else: ctx.generateFromElem(child) - of STYLED_TEXT: + of stText: if ctx.blockgroup.canGenerateAnonymousInline(box.computed, child.text): ctx.generateAnonymousInlineText(child.text, ctx.styledNode) - of STYLED_REPLACEMENT: + of stReplacement: ctx.generateReplacement(child, ctx.styledNode) ctx.iflush() # Flush anonymous tables here, to avoid setting inline layout with tables. @@ -2996,7 +3018,7 @@ proc generateFlexBox(styledNode: StyledNode; lctx: LayoutState; assert not box.inlinelayout return box -proc generateTableCellBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableCellBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableCellBoxBuilder = let box = TableCellBoxBuilder(computed: styledNode.computed) var ctx = newInnerBlockContext(styledNode, box, lctx, addr parent) @@ -3007,9 +3029,9 @@ proc generateTableCellBox(styledNode: StyledNode, lctx: LayoutState, proc generateTableRowChildWrappers(box: TableRowBoxBuilder) = var newchildren = newSeqOfCap[BoxBuilder](box.children.len) var wrappervals = box.computed.inheritProperties() - wrappervals{"display"} = DISPLAY_TABLE_CELL + wrappervals{"display"} = DisplayTableCell for child in box.children: - if child.computed{"display"} == DISPLAY_TABLE_CELL: + if child.computed{"display"} == DisplayTableCell: newchildren.add(child) else: let wrapper = TableCellBoxBuilder(computed: wrappervals) @@ -3017,7 +3039,7 @@ proc generateTableRowChildWrappers(box: TableRowBoxBuilder) = newchildren.add(wrapper) box.children = newchildren -proc generateTableRowBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableRowBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableRowBoxBuilder = let box = TableRowBoxBuilder(computed: styledNode.computed) var ctx = newInnerBlockContext(styledNode, box, lctx, addr parent) @@ -3029,9 +3051,9 @@ proc generateTableRowBox(styledNode: StyledNode, lctx: LayoutState, proc generateTableRowGroupChildWrappers(box: TableRowGroupBoxBuilder) = var newchildren = newSeqOfCap[BoxBuilder](box.children.len) var wrappervals = box.computed.inheritProperties() - wrappervals{"display"} = DISPLAY_TABLE_ROW + wrappervals{"display"} = DisplayTableRow for child in box.children: - if child.computed{"display"} == DISPLAY_TABLE_ROW: + if child.computed{"display"} == DisplayTableRow: newchildren.add(child) else: let wrapper = TableRowBoxBuilder(computed: wrappervals) @@ -3040,7 +3062,7 @@ proc generateTableRowGroupChildWrappers(box: TableRowGroupBoxBuilder) = newchildren.add(wrapper) box.children = newchildren -proc generateTableRowGroupBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableRowGroupBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableRowGroupBoxBuilder = let box = TableRowGroupBoxBuilder(computed: styledNode.computed) var ctx = newInnerBlockContext(styledNode, box, lctx, addr parent) @@ -3049,7 +3071,7 @@ proc generateTableRowGroupBox(styledNode: StyledNode, lctx: LayoutState, box.generateTableRowGroupChildWrappers() return box -proc generateTableCaptionBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableCaptionBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableCaptionBoxBuilder = let box = TableCaptionBoxBuilder(computed: styledNode.computed) var ctx = newInnerBlockContext(styledNode, box, lctx, addr parent) @@ -3060,7 +3082,7 @@ proc generateTableCaptionBox(styledNode: StyledNode, lctx: LayoutState, proc generateTableChildWrappers(box: TableBoxBuilder) = var newchildren = newSeqOfCap[BoxBuilder](box.children.len) var wrappervals = box.computed.inheritProperties() - wrappervals{"display"} = DISPLAY_TABLE_ROW + wrappervals{"display"} = DisplayTableRow for child in box.children: if child.computed{"display"} in ProperTableChild: newchildren.add(child) @@ -3071,7 +3093,7 @@ proc generateTableChildWrappers(box: TableBoxBuilder) = newchildren.add(wrapper) box.children = newchildren -proc generateTableBox(styledNode: StyledNode, lctx: LayoutState, +proc generateTableBox(styledNode: StyledNode; lctx: LayoutState; parent: var InnerBlockContext): TableBoxBuilder = let box = TableBoxBuilder(computed: styledNode.computed, node: styledNode) var ctx = newInnerBlockContext(styledNode, box, lctx, addr parent) diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim index 7227cbfe..fe7b92cb 100644 --- a/src/layout/renderdocument.nim +++ b/src/layout/renderdocument.nim @@ -55,17 +55,17 @@ func toFormat(computed: CSSComputedValues): Format = if computed == nil: return Format() var flags: set[FormatFlags] - if computed{"font-style"} in {FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE}: + if computed{"font-style"} in {FontStyleItalic, FontStyleOblique}: flags.incl(ffItalic) if computed{"font-weight"} > 500: flags.incl(ffBold) - if TEXT_DECORATION_UNDERLINE in computed{"text-decoration"}: + if TextDecorationUnderline in computed{"text-decoration"}: flags.incl(ffUnderline) - if TEXT_DECORATION_OVERLINE in computed{"text-decoration"}: + if TextDecorationOverline in computed{"text-decoration"}: flags.incl(ffOverline) - if TEXT_DECORATION_LINE_THROUGH in computed{"text-decoration"}: + if TextDecorationLineThrough in computed{"text-decoration"}: flags.incl(ffStrike) - if TEXT_DECORATION_BLINK in computed{"text-decoration"}: + if TextDecorationBlink in computed{"text-decoration"}: flags.incl(ffBlink) return Format( fgcolor: computed{"color"}, @@ -361,7 +361,7 @@ proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState; grid.setRowWord(state, atom, offset, format, fragment.node) of iatSpacing: grid.setSpacing(state, atom, offset, format, fragment.node) - if fragment.computed{"position"} != POSITION_STATIC: + if fragment.computed{"position"} != PositionStatic: if fragment.splitType != {stSplitStart, stSplitEnd}: if stSplitStart in fragment.splitType: state.absolutePos.add(Offset( @@ -400,11 +400,11 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState; offset.y = state.absolutePos[^1].y offset.x += box.offset.x offset.y += box.offset.y - if box.computed{"position"} != POSITION_STATIC: + if box.computed{"position"} != PositionStatic: state.absolutePos.add(offset) stack.add((nil, Offset(x: -1, y: -1))) - if box.computed{"visibility"} == VISIBILITY_VISIBLE: + if box.computed{"visibility"} == VisibilityVisible: let bgcolor = box.computed{"background-color"} if bgcolor.t == ctANSI or bgcolor.t == ctRGB and bgcolor.rgbacolor.a > 0: if box.computed{"-cha-bgcolor-is-canvas"} and @@ -417,7 +417,7 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState; let iex = toInt(offset.x + box.size.w) let iey = toInt(offset.y + box.size.h) grid.paintBackground(state, bgcolor, ix, iy, iex, iey, box.node) - if box.computed{"background-image"}.t == CONTENT_IMAGE and + if box.computed{"background-image"}.t == ContentImage and box.computed{"background-image"}.s != "": # ugly hack for background-image display... TODO actually display images let s = "[img]" @@ -433,7 +433,7 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState; grid.setText(s, x, y, box.computed.toFormat(), box.node) if box.inline != nil: assert box.nested.len == 0 - if box.computed{"visibility"} == VISIBILITY_VISIBLE: + if box.computed{"visibility"} == VisibilityVisible: grid.renderRootInlineFragment(state, box.inline, offset) else: for i in countdown(box.nested.high, 0): diff --git a/src/loader/cgi.nim b/src/loader/cgi.nim index 10809767..79344b6f 100644 --- a/src/loader/cgi.nim +++ b/src/loader/cgi.nim @@ -96,7 +96,7 @@ proc handleFirstLine(handle: LoaderHandle; line: string; headers: Headers; headers.add(k, v) return crDone -proc handleControlLine(handle: LoaderHandle, line: string, headers: Headers, +proc handleControlLine(handle: LoaderHandle; line: string; headers: Headers; status: var uint16): ControlResult = let k = line.until(':') if k.len == line.len: @@ -114,7 +114,7 @@ proc handleControlLine(handle: LoaderHandle, line: string, headers: Headers, return crDone # returns false if transfer was interrupted -proc handleLine(handle: LoaderHandle, line: string, headers: Headers) = +proc handleLine(handle: LoaderHandle; line: string; headers: Headers) = let k = line.until(':') if k.len == line.len: # invalid diff --git a/src/loader/headers.nim b/src/loader/headers.nim index 20764760..d870eaea 100644 --- a/src/loader/headers.nim +++ b/src/loader/headers.nim @@ -32,21 +32,21 @@ proc fromJSHeadersInit(ctx: JSContext; val: JSValue): JSResult[HeadersInit] = let x = ?fromJS[Table[string, string]](ctx, val) return ok(HeadersInit(t: HEADERS_INIT_TABLE, tab: x)) -proc fill*(headers: Headers, s: seq[(string, string)]) = +proc fill*(headers: Headers; s: seq[(string, string)]) = for (k, v) in s: if k in headers.table: headers.table[k].add(v) else: headers.table[k] = @[v] -proc fill*(headers: Headers, tab: Table[string, string]) = +proc fill*(headers: Headers; tab: Table[string, string]) = for k, v in tab: if k in headers.table: headers.table[k].add(v) else: headers.table[k] = @[v] -proc fill*(headers: Headers, init: HeadersInit) = +proc fill*(headers: Headers; init: HeadersInit) = if init.t == HEADERS_INIT_SEQUENCE: headers.fill(init.s) else: # table @@ -86,26 +86,26 @@ func clone*(headers: Headers): Headers = table: headers.table ) -proc add*(headers: Headers, k, v: string) = +proc add*(headers: Headers; k, v: string) = let k = k.toHeaderCase() headers.table.withValue(k, p): p[].add(v) do: headers.table[k] = @[v] -proc `[]=`*(headers: Headers, k: static string, v: string) = +proc `[]=`*(headers: Headers; k: static string, v: string) = const k = k.toHeaderCase() headers.table[k] = @[v] -func `[]`*(headers: Headers, k: static string): string = +func `[]`*(headers: Headers; k: static string): string = const k = k.toHeaderCase() return headers.table[k][0] -func contains*(headers: Headers, k: static string): bool = +func contains*(headers: Headers; k: static string): bool = const k = k.toHeaderCase() return k in headers.table -func getOrDefault*(headers: Headers, k: static string, default = ""): string = +func getOrDefault*(headers: Headers; k: static string; default = ""): string = const k = k.toHeaderCase() headers.table.withValue(k, p): return p[][0] diff --git a/src/loader/loader.nim b/src/loader/loader.nim index 37da64cb..207600f2 100644 --- a/src/loader/loader.nim +++ b/src/loader/loader.nim @@ -970,7 +970,7 @@ proc redirectToFile*(loader: FileLoader; outputId: int; targetPath: string): const BufferSize = 4096 -proc onConnected*(loader: FileLoader, fd: int) = +proc onConnected*(loader: FileLoader; fd: int) = let connectData = loader.connecting[fd] let stream = connectData.stream let promise = connectData.promise diff --git a/src/loader/request.nim b/src/loader/request.nim index 824e643e..7be0f818 100644 --- a/src/loader/request.nim +++ b/src/loader/request.nim @@ -139,8 +139,8 @@ func newRequest*(url: URL; httpMethod = HTTP_GET; proxy = proxy ) -func createPotentialCORSRequest*(url: URL, destination: RequestDestination, - cors: CORSAttribute, fallbackFlag = false): Request = +func createPotentialCORSRequest*(url: URL; destination: RequestDestination; + cors: CORSAttribute; fallbackFlag = false): Request = var mode = if cors == NO_CORS: RequestMode.NO_CORS else: @@ -150,7 +150,12 @@ func createPotentialCORSRequest*(url: URL, destination: RequestDestination, let credentialsMode = if cors == ANONYMOUS: CredentialsMode.SAME_ORIGIN else: CredentialsMode.INCLUDE - return newRequest(url, destination = destination, mode = mode, credentialsMode = credentialsMode) + return newRequest( + url, + destination = destination, + mode = mode, + credentialsMode = credentialsMode + ) type BodyInitType = enum @@ -180,7 +185,7 @@ type proxyUrl: URL mode: Option[RequestMode] -proc fromJSBodyInit(ctx: JSContext, val: JSValue): JSResult[BodyInit] = +proc fromJSBodyInit(ctx: JSContext; val: JSValue): JSResult[BodyInit] = if JS_IsUndefined(val) or JS_IsNull(val): return err(nil) block formData: @@ -201,7 +206,7 @@ proc fromJSBodyInit(ctx: JSContext, val: JSValue): JSResult[BodyInit] = return ok(BodyInit(t: BODY_INIT_STRING, str: x.get)) return err(newTypeError("Invalid body init type")) -func newRequest*[T: string|Request](ctx: JSContext, resource: T, +func newRequest*[T: string|Request](ctx: JSContext; resource: T; init = none(RequestInit)): JSResult[Request] {.jsctor.} = when T is string: let url = ?newURL(resource) diff --git a/src/loader/response.nim b/src/loader/response.nim index dbec92d2..648b2e2b 100644 --- a/src/loader/response.nim +++ b/src/loader/response.nim @@ -145,7 +145,7 @@ proc blob*(response: Response): Promise[JSResult[Blob]] {.jsfunc.} = let blob = newBlob(unsafeAddr s[0], s.len, contentType, deallocFun) ok(blob)) -proc json(ctx: JSContext, this: Response): Promise[JSResult[JSValue]] +proc json(ctx: JSContext; this: Response): Promise[JSResult[JSValue]] {.jsfunc.} = return this.text().then(proc(s: JSResult[string]): JSResult[JSValue] = let s = ?s diff --git a/src/local/client.nim b/src/local/client.nim index c4aad504..92fa4660 100644 --- a/src/local/client.nim +++ b/src/local/client.nim @@ -3,15 +3,13 @@ import std/nativesockets import std/net import std/options import std/os +import std/posix import std/selectors import std/streams import std/strutils import std/tables import std/unicode -when defined(posix): - import std/posix - import bindings/constcharp import bindings/quickjs import config/config @@ -67,7 +65,7 @@ type jsrt: JSRuntime pager {.jsget.}: Pager timeouts: TimeoutState - pressed: tuple[col: int, row: int] + pressed: tuple[col: int; row: int] ConsoleWrapper = object console: Console @@ -97,12 +95,12 @@ proc finalize(client: Client) {.jsfin.} = if client.jsrt != nil: free(client.jsrt) -proc fetch[T: Request|string](client: Client, req: T, +proc fetch[T: Request|string](client: Client; req: T; init = none(RequestInit)): JSResult[FetchPromise] {.jsfunc.} = let req = ?newRequest(client.jsctx, req, init) return ok(client.loader.fetch(req)) -proc interruptHandler(rt: JSRuntime, opaque: pointer): cint {.cdecl.} = +proc interruptHandler(rt: JSRuntime; opaque: pointer): cint {.cdecl.} = let client = cast[Client](opaque) if client.console == nil or client.pager.term.istream == nil: return 0 @@ -120,7 +118,7 @@ proc interruptHandler(rt: JSRuntime, opaque: pointer): cint {.cdecl.} = proc runJSJobs(client: Client) = client.jsrt.runJSJobs(client.console.err) -proc evalJS(client: Client, src, filename: string, module = false): JSValue = +proc evalJS(client: Client; src, filename: string; module = false): JSValue = client.pager.term.unblockStdin() let flags = if module: JS_EVAL_TYPE_MODULE @@ -130,11 +128,11 @@ proc evalJS(client: Client, src, filename: string, module = false): JSValue = client.runJSJobs() client.pager.term.restoreStdin() -proc evalJSFree(client: Client, src, filename: string) = +proc evalJSFree(client: Client; src, filename: string) = JS_FreeValue(client.jsctx, client.evalJS(src, filename)) -proc command0(client: Client, src: string, filename = "<command>", - silence = false, module = false) = +proc command0(client: Client; src: string; filename = "<command>"; + silence = false; module = false) = let ret = client.evalJS(src, filename, module = module) if JS_IsException(ret): client.jsctx.writeException(client.console.err) @@ -145,7 +143,7 @@ proc command0(client: Client, src: string, filename = "<command>", client.console.log(str.get) JS_FreeValue(client.jsctx, ret) -proc command(client: Client, src: string) = +proc command(client: Client; src: string) = client.command0(src) let container = client.consoleWrapper.container if container != nil: @@ -156,7 +154,7 @@ proc suspend(client: Client) {.jsfunc.} = discard kill(0, cint(SIGTSTP)) client.pager.term.restart() -proc quit(client: Client, code = 0) {.jsfunc.} = +proc quit(client: Client; code = 0) {.jsfunc.} = if client.alive: client.alive = false client.pager.quit() @@ -173,7 +171,7 @@ proc quit(client: Client, code = 0) {.jsfunc.} = proc feedNext(client: Client) {.jsfunc.} = client.feednext = true -proc alert(client: Client, msg: string) {.jsfunc.} = +proc alert(client: Client; msg: string) {.jsfunc.} = client.pager.alert(msg) proc handlePagerEvents(client: Client) = @@ -218,7 +216,7 @@ proc evalAction(client: Client; action: string; arg0: int32): EmptyPromise = # it proves to be too low. const MaxPrecNum = 100000000 -proc handleCommandInput(client: Client, c: char): EmptyPromise = +proc handleCommandInput(client: Client; c: char): EmptyPromise = if client.config.input.vi_numeric_prefix and not client.pager.notnum: if client.pager.precnum != 0 and c == '0' or c in '1' .. '9': if client.pager.precnum < MaxPrecNum: # better ignore than eval... @@ -354,18 +352,18 @@ proc input(client: Client): EmptyPromise = p.resolve() return p -proc setTimeout[T: JSValue|string](client: Client, handler: T, +proc setTimeout[T: JSValue|string](client: Client; handler: T; timeout = 0i32): int32 {.jsfunc.} = return client.timeouts.setTimeout(handler, timeout) -proc setInterval[T: JSValue|string](client: Client, handler: T, +proc setInterval[T: JSValue|string](client: Client; handler: T; interval = 0i32): int32 {.jsfunc.} = return client.timeouts.setInterval(handler, interval) -proc clearTimeout(client: Client, id: int32) {.jsfunc.} = +proc clearTimeout(client: Client; id: int32) {.jsfunc.} = client.timeouts.clearTimeout(id) -proc clearInterval(client: Client, id: int32) {.jsfunc.} = +proc clearInterval(client: Client; id: int32) {.jsfunc.} = client.timeouts.clearInterval(id) let SIGWINCH {.importc, header: "<signal.h>", nodecl.}: cint @@ -494,7 +492,7 @@ proc handleRead(client: Client; fd: int) = let container = client.fdmap[fd] client.pager.handleEvent(container) -proc handleWrite(client: Client, fd: int) = +proc handleWrite(client: Client; fd: int) = let container = client.fdmap[fd] if container.iface.stream.flushWrite(): client.selector.unregister(fd) @@ -508,7 +506,7 @@ proc flushConsole*(client: Client) {.jsfunc.} = ) client.handleRead(client.forkserver.estream.fd) -proc handleError(client: Client, fd: int) = +proc handleError(client: Client; fd: int) = if client.pager.term.istream != nil and fd == client.pager.term.istream.fd: #TODO do something here... stderr.write("Error in tty\n") @@ -612,7 +610,7 @@ proc headlessLoop(client: Client) = client.loader.unregistered.setLen(0) client.acceptBuffers() -proc clientLoadJSModule(ctx: JSContext, module_name: cstringConst, +proc clientLoadJSModule(ctx: JSContext; module_name: cstringConst; opaque: pointer): JSModuleDef {.cdecl.} = let global = JS_GetGlobalObject(ctx) JS_FreeValue(ctx, global) @@ -634,21 +632,21 @@ proc clientLoadJSModule(ctx: JSContext, module_name: cstringConst, JS_ThrowTypeError(ctx, "Failed to open file %s", module_name) return nil -proc readBlob(client: Client, path: string): Option[WebFile] {.jsfunc.} = +proc readBlob(client: Client; path: string): Option[WebFile] {.jsfunc.} = try: return some(newWebFile(path)) except IOError: discard #TODO this is dumb -proc readFile(client: Client, path: string): string {.jsfunc.} = +proc readFile(client: Client; path: string): string {.jsfunc.} = try: return readFile(path) except IOError: discard #TODO ditto -proc writeFile(client: Client, path: string, content: string) {.jsfunc.} = +proc writeFile(client: Client; path, content: string) {.jsfunc.} = writeFile(path, content) const ConsoleTitle = "Browser Console" @@ -770,20 +768,20 @@ proc nimCollect(client: Client) {.jsfunc.} = proc jsCollect(client: Client) {.jsfunc.} = JS_RunGC(client.jsrt) -proc sleep(client: Client, millis: int) {.jsfunc.} = +proc sleep(client: Client; millis: int) {.jsfunc.} = sleep millis -proc atob(client: Client, data: string): DOMResult[NarrowString] {.jsfunc.} = +proc atob(client: Client; data: string): DOMResult[NarrowString] {.jsfunc.} = return atob(data) -proc btoa(ctx: JSContext, client: Client, data: JSValue): DOMResult[string] +proc btoa(ctx: JSContext; client: Client; data: JSValue): DOMResult[string] {.jsfunc.} = return btoa(ctx, data) func line(client: Client): LineEdit {.jsfget.} = return client.pager.lineedit.get(nil) -proc addJSModules(client: Client, ctx: JSContext) = +proc addJSModules(client: Client; ctx: JSContext) = ctx.addDOMExceptionModule() ctx.addConsoleModule() ctx.addCookieModule() diff --git a/src/local/container.nim b/src/local/container.nim index 022c40f2..e93bf610 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -203,14 +203,15 @@ proc clone*(container: Container; newurl: URL): Promise[Container] = return nc ) -func lineLoaded(container: Container, y: int): bool = +func lineLoaded(container: Container; y: int): bool = return y - container.lineshift in 0..container.lines.high -func getLine(container: Container, y: int): SimpleFlexibleLine = +func getLine(container: Container; y: int): SimpleFlexibleLine = if container.lineLoaded(y): return container.lines[y - container.lineshift] -iterator ilines*(container: Container, slice: Slice[int]): SimpleFlexibleLine {.inline.} = +iterator ilines*(container: Container; slice: Slice[int]): SimpleFlexibleLine + {.inline.} = for y in slice: yield container.getLine(y) @@ -235,7 +236,7 @@ func lastVisibleLine(container: Container): int = func currentLine(container: Container): string = return container.getLine(container.cursory).str -func findColBytes(s: string, endx: int, startx = 0, starti = 0): int = +func findColBytes(s: string; endx: int; startx = 0; starti = 0): int = var w = startx var i = starti while i < s.len and w < endx: @@ -244,10 +245,10 @@ func findColBytes(s: string, endx: int, startx = 0, starti = 0): int = w += r.twidth(w) return i -func cursorBytes(container: Container, y: int, cc = container.cursorx): int = +func cursorBytes(container: Container; y: int; cc = container.cursorx): int = return container.getLine(y).str.findColBytes(cc, 0, 0) -func currentCursorBytes(container: Container, cc = container.cursorx): int = +func currentCursorBytes(container: Container; cc = container.cursorx): int = return container.cursorBytes(container.cursory, cc) # Returns the X position of the first cell occupied by the character the cursor @@ -362,7 +363,7 @@ func endx(hl: Highlight): int = max(hl.x1, hl.x2) func endy(hl: Highlight): int = max(hl.y1, hl.y2) -func colorNormal(container: Container, hl: Highlight, y: int, +func colorNormal(container: Container; hl: Highlight; y: int; limitx: Slice[int]): Slice[int] = let starty = hl.starty let endy = hl.endy @@ -378,7 +379,7 @@ func colorNormal(container: Container, hl: Highlight, y: int, let w = container.getLine(y).str.width() return min(limitx.a, w) .. min(hl.endx, limitx.b) -func colorArea(container: Container, hl: Highlight, y: int, +func colorArea(container: Container; hl: Highlight; y: int; limitx: Slice[int]): Slice[int] = case hl.t of hltSelect: @@ -399,7 +400,7 @@ func colorArea(container: Container, hl: Highlight, y: int, else: return container.colorNormal(hl, y, limitx) -func findHighlights*(container: Container, y: int): seq[Highlight] = +func findHighlights*(container: Container; y: int): seq[Highlight] = for hl in container.highlights: if y in hl.starty .. hl.endy: result.add(hl) @@ -410,19 +411,19 @@ func getHoverText*(container: Container): string = return container.hoverText[t] "" -func isHoverURL*(container: Container, url: URL): bool = +func isHoverURL*(container: Container; url: URL): bool = let hoverurl = parseURL(container.hoverText[htLink]) return hoverurl.isSome and url.host == hoverurl.get.host -proc triggerEvent(container: Container, event: ContainerEvent) = +proc triggerEvent(container: Container; event: ContainerEvent) = container.events.addLast(event) -proc triggerEvent(container: Container, t: ContainerEventType) = +proc triggerEvent(container: Container; t: ContainerEventType) = container.triggerEvent(ContainerEvent(t: t)) proc updateCursor(container: Container) -proc setNumLines(container: Container, lines: int, finish = false) = +proc setNumLines(container: Container; lines: int; finish = false) = if container.numLines != lines: container.numLines = lines if container.startpos.isSome and finish: @@ -476,22 +477,23 @@ proc sendCursorPosition*(container: Container) = container.needslines = true ) -proc setFromY(container: Container, y: int) {.jsfunc.} = +proc setFromY(container: Container; y: int) {.jsfunc.} = if container.pos.fromy != y: container.pos.fromy = max(min(y, container.maxfromy), 0) container.needslines = true container.triggerEvent(cetUpdate) -proc setFromX(container: Container, x: int, refresh = true) {.jsfunc.} = +proc setFromX(container: Container; x: int; refresh = true) {.jsfunc.} = if container.pos.fromx != x: container.pos.fromx = max(min(x, container.maxfromx), 0) if container.pos.fromx > container.cursorx: - container.pos.cursorx = min(container.pos.fromx, container.currentLineWidth()) + container.pos.cursorx = min(container.pos.fromx, + container.currentLineWidth()) if refresh: container.sendCursorPosition() container.triggerEvent(cetUpdate) -proc setFromXY(container: Container, x, y: int) {.jsfunc.} = +proc setFromXY(container: Container; x, y: int) {.jsfunc.} = container.setFromY(y) container.setFromX(x) @@ -500,7 +502,7 @@ proc setFromXY(container: Container, x, y: int) {.jsfunc.} = # * `save = false' inhibits cursor movement if it is currently outside the # screen, and makes it so cursorx is not saved for restoration on cursory # movement. -proc setCursorX(container: Container, x: int, refresh = true, save = true) +proc setCursorX(container: Container; x: int; refresh = true; save = true) {.jsfunc.} = if not container.lineLoaded(container.cursory): container.pos.setx = x @@ -550,7 +552,7 @@ proc restoreCursorX(container: Container) {.jsfunc.} = let x = clamp(container.currentLineWidth() - 1, 0, container.xend) container.setCursorX(x, false, false) -proc setCursorY(container: Container, y: int, refresh = true) {.jsfunc.} = +proc setCursorY(container: Container; y: int; refresh = true) {.jsfunc.} = let y = max(min(y, container.numLines - 1), 0) if container.cursory == y: return if y - container.fromy >= 0 and y - container.height < container.fromy: @@ -568,7 +570,7 @@ proc setCursorY(container: Container, y: int, refresh = true) {.jsfunc.} = if refresh: container.sendCursorPosition() -proc setCursorXY*(container: Container, x, y: int, refresh = true) {.jsfunc.} = +proc setCursorXY*(container: Container; x, y: int; refresh = true) {.jsfunc.} = container.setCursorY(y, refresh) container.setCursorX(x, refresh) @@ -584,40 +586,40 @@ proc cursorLineTextStart(container: Container) {.jsfunc.} = container.setCursorX(x) # zb -proc lowerPage(container: Container, n = 0) {.jsfunc.} = +proc lowerPage(container: Container; n = 0) {.jsfunc.} = if n != 0: container.setCursorY(n - 1) container.setFromY(container.cursory - container.height + 1) # z- -proc lowerPageBegin(container: Container, n = 0) {.jsfunc.} = +proc lowerPageBegin(container: Container; n = 0) {.jsfunc.} = container.lowerPage(n) container.cursorLineTextStart() # zz -proc centerLine(container: Container, n = 0) {.jsfunc.} = +proc centerLine(container: Container; n = 0) {.jsfunc.} = if n != 0: container.setCursorY(n - 1) container.setFromY(container.cursory - container.height div 2) # z. -proc centerLineBegin(container: Container, n = 0) {.jsfunc.} = +proc centerLineBegin(container: Container; n = 0) {.jsfunc.} = container.centerLine(n) container.cursorLineTextStart() # zt -proc raisePage(container: Container, n = 0) {.jsfunc.} = +proc raisePage(container: Container; n = 0) {.jsfunc.} = if n != 0: container.setCursorY(n - 1) container.setFromY(container.cursory) # z^M -proc raisePageBegin(container: Container, n = 0) {.jsfunc.} = +proc raisePageBegin(container: Container; n = 0) {.jsfunc.} = container.raisePage(n) container.cursorLineTextStart() # z+ -proc nextPageBegin(container: Container, n = 0) {.jsfunc.} = +proc nextPageBegin(container: Container; n = 0) {.jsfunc.} = if n == 0: container.setCursorY(container.fromy + container.height) else: @@ -626,7 +628,7 @@ proc nextPageBegin(container: Container, n = 0) {.jsfunc.} = container.raisePage() # z^ -proc previousPageBegin(container: Container, n = 0) {.jsfunc.} = +proc previousPageBegin(container: Container; n = 0) {.jsfunc.} = if n == 0: container.setCursorY(container.fromy - 1) else: @@ -637,14 +639,15 @@ proc previousPageBegin(container: Container, n = 0) {.jsfunc.} = proc centerColumn(container: Container) {.jsfunc.} = container.setFromX(container.cursorx - container.width div 2) -proc setCursorYCenter(container: Container, y: int, refresh = true) +proc setCursorYCenter(container: Container; y: int; refresh = true) {.jsfunc.} = let fy = container.fromy container.setCursorY(y, refresh) if fy != container.fromy: container.centerLine() -proc setCursorXYCenter(container: Container, x, y: int, refresh = true) {.jsfunc.} = +proc setCursorXYCenter(container: Container; x, y: int; refresh = true) + {.jsfunc.} = let fy = container.fromy let fx = container.fromx container.setCursorXY(x, y, refresh) @@ -653,25 +656,25 @@ proc setCursorXYCenter(container: Container, x, y: int, refresh = true) {.jsfunc if fx != container.fromx: container.centerColumn() -proc cursorDown(container: Container, n = 1) {.jsfunc.} = +proc cursorDown(container: Container; n = 1) {.jsfunc.} = if container.select.open: container.select.cursorDown() else: container.setCursorY(container.cursory + n) -proc cursorUp(container: Container, n = 1) {.jsfunc.} = +proc cursorUp(container: Container; n = 1) {.jsfunc.} = if container.select.open: container.select.cursorUp() else: container.setCursorY(container.cursory - n) -proc cursorLeft(container: Container, n = 1) {.jsfunc.} = +proc cursorLeft(container: Container; n = 1) {.jsfunc.} = if container.select.open: container.select.cursorLeft() else: container.setCursorX(container.cursorFirstX() - n) -proc cursorRight(container: Container, n = 1) {.jsfunc.} = +proc cursorRight(container: Container; n = 1) {.jsfunc.} = if container.select.open: container.select.cursorRight() else: @@ -685,7 +688,7 @@ proc cursorLineEnd(container: Container) {.jsfunc.} = type BreakFunc = proc(r: Rune): BreakCategory {.nimcall.} -proc cursorNextWord(container: Container, breakFunc: BreakFunc) = +proc cursorNextWord(container: Container; breakFunc: BreakFunc) = if container.numLines == 0: return var r: Rune var b = container.currentCursorBytes() @@ -694,8 +697,8 @@ proc cursorNextWord(container: Container, breakFunc: BreakFunc) = let currentCat = if b < container.currentLine.len: container.currentLine.runeAt(b).breakFunc() else: - BREAK_SPACE - if currentCat != BREAK_SPACE: + bcSpace + if currentCat != bcSpace: # not in space, skip chars that have the same category while b < container.currentLine.len: let pb = b @@ -709,7 +712,7 @@ proc cursorNextWord(container: Container, breakFunc: BreakFunc) = while b < container.currentLine.len: let pb = b fastRuneAt(container.currentLine, b, r) - if r.breakFunc() != BREAK_SPACE: + if r.breakFunc() != bcSpace: b = pb break x += r.twidth(x) @@ -732,7 +735,7 @@ proc cursorNextViWord(container: Container) {.jsfunc.} = proc cursorNextBigWord(container: Container) {.jsfunc.} = container.cursorNextWord(breaksBigWordCat) -proc cursorPrevWord(container: Container, breakFunc: BreakFunc) = +proc cursorPrevWord(container: Container; breakFunc: BreakFunc) = if container.numLines == 0: return var b = container.currentCursorBytes() var x = container.cursorx @@ -741,8 +744,8 @@ proc cursorPrevWord(container: Container, breakFunc: BreakFunc) = let currentCat = if b >= 0: container.currentLine.runeAt(b).breakFunc() else: - BREAK_SPACE - if currentCat != BREAK_SPACE: + bcSpace + if currentCat != bcSpace: # not in space, skip chars that have the same category while b >= 0: let (r, o) = lastRune(container.currentLine, b) @@ -754,7 +757,7 @@ proc cursorPrevWord(container: Container, breakFunc: BreakFunc) = # skip space while b >= 0: let (r, o) = lastRune(container.currentLine, b) - if r.breakFunc() != BREAK_SPACE: + if r.breakFunc() != bcSpace: break b -= o x -= r.twidth(x) @@ -779,7 +782,7 @@ proc cursorPrevViWord(container: Container) {.jsfunc.} = proc cursorPrevBigWord(container: Container) {.jsfunc.} = container.cursorPrevWord(breaksBigWordCat) -proc cursorWordEnd(container: Container, breakFunc: BreakFunc) = +proc cursorWordEnd(container: Container; breakFunc: BreakFunc) = if container.numLines == 0: return var r: Rune var b = container.currentCursorBytes() @@ -789,7 +792,7 @@ proc cursorWordEnd(container: Container, breakFunc: BreakFunc) = if b < container.currentLine.len: let pb = b fastRuneAt(container.currentLine, b, r) - if r.breakFunc() == BREAK_SPACE: + if r.breakFunc() == bcSpace: b = pb else: px = x @@ -799,7 +802,7 @@ proc cursorWordEnd(container: Container, breakFunc: BreakFunc) = while b < container.currentLine.len: let pb = b fastRuneAt(container.currentLine, b, r) - if r.breakFunc() != BREAK_SPACE: + if r.breakFunc() != bcSpace: b = pb break x += r.twidth(x) @@ -836,7 +839,7 @@ proc cursorViWordEnd(container: Container) {.jsfunc.} = proc cursorBigWordEnd(container: Container) {.jsfunc.} = container.cursorWordEnd(breaksBigWordCat) -proc cursorWordBegin(container: Container, breakFunc: BreakFunc) = +proc cursorWordBegin(container: Container; breakFunc: BreakFunc) = if container.numLines == 0: return var b = container.currentCursorBytes() var x = container.cursorx @@ -847,7 +850,7 @@ proc cursorWordBegin(container: Container, breakFunc: BreakFunc) = if b >= 0: let (r, o) = lastRune(container.currentLine, b) # if not in space, move to the left by one - if r.breakFunc() != BREAK_SPACE: + if r.breakFunc() != bcSpace: b -= o px = x x -= r.twidth(x) @@ -855,7 +858,7 @@ proc cursorWordBegin(container: Container, breakFunc: BreakFunc) = # skip space while b >= 0: let (r, o) = lastRune(container.currentLine, b) - if r.breakFunc() != BREAK_SPACE: + if r.breakFunc() != bcSpace: break b -= o x -= r.twidth(x) @@ -895,40 +898,40 @@ proc cursorViWordBegin(container: Container) {.jsfunc.} = proc cursorBigWordBegin(container: Container) {.jsfunc.} = container.cursorWordBegin(breaksBigWordCat) -proc pageDown(container: Container, n = 1) {.jsfunc.} = +proc pageDown(container: Container; n = 1) {.jsfunc.} = container.setFromY(container.fromy + container.height * n) container.setCursorY(container.cursory + container.height * n) container.restoreCursorX() -proc pageUp(container: Container, n = 1) {.jsfunc.} = +proc pageUp(container: Container; n = 1) {.jsfunc.} = container.setFromY(container.fromy - container.height * n) container.setCursorY(container.cursory - container.height * n) container.restoreCursorX() -proc pageLeft(container: Container, n = 1) {.jsfunc.} = +proc pageLeft(container: Container; n = 1) {.jsfunc.} = container.setFromX(container.fromx - container.width * n) -proc pageRight(container: Container, n = 1) {.jsfunc.} = +proc pageRight(container: Container; n = 1) {.jsfunc.} = container.setFromX(container.fromx + container.width * n) # I am not cloning the vi behavior here because it is counter-intuitive # and annoying. # Users who disagree are free to implement it themselves. (It is about # 5 lines of JS.) -proc halfPageUp(container: Container, n = 1) {.jsfunc.} = +proc halfPageUp(container: Container; n = 1) {.jsfunc.} = container.setFromY(container.fromy - (container.height + 1) div 2 * n) container.setCursorY(container.cursory - (container.height + 1) div 2 * n) container.restoreCursorX() -proc halfPageDown(container: Container, n = 1) {.jsfunc.} = +proc halfPageDown(container: Container; n = 1) {.jsfunc.} = container.setFromY(container.fromy + (container.height + 1) div 2 * n) container.setCursorY(container.cursory + (container.height + 1) div 2 * n) container.restoreCursorX() -proc halfPageLeft(container: Container, n = 1) {.jsfunc.} = +proc halfPageLeft(container: Container; n = 1) {.jsfunc.} = container.setFromX(container.fromx - (container.width + 1) div 2 * n) -proc halfPageRight(container: Container, n = 1) {.jsfunc.} = +proc halfPageRight(container: Container; n = 1) {.jsfunc.} = container.setFromX(container.fromx + (container.width + 1) div 2 * n) proc markPos0*(container: Container) = @@ -955,7 +958,7 @@ proc cursorLastLine*(container: Container) {.jsfunc.} = container.setCursorY(container.numLines - 1) container.markPos() -proc cursorTop(container: Container, i = 1) {.jsfunc.} = +proc cursorTop(container: Container; i = 1) {.jsfunc.} = container.markPos0() let i = clamp(i - 1, 0, container.height - 1) container.setCursorY(container.fromy + i) @@ -966,7 +969,7 @@ proc cursorMiddle(container: Container) {.jsfunc.} = container.setCursorY(container.fromy + (container.height - 2) div 2) container.markPos() -proc cursorBottom(container: Container, i = 1) {.jsfunc.} = +proc cursorBottom(container: Container; i = 1) {.jsfunc.} = container.markPos0() let i = clamp(i, 0, container.height) container.setCursorY(container.fromy + container.height - i) @@ -981,7 +984,7 @@ proc cursorMiddleColumn(container: Container) {.jsfunc.} = proc cursorRightEdge(container: Container) {.jsfunc.} = container.setCursorX(container.fromx + container.width - 1) -proc scrollDown*(container: Container, n = 1) {.jsfunc.} = +proc scrollDown*(container: Container; n = 1) {.jsfunc.} = let H = container.numLines let y = min(container.fromy + container.height + n, H) - container.height if y > container.fromy: @@ -991,7 +994,7 @@ proc scrollDown*(container: Container, n = 1) {.jsfunc.} = else: container.cursorDown(n) -proc scrollUp*(container: Container, n = 1) {.jsfunc.} = +proc scrollUp*(container: Container; n = 1) {.jsfunc.} = let y = max(container.fromy - n, 0) if y < container.fromy: container.setFromY(y) @@ -1001,18 +1004,18 @@ proc scrollUp*(container: Container, n = 1) {.jsfunc.} = else: container.cursorUp(n) -proc scrollRight*(container: Container, n = 1) {.jsfunc.} = +proc scrollRight*(container: Container; n = 1) {.jsfunc.} = let msw = container.maxScreenWidth() let x = min(container.fromx + container.width + n, msw) - container.width if x > container.fromx: container.setFromX(x) -proc scrollLeft*(container: Container, n = 1) {.jsfunc.} = +proc scrollLeft*(container: Container; n = 1) {.jsfunc.} = let x = max(container.fromx - n, 0) if x < container.fromx: container.setFromX(x) -proc alert(container: Container, msg: string) = +proc alert(container: Container; msg: string) = container.triggerEvent(ContainerEvent(t: cetAlert, msg: msg)) proc lineInfo(container: Container) {.jsfunc.} = @@ -1031,7 +1034,7 @@ proc updateCursor(container: Container) = container.setCursorY(container.lastVisibleLine) container.alert("Last line is #" & $container.numLines) -proc gotoLine*[T: string|int](container: Container, s: T) = +proc gotoLine*[T: string|int](container: Container; s: T) = when s is string: if s == "": redraw(container) @@ -1058,7 +1061,7 @@ proc pushCursorPos*(container: Container) = else: container.bpos.add(container.pos) -proc popCursorPos*(container: Container, nojump = false) = +proc popCursorPos*(container: Container; nojump = false) = if container.select.open: container.select.popCursorPos(nojump) else: @@ -1072,7 +1075,7 @@ proc copyCursorPos*(container, c2: Container) = container.startpos = some(c2.pos) container.flags.incl(cfHasStart) -proc cursorNextLink*(container: Container, n = 1) {.jsfunc.} = +proc cursorNextLink*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.markPos0() @@ -1084,7 +1087,7 @@ proc cursorNextLink*(container: Container, n = 1) {.jsfunc.} = container.markPos() ) -proc cursorPrevLink*(container: Container, n = 1) {.jsfunc.} = +proc cursorPrevLink*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.markPos0() @@ -1096,7 +1099,7 @@ proc cursorPrevLink*(container: Container, n = 1) {.jsfunc.} = container.markPos() ) -proc cursorNextParagraph*(container: Container, n = 1) {.jsfunc.} = +proc cursorNextParagraph*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.markPos0() @@ -1107,7 +1110,7 @@ proc cursorNextParagraph*(container: Container, n = 1) {.jsfunc.} = container.markPos() ) -proc cursorPrevParagraph*(container: Container, n = 1) {.jsfunc.} = +proc cursorPrevParagraph*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.markPos0() @@ -1118,7 +1121,7 @@ proc cursorPrevParagraph*(container: Container, n = 1) {.jsfunc.} = container.markPos() ) -proc setMark*(container: Container, id: string, x = none(int), +proc setMark*(container: Container; id: string; x = none(int); y = none(int)): bool {.jsfunc.} = let x = x.get(container.cursorx) let y = y.get(container.cursory) @@ -1131,19 +1134,19 @@ proc setMark*(container: Container, id: string, x = none(int), container.triggerEvent(cetUpdate) return true -proc clearMark*(container: Container, id: string): bool {.jsfunc.} = +proc clearMark*(container: Container; id: string): bool {.jsfunc.} = result = id in container.marks container.marks.del(id) container.triggerEvent(cetUpdate) -proc getMarkPos(container: Container, id: string): Opt[PagePos] {.jsfunc.} = +proc getMarkPos(container: Container; id: string): Opt[PagePos] {.jsfunc.} = if id == "`" or id == "'": return ok(container.jumpMark) container.marks.withValue(id, p): return ok(p[]) return err() -proc gotoMark*(container: Container, id: string): bool {.jsfunc.} = +proc gotoMark*(container: Container; id: string): bool {.jsfunc.} = container.markPos0() let mark = container.getMarkPos(id) if mark.isSome: @@ -1153,7 +1156,7 @@ proc gotoMark*(container: Container, id: string): bool {.jsfunc.} = return true return false -proc gotoMarkY*(container: Container, id: string): bool {.jsfunc.} = +proc gotoMarkY*(container: Container; id: string): bool {.jsfunc.} = container.markPos0() let mark = container.getMarkPos(id) if mark.isSome: @@ -1163,7 +1166,7 @@ proc gotoMarkY*(container: Container, id: string): bool {.jsfunc.} = return true return false -proc findNextMark*(container: Container, x = none(int), y = none(int)): +proc findNextMark*(container: Container; x = none(int), y = none(int)): Option[string] {.jsfunc.} = #TODO optimize (maybe store marks in an OrderedTable and sort on insert?) let x = x.get(container.cursorx) @@ -1178,7 +1181,7 @@ proc findNextMark*(container: Container, x = none(int), y = none(int)): bestid = some(id) return bestid -proc findPrevMark*(container: Container, x = none(int), y = none(int)): +proc findPrevMark*(container: Container; x = none(int), y = none(int)): Option[string] {.jsfunc.} = #TODO optimize (maybe store marks in an OrderedTable and sort on insert?) let x = x.get(container.cursorx) @@ -1193,7 +1196,7 @@ proc findPrevMark*(container: Container, x = none(int), y = none(int)): bestid = some(id) return bestid -proc cursorNthLink*(container: Container, n = 1) {.jsfunc.} = +proc cursorNthLink*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.iface @@ -1202,7 +1205,7 @@ proc cursorNthLink*(container: Container, n = 1) {.jsfunc.} = if res.x > -1 and res.y != -1: container.setCursorXYCenter(res.x, res.y)) -proc cursorRevNthLink*(container: Container, n = 1) {.jsfunc.} = +proc cursorRevNthLink*(container: Container; n = 1) {.jsfunc.} = if container.iface == nil: return container.iface @@ -1216,7 +1219,7 @@ proc clearSearchHighlights*(container: Container) = if container.highlights[i].t == hltSearch: container.highlights.del(i) -proc onMatch(container: Container, res: BufferMatch, refresh: bool) = +proc onMatch(container: Container; res: BufferMatch; refresh: bool) = if res.success: container.setCursorXYCenter(res.x, res.y, refresh) if container.hlon: @@ -1239,7 +1242,7 @@ proc onMatch(container: Container, res: BufferMatch, refresh: bool) = container.needslines = true container.hlon = false -proc cursorNextMatch*(container: Container, regex: Regex, wrap, refresh: bool, +proc cursorNextMatch*(container: Container; regex: Regex; wrap, refresh: bool; n: int): EmptyPromise {.discardable.} = if container.select.open: #TODO @@ -1254,7 +1257,7 @@ proc cursorNextMatch*(container: Container, regex: Regex, wrap, refresh: bool, .then(proc(res: BufferMatch) = container.onMatch(res, refresh)) -proc cursorPrevMatch*(container: Container, regex: Regex, wrap, refresh: bool, +proc cursorPrevMatch*(container: Container; regex: Regex; wrap, refresh: bool; n: int): EmptyPromise {.discardable.} = if container.select.open: #TODO @@ -1276,7 +1279,7 @@ type SelectionOptions = object of JSDict selectionType: SelectionType -proc cursorToggleSelection(container: Container, n = 1, +proc cursorToggleSelection(container: Container; n = 1; opts = SelectionOptions()): Highlight {.jsfunc.} = if container.currentSelection != nil: let i = container.highlights.find(container.currentSelection) @@ -1302,7 +1305,7 @@ proc cursorToggleSelection(container: Container, n = 1, #TODO I don't like this API # maybe make selection a subclass of highlight? -proc getSelectionText(container: Container, hl: Highlight = nil): +proc getSelectionText(container: Container; hl: Highlight = nil): Promise[string] {.jsfunc.} = if container.iface == nil: return @@ -1354,7 +1357,7 @@ proc markURL(container: Container) {.jsfunc.} = container.needslines = true ) -proc setLoadInfo(container: Container, msg: string) = +proc setLoadInfo(container: Container; msg: string) = container.loadinfo = msg container.triggerEvent(cetSetLoadInfo) @@ -1614,8 +1617,8 @@ proc setCloneStream*(container: Container; stream: SocketStream; # Maybe we have to resume loading. Let's try. container.startLoad() -proc onreadline(container: Container, w: Slice[int], - handle: (proc(line: SimpleFlexibleLine)), res: GetLinesResult) = +proc onreadline(container: Container; w: Slice[int]; + handle: (proc(line: SimpleFlexibleLine)); res: GetLinesResult) = for line in res.lines: handle(line) if res.numLines > w.b + 1: @@ -1628,7 +1631,7 @@ proc onreadline(container: Container, w: Slice[int], container.setNumLines(res.numLines, true) # Synchronously read all lines in the buffer. -proc readLines*(container: Container, handle: proc(line: SimpleFlexibleLine)) = +proc readLines*(container: Container; handle: proc(line: SimpleFlexibleLine)) = if container.code == 0: # load succeded let w = 0 .. 23 @@ -1638,7 +1641,7 @@ proc readLines*(container: Container, handle: proc(line: SimpleFlexibleLine)) = # fulfill all promises container.handleCommand() -proc drawLines*(container: Container, display: var FixedGrid, +proc drawLines*(container: Container; display: var FixedGrid; hlcolor: CellColor) = let bgcolor = container.bgcolor template set_fmt(cell, cf: typed) = @@ -1709,7 +1712,7 @@ proc drawLines*(container: Container, display: var FixedGrid, display[dls + i - startw].format = hlformat inc by -proc highlightMarks*(container: Container, display: var FixedGrid, +proc highlightMarks*(container: Container; display: var FixedGrid; hlcolor: CellColor) = for mark in container.marks.values: if mark.x in container.fromx ..< container.fromx + display.width and diff --git a/src/local/lineedit.nim b/src/local/lineedit.nim index 42543d46..2db59e7b 100644 --- a/src/local/lineedit.nim +++ b/src/local/lineedit.nim @@ -120,7 +120,7 @@ proc generateOutput*(edit: LineEdit): FixedGrid = proc getCursorX*(edit: LineEdit): int = return edit.promptw + edit.cursorx + edit.padding - edit.shiftx -proc insertCharseq(edit: LineEdit, s: string) = +proc insertCharseq(edit: LineEdit; s: string) = let s = if edit.escNext: s else: @@ -152,7 +152,7 @@ proc backspace(edit: LineEdit) {.jsfunc.} = edit.cursorx -= r.width() edit.invalid = true -proc write*(edit: LineEdit, s: string, cs: Charset): bool = +proc write*(edit: LineEdit; s: string; cs: Charset): bool = if cs == CHARSET_UTF_8: if s.validateUTF8Surr() != -1: return false @@ -166,7 +166,7 @@ proc write*(edit: LineEdit, s: string, cs: Charset): bool = edit.insertCharseq(s) return true -proc write(edit: LineEdit, s: string): bool {.jsfunc.} = +proc write(edit: LineEdit; s: string): bool {.jsfunc.} = edit.write(s, CHARSET_UTF_8) proc delete(edit: LineEdit) {.jsfunc.} = @@ -304,11 +304,11 @@ proc nextHist(edit: LineEdit) {.jsfunc.} = edit.end() edit.histtmp = "" -proc windowChange*(edit: LineEdit, attrs: WindowAttributes) = +proc windowChange*(edit: LineEdit; attrs: WindowAttributes) = edit.maxwidth = attrs.width - edit.promptw - 1 -proc readLine*(prompt: string, termwidth: int, current = "", - disallowed: set[char] = {}, hide = false, hist: LineHistory): LineEdit = +proc readLine*(prompt, current: string; termwidth: int; + disallowed: set[char]; hide: bool; hist: LineHistory): LineEdit = result = LineEdit( prompt: prompt, promptw: prompt.width(), diff --git a/src/local/pager.nim b/src/local/pager.nim index 624a4867..99a1ba1c 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -168,13 +168,13 @@ iterator containers*(pager: Pager): Container {.inline.} = for c in root.descendants: yield c -proc setContainer*(pager: Pager, c: Container) {.jsfunc.} = +proc setContainer*(pager: Pager; c: Container) {.jsfunc.} = pager.container = c pager.redraw = true if c != nil: pager.term.setTitle(c.getTitle()) -proc hasprop(ctx: JSContext, pager: Pager, s: string): bool {.jshasprop.} = +proc hasprop(ctx: JSContext; pager: Pager; s: string): bool {.jshasprop.} = if pager.container != nil: let cval = toJS(ctx, pager.container) let val = JS_GetPropertyStr(ctx, cval, s) @@ -182,12 +182,12 @@ proc hasprop(ctx: JSContext, pager: Pager, s: string): bool {.jshasprop.} = result = true JS_FreeValue(ctx, val) -proc reflect(ctx: JSContext, this_val: JSValue, argc: cint, argv: ptr JSValue, - magic: cint, func_data: ptr JSValue): JSValue {.cdecl.} = +proc reflect(ctx: JSContext; this_val: JSValue; argc: cint; argv: ptr JSValue; + magic: cint; func_data: ptr JSValue): JSValue {.cdecl.} = let fun = cast[ptr JSValue](cast[int](func_data) + sizeof(JSValue))[] return JS_Call(ctx, fun, func_data[], argc, argv) -proc getter(ctx: JSContext, pager: Pager, s: string): Option[JSValue] +proc getter(ctx: JSContext; pager: Pager; s: string): Option[JSValue] {.jsgetprop.} = if pager.container != nil: let cval = toJS(ctx, pager.container) @@ -199,7 +199,7 @@ proc getter(ctx: JSContext, pager: Pager, s: string): Option[JSValue] return some(fun) return some(val) -proc searchNext(pager: Pager, n = 1) {.jsfunc.} = +proc searchNext(pager: Pager; n = 1) {.jsfunc.} = if pager.regex.isSome: let wrap = pager.config.search.wrap pager.container.markPos0() @@ -211,7 +211,7 @@ proc searchNext(pager: Pager, n = 1) {.jsfunc.} = else: pager.alert("No previous regular expression") -proc searchPrev(pager: Pager, n = 1) {.jsfunc.} = +proc searchPrev(pager: Pager; n = 1) {.jsfunc.} = if pager.regex.isSome: let wrap = pager.config.search.wrap pager.container.markPos0() @@ -233,7 +233,7 @@ proc setLineEdit(pager: Pager; mode: LineMode; current = ""; hide = false; let hist = pager.getLineHist(mode) if pager.term.isatty() and pager.config.input.use_mouse: pager.term.disableMouse() - let edit = readLine($mode & extraPrompt, pager.attrs.width, current, {}, hide, + let edit = readLine($mode & extraPrompt, current, pager.attrs.width, {}, hide, hist) pager.lineedit = some(edit) pager.linemode = mode @@ -261,7 +261,7 @@ proc isearchBackward(pager: Pager) {.jsfunc.} = pager.container.markPos0() pager.setLineEdit(lmISearchB) -proc gotoLine[T: string|int](pager: Pager, s: T = "") {.jsfunc.} = +proc gotoLine[T: string|int](pager: Pager; s: T = "") {.jsfunc.} = when s is string: if s == "": pager.setLineEdit(lmGotoLine) @@ -272,7 +272,7 @@ proc dumpAlerts*(pager: Pager) = for msg in pager.alerts: stderr.write("cha: " & msg & '\n') -proc quit*(pager: Pager, code = 0) = +proc quit*(pager: Pager; code = 0) = pager.term.quit() pager.dumpAlerts() @@ -292,14 +292,14 @@ proc genClientKey(pager: Pager): ClientKey = doAssert n == key.len return key -proc addLoaderClient*(pager: Pager, pid: int, config: LoaderClientConfig): +proc addLoaderClient*(pager: Pager; pid: int; config: LoaderClientConfig): ClientKey = var key = pager.genClientKey() while unlikely(not pager.loader.addClient(key, pid, config)): key = pager.genClientKey() return key -proc setLoader*(pager: Pager, loader: FileLoader) = +proc setLoader*(pager: Pager; loader: FileLoader) = pager.devRandom = newPosixStream("/dev/urandom", O_RDONLY, 0) pager.loader = loader let config = LoaderClientConfig( @@ -323,7 +323,7 @@ proc clearDisplay(pager: Pager) = proc buffer(pager: Pager): Container {.jsfget, inline.} = pager.container -proc refreshDisplay(pager: Pager, container = pager.container) = +proc refreshDisplay(pager: Pager; container = pager.container) = pager.clearDisplay() let hlcolor = cellColor(pager.config.display.highlight_color) container.drawLines(pager.display, hlcolor) @@ -331,8 +331,8 @@ proc refreshDisplay(pager: Pager, container = pager.container) = container.highlightMarks(pager.display, hlcolor) # Note: this function does not work correctly if start < i of last written char -proc writeStatusMessage(pager: Pager, str: string, format = Format(), - start = 0, maxwidth = -1, clip = '$'): int {.discardable.} = +proc writeStatusMessage(pager: Pager; str: string; format = Format(); + start = 0; maxwidth = -1; clip = '$'): int {.discardable.} = var maxwidth = maxwidth if maxwidth == -1: maxwidth = pager.statusgrid.len @@ -401,7 +401,7 @@ proc showAlerts*(pager: Pager) = pager.inputBuffer == "" and pager.precnum == 0: pager.refreshStatusMsg() -proc drawBuffer*(pager: Pager, container: Container, ostream: Stream) = +proc drawBuffer*(pager: Pager; container: Container; ostream: Stream) = var format = Format() container.readLines(proc(line: SimpleFlexibleLine) = if line.formats.len == 0: @@ -452,7 +452,8 @@ proc draw*(pager: Pager) = if pager.askpromise != nil: pager.term.setCursor(pager.askcursor, pager.attrs.height - 1) elif pager.lineedit.isSome: - pager.term.setCursor(pager.lineedit.get.getCursorX(), pager.attrs.height - 1) + pager.term.setCursor(pager.lineedit.get.getCursorX(), + pager.attrs.height - 1) elif container != nil: if container.select.open: pager.term.setCursor(container.select.getCursorX(), @@ -463,35 +464,35 @@ proc draw*(pager: Pager) = pager.term.flush() pager.redraw = false -proc writeAskPrompt(pager: Pager, s = "") = +proc writeAskPrompt(pager: Pager; s = "") = let maxwidth = pager.statusgrid.width - s.len let i = pager.writeStatusMessage(pager.askprompt, maxwidth = maxwidth) pager.askcursor = pager.writeStatusMessage(s, start = i) pager.term.writeGrid(pager.statusgrid, 0, pager.attrs.height - 1) -proc ask(pager: Pager, prompt: string): Promise[bool] {.jsfunc.} = +proc ask(pager: Pager; prompt: string): Promise[bool] {.jsfunc.} = pager.askprompt = prompt pager.writeAskPrompt(" (y/n)") pager.askpromise = Promise[bool]() return pager.askpromise -proc askChar(pager: Pager, prompt: string): Promise[string] {.jsfunc.} = +proc askChar(pager: Pager; prompt: string): Promise[string] {.jsfunc.} = pager.askprompt = prompt pager.writeAskPrompt() pager.askcharpromise = Promise[string]() return pager.askcharpromise -proc fulfillAsk*(pager: Pager, y: bool) = +proc fulfillAsk*(pager: Pager; y: bool) = pager.askpromise.resolve(y) pager.askpromise = nil pager.askprompt = "" -proc fulfillCharAsk*(pager: Pager, s: string) = +proc fulfillCharAsk*(pager: Pager; s: string) = pager.askcharpromise.resolve(s) pager.askcharpromise = nil pager.askprompt = "" -proc addContainer*(pager: Pager, container: Container) = +proc addContainer*(pager: Pager; container: Container) = container.parent = pager.container if pager.container != nil: pager.container.children.insert(container, 0) @@ -569,7 +570,7 @@ func findProcMapItem*(pager: Pager; pid: int): int = return i -1 -proc dupeBuffer(pager: Pager, container: Container, url: URL) = +proc dupeBuffer(pager: Pager; container: Container; url: URL) = container.clone(url).then(proc(container: Container) = if container == nil: pager.alert("Failed to duplicate buffer.") @@ -653,7 +654,7 @@ proc nextSiblingBuffer(pager: Pager): bool {.jsfunc.} = pager.setContainer(pager.container.parent.children[n + 1]) return true -proc alert*(pager: Pager, msg: string) {.jsfunc.} = +proc alert*(pager: Pager; msg: string) {.jsfunc.} = pager.alerts.add(msg) # replace target with container in the tree @@ -721,14 +722,14 @@ proc deleteContainer(pager: Pager; container: Container) = pager.forkserver.removeChild(container.process) pager.loader.removeClient(container.process) -proc discardBuffer*(pager: Pager, container = none(Container)) {.jsfunc.} = +proc discardBuffer*(pager: Pager; container = none(Container)) {.jsfunc.} = let c = container.get(pager.container) if c == nil or c.parent == nil and c.children.len == 0: pager.alert("Cannot discard last buffer!") else: pager.deleteContainer(c) -proc discardTree(pager: Pager, container = none(Container)) {.jsfunc.} = +proc discardTree(pager: Pager; container = none(Container)) {.jsfunc.} = let container = container.get(pager.container) if container != nil: for c in container.descendants: @@ -754,7 +755,7 @@ proc runProcess(cmd: string): bool = result = WIFSIGNALED(wstatus) and WTERMSIG(wstatus) == SIGINT # Run process (and suspend the terminal controller). -proc runProcess(term: Terminal, cmd: string, wait = false): bool = +proc runProcess(term: Terminal; cmd: string; wait = false): bool = term.quit() result = runProcess(cmd) if wait: @@ -762,7 +763,7 @@ proc runProcess(term: Terminal, cmd: string, wait = false): bool = term.restart() # Run process, and capture its output. -proc runProcessCapture(cmd: string, outs: var string): bool = +proc runProcessCapture(cmd: string; outs: var string): bool = let file = popen(cmd, "r") if file == nil: return false @@ -972,7 +973,7 @@ proc gotoURL(pager: Pager; request: Request; prevurl = none(URL); else: pager.container.findAnchor(request.url.anchor) -proc omniRewrite(pager: Pager, s: string): string = +proc omniRewrite(pager: Pager; s: string): string = for rule in pager.config.omnirule: if rule.match.match(s): let fun = rule.substitute_url.get @@ -991,7 +992,7 @@ proc omniRewrite(pager: Pager, s: string): string = # * file://$PWD/<file> # * https://<url> # So we attempt to load both, and see what works. -proc loadURL*(pager: Pager, url: string, ctype = none(string), +proc loadURL*(pager: Pager; url: string; ctype = none(string); cs = CHARSET_UNKNOWN) = let url0 = pager.omniRewrite(url) let url = if url[0] == '~': expandPath(url0) else: url0 @@ -1009,7 +1010,8 @@ proc loadURL*(pager: Pager, url: string, ctype = none(string), let pageurl = parseURL(pager.config.network.prepend_scheme & url) if pageurl.isSome: # attempt to load remote page urls.add(pageurl.get) - let cdir = parseURL("file://" & percentEncode(getCurrentDir(), LocalPathPercentEncodeSet) & DirSep) + let cdir = parseURL("file://" & percentEncode(getCurrentDir(), + LocalPathPercentEncodeSet) & DirSep) let localurl = percentEncode(url, LocalPathPercentEncodeSet) let newurl = parseURL(localurl, cdir) if newurl.isSome: @@ -1039,7 +1041,7 @@ proc readPipe0*(pager: Pager; contentType: string; cs: Charset; contentType = some(contentType) ) -proc readPipe*(pager: Pager, contentType: string, cs: Charset, fd: FileHandle, +proc readPipe*(pager: Pager; contentType: string; cs: Charset; fd: FileHandle; title: string) = let url = newURL("stream:-").get let container = pager.readPipe0(contentType, cs, fd, url, title, @@ -1050,24 +1052,24 @@ proc readPipe*(pager: Pager, contentType: string, cs: Charset, fd: FileHandle, proc command(pager: Pager) {.jsfunc.} = pager.setLineEdit(lmCommand) -proc commandMode(pager: Pager, val: bool) {.jsfset.} = +proc commandMode(pager: Pager; val: bool) {.jsfset.} = pager.commandMode = val if val: pager.command() -proc checkRegex(pager: Pager, regex: Result[Regex, string]): Opt[Regex] = +proc checkRegex(pager: Pager; regex: Result[Regex, string]): Opt[Regex] = if regex.isErr: pager.alert("Invalid regex: " & regex.error) return err() return ok(regex.get) -proc compileSearchRegex(pager: Pager, s: string): Result[Regex, string] = +proc compileSearchRegex(pager: Pager; s: string): Result[Regex, string] = var flags = {LRE_FLAG_UNICODE} if pager.config.search.ignore_case: flags.incl(LRE_FLAG_IGNORECASE) return compileSearchRegex(s, flags) -proc updateReadLineISearch(pager: Pager, linemode: LineMode) = +proc updateReadLineISearch(pager: Pager; linemode: LineMode) = let lineedit = pager.lineedit.get pager.isearchpromise = pager.isearchpromise.then(proc(): EmptyPromise = case lineedit.state @@ -1183,11 +1185,11 @@ proc updateReadLine*(pager: Pager) = pager.clearLineEdit() # Same as load(s + '\n') -proc loadSubmit(pager: Pager, s: string) {.jsfunc.} = +proc loadSubmit(pager: Pager; s: string) {.jsfunc.} = pager.loadURL(s) # Open a URL prompt and visit the specified URL. -proc load(pager: Pager, s = "") {.jsfunc.} = +proc load(pager: Pager; s = "") {.jsfunc.} = if s.len > 0 and s[^1] == '\n': if s.len > 1: pager.loadURL(s[0..^2]) @@ -1197,7 +1199,7 @@ proc load(pager: Pager, s = "") {.jsfunc.} = pager.setLineEdit(lmLocation, s) # Go to specific URL (for JS) -proc jsGotoURL(pager: Pager, s: string): JSResult[void] {.jsfunc: "gotoURL".} = +proc jsGotoURL(pager: Pager; s: string): JSResult[void] {.jsfunc: "gotoURL".} = pager.gotoURL(newRequest(?newURL(s))) ok() @@ -1228,14 +1230,14 @@ proc extern(pager: Pager; cmd: string; t = ExternDict()): bool {.jsfunc.} = else: return runProcess(cmd) -proc externCapture(pager: Pager, cmd: string): Opt[string] {.jsfunc.} = +proc externCapture(pager: Pager; cmd: string): Opt[string] {.jsfunc.} = pager.setEnvVars() var s: string if not runProcessCapture(cmd, s): return err() return ok(s) -proc externInto(pager: Pager, cmd, ins: string): bool {.jsfunc.} = +proc externInto(pager: Pager; cmd, ins: string): bool {.jsfunc.} = pager.setEnvVars() return runProcessInto(cmd, ins) @@ -1784,13 +1786,13 @@ proc handleEvent0(pager: Pager; container: Container; event: ContainerEvent): item.stream.sclose() return true -proc handleEvents*(pager: Pager, container: Container) = +proc handleEvents*(pager: Pager; container: Container) = while container.events.len > 0: let event = container.events.popFirst() if not pager.handleEvent0(container, event): break -proc handleEvent*(pager: Pager, container: Container) = +proc handleEvent*(pager: Pager; container: Container) = try: container.handleEvent() pager.handleEvents(container) diff --git a/src/local/select.nim b/src/local/select.nim index a02aa1a4..cbefea5a 100644 --- a/src/local/select.nim +++ b/src/local/select.nim @@ -33,7 +33,7 @@ type submitFun: SubmitSelect bpos: seq[int] -proc windowChange*(select: var Select, height: int) = +proc windowChange*(select: var Select; height: int) = select.maxh = height - 2 if select.y + select.options.len >= select.maxh: select.y = height - select.options.len @@ -48,8 +48,8 @@ proc windowChange*(select: var Select, height: int) = select.si = max(i - select.maxh, 0) select.redraw = true -proc initSelect*(select: var Select, selectResult: SelectResult, - x, y, height: int, submitFun: SubmitSelect) = +proc initSelect*(select: var Select; selectResult: SelectResult; + x, y, height: int; submitFun: SubmitSelect) = select.open = true select.multiple = selectResult.multiple select.options = selectResult.options @@ -70,7 +70,7 @@ func hover(select: Select): int = func dispheight(select: Select): int = return select.maxh - select.y -proc `hover=`(select: var Select, i: int) = +proc `hover=`(select: var Select; i: int) = let i = clamp(i, 0, select.options.high) if i >= select.si + select.dispheight: select.si = i - select.dispheight + 1 @@ -156,7 +156,7 @@ proc cursorLastLine*(select: var Select) = select.si = max(select.options.len - select.maxh, 0) select.redraw = true -proc cursorNextMatch*(select: var Select, regex: Regex, wrap: bool) = +proc cursorNextMatch*(select: var Select; regex: Regex; wrap: bool) = var j = -1 for i in select.hover + 1 ..< select.options.len: if regex.exec(select.options[i]).success: @@ -174,7 +174,7 @@ proc cursorNextMatch*(select: var Select, regex: Regex, wrap: bool) = select.hover = j select.redraw = true -proc cursorPrevMatch*(select: var Select, regex: Regex, wrap: bool) = +proc cursorPrevMatch*(select: var Select; regex: Regex; wrap: bool) = var j = -1 for i in countdown(select.hover - 1, 0): if regex.exec(select.options[i]).success: @@ -195,7 +195,7 @@ proc cursorPrevMatch*(select: var Select, regex: Regex, wrap: bool) = proc pushCursorPos*(select: var Select) = select.bpos.add(select.hover) -proc popCursorPos*(select: var Select, nojump = false) = +proc popCursorPos*(select: var Select; nojump = false) = select.hover = select.bpos.pop() if not nojump: select.redraw = true @@ -207,7 +207,7 @@ const CornerTopRight = $Rune(0x2510) const CornerBottomLeft = $Rune(0x2514) const CornerBottomRight = $Rune(0x2518) -proc drawBorders(display: var FixedGrid, sx, ex, sy, ey: int, +proc drawBorders(display: var FixedGrid; sx, ex, sy, ey: int; upmore, downmore: bool) = for y in sy .. ey: var x = 0 @@ -251,7 +251,7 @@ proc drawBorders(display: var FixedGrid, sx, ex, sy, ey: int, display[y * display.width + sx].format = fmt display[y * display.width + ex].format = fmt -proc drawSelect*(select: Select, display: var FixedGrid) = +proc drawSelect*(select: Select; display: var FixedGrid) = if display.width < 2 or display.height < 2: return # border does not fit... # Max width, height with one row/column on the sides. diff --git a/src/local/term.nim b/src/local/term.nim index cda376aa..eee53039 100644 --- a/src/local/term.nim +++ b/src/local/term.nim @@ -96,7 +96,7 @@ const GEOMCELL = CSI(18, "t") const XTSHIFTESCAPE = CSI(">0s") # device control string -template DCS(a, b: char, s: varargs[string]): string = +template DCS(a, b: char; s: varargs[string]): string = "\eP" & a & b & s.join(';') & "\e\\" template XTGETTCAP(s: varargs[string, `$`]): string = @@ -138,21 +138,21 @@ when not termcap_found: template ED(): string = CSI() & "J" - proc write(term: Terminal, s: string) = + proc write(term: Terminal; s: string) = term.outfile.write(s) else: - func hascap(term: Terminal, c: TermcapCap): bool = term.tc.caps[c] != nil - func cap(term: Terminal, c: TermcapCap): string = $term.tc.caps[c] - func ccap(term: Terminal, c: TermcapCap): cstring = term.tc.caps[c] + func hascap(term: Terminal; c: TermcapCap): bool = term.tc.caps[c] != nil + func cap(term: Terminal; c: TermcapCap): string = $term.tc.caps[c] + func ccap(term: Terminal; c: TermcapCap): cstring = term.tc.caps[c] var goutfile: File proc putc(c: char): cint {.cdecl.} = goutfile.write(c) - proc write(term: Terminal, s: cstring) = + proc write(term: Terminal; s: cstring) = discard tputs(s, 1, putc) - proc write(term: Terminal, s: string) = + proc write(term: Terminal; s: string) = term.write(cstring(s)) proc readChar*(term: Terminal): char = @@ -188,7 +188,7 @@ const ANSIColorMap = [ proc flush*(term: Terminal) = term.outfile.flushFile() -proc cursorGoto(term: Terminal, x, y: int): string = +proc cursorGoto(term: Terminal; x, y: int): string = when termcap_found: return $tgoto(term.ccap cm, cint(x), cint(y)) else: @@ -225,7 +225,7 @@ proc resetFormat(term: Terminal): string = return term.cap me return SGR() -proc startFormat(term: Terminal, flag: FormatFlags): string = +proc startFormat(term: Terminal; flag: FormatFlags): string = when termcap_found: if term.isatty(): case flag @@ -237,7 +237,7 @@ proc startFormat(term: Terminal, flag: FormatFlags): string = else: discard return SGR(FormatCodes[flag].s) -proc endFormat(term: Terminal, flag: FormatFlags): string = +proc endFormat(term: Terminal; flag: FormatFlags): string = when termcap_found: if term.isatty(): case flag @@ -246,7 +246,7 @@ proc endFormat(term: Terminal, flag: FormatFlags): string = else: discard return SGR(FormatCodes[flag].e) -proc setCursor*(term: Terminal, x, y: int) = +proc setCursor*(term: Terminal; x, y: int) = term.write(term.cursorGoto(x, y)) proc enableAltScreen(term: Terminal): string = @@ -264,7 +264,7 @@ proc disableAltScreen(term: Terminal): string = func mincontrast(term: Terminal): int32 = return term.config.display.minimum_contrast -proc getRGB(a: CellColor, termDefault: RGBColor): RGBColor = +proc getRGB(a: CellColor; termDefault: RGBColor): RGBColor = case a.t of ctNone: return termDefault @@ -299,7 +299,7 @@ proc approximateANSIColor(rgb, termDefault: RGBColor): CellColor = return if n == -1: defaultColor else: ANSIColor(n).cellColor() # Return a fgcolor contrasted to the background by term.mincontrast. -proc correctContrast(term: Terminal, bgcolor, fgcolor: CellColor): CellColor = +proc correctContrast(term: Terminal; bgcolor, fgcolor: CellColor): CellColor = let contrast = term.mincontrast let cfgcolor = fgcolor let bgcolor = getRGB(bgcolor, term.defaultBackground) @@ -344,10 +344,10 @@ template eightBitSGR(n: uint8, bgmod: int): string = else: SGR(38 + bgmod, 5, n) -template rgbSGR(rgb: RGBColor, bgmod: int): string = +template rgbSGR(rgb: RGBColor; bgmod: int): string = SGR(38 + bgmod, 2, rgb.r, rgb.g, rgb.b) -proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = +proc processFormat*(term: Terminal; format: var Format; cellf: Format): string = for flag in FormatFlags: if flag in term.formatmode: if flag in format.flags and flag notin cellf.flags: @@ -418,7 +418,7 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = discard # nothing to do format = cellf -proc setTitle*(term: Terminal, title: string) = +proc setTitle*(term: Terminal; title: string) = if term.set_title: term.outfile.write(XTSETTITLE(title.replaceControls())) @@ -428,7 +428,7 @@ proc enableMouse*(term: Terminal) = proc disableMouse*(term: Terminal) = term.write(SGRMOUSEBTNOFF) -proc processOutputString*(term: Terminal, str: string, w: var int): string = +proc processOutputString*(term: Terminal; str: string; w: var int): string = if str.validateUTF8Surr() != -1: return "?" # twidth wouldn't work here, the view may start at the nth character. @@ -446,7 +446,7 @@ proc processOutputString*(term: Terminal, str: string, w: var int): string = var success = false return newTextEncoder(term.cs).encodeAll(str, success) -proc generateFullOutput(term: Terminal, grid: FixedGrid): string = +proc generateFullOutput(term: Terminal; grid: FixedGrid): string = var format = Format() result &= term.cursorGoto(0, 0) result &= term.resetFormat() @@ -463,7 +463,7 @@ proc generateFullOutput(term: Terminal, grid: FixedGrid): string = result &= term.processFormat(format, cell.format) result &= term.processOutputString(cell.str, w) -proc generateSwapOutput(term: Terminal, grid, prev: FixedGrid): string = +proc generateSwapOutput(term: Terminal; grid, prev: FixedGrid): string = var vy = -1 for y in 0 ..< grid.height: var w = 0 @@ -518,7 +518,7 @@ func emulateOverline(term: Terminal): bool = term.config.display.emulate_overline and ffOverline notin term.formatmode and ffUnderline in term.formatmode -proc writeGrid*(term: Terminal, grid: FixedGrid, x = 0, y = 0) = +proc writeGrid*(term: Terminal; grid: FixedGrid; x = 0, y = 0) = for ly in y ..< y + grid.height: for lx in x ..< x + grid.width: let i = ly * term.canvas.width + lx @@ -660,7 +660,8 @@ when termcap_found: for id in TermcapCapNumeric: tc.numCaps[id] = tgetnum(cstring($id)) else: - raise newException(Defect, "Failed to load termcap description for terminal " & term.tname) + raise newException(Defect, + "Failed to load termcap description for terminal " & term.tname) type QueryAttrs = enum @@ -676,7 +677,7 @@ type width: int height: int -proc queryAttrs(term: Terminal, windowOnly: bool): QueryResult = +proc queryAttrs(term: Terminal; windowOnly: bool): QueryResult = const tcapRGB = 0x524742 # RGB supported? if not windowOnly: const outs = @@ -698,13 +699,13 @@ proc queryAttrs(term: Terminal, windowOnly: bool): QueryResult = while true: template consume(term: Terminal): char = term.readChar() template fail = return - template expect(term: Terminal, c: char) = + template expect(term: Terminal; c: char) = if term.consume != c: fail - template expect(term: Terminal, s: string) = + template expect(term: Terminal; s: string) = for c in s: term.expect c - template skip_until(term: Terminal, c: char) = + template skip_until(term: Terminal; c: char) = while (let cc = term.consume; cc != c): discard term.expect '\e' @@ -813,7 +814,7 @@ type TermStartResult* = enum tsrSuccess, tsrDA1Fail # when windowOnly, only refresh window size. -proc detectTermAttributes(term: Terminal, windowOnly: bool): TermStartResult = +proc detectTermAttributes(term: Terminal; windowOnly: bool): TermStartResult = result = tsrSuccess term.tname = getEnv("TERM") if term.tname == "": @@ -994,7 +995,7 @@ proc restart*(term: Terminal) = if term.set_title: term.write(XTPUSHTITLE) -proc newTerminal*(outfile: File, config: Config): Terminal = +proc newTerminal*(outfile: File; config: Config): Terminal = return Terminal( outfile: outfile, config: config, diff --git a/src/server/buffer.nim b/src/server/buffer.nim index a3e4afe2..3d5b706f 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -142,14 +142,14 @@ type charsets*: seq[Charset] charsetOverride*: Charset -proc getFromOpaque[T](opaque: pointer, res: var T) = +proc getFromOpaque[T](opaque: pointer; res: var T) = let opaque = cast[InterfaceOpaque](opaque) if opaque.len != 0: var r = opaque.stream.initReader(opaque.len) r.sread(res) opaque.len = 0 -proc newBufferInterface*(stream: SocketStream, registerFun: proc(fd: int)): +proc newBufferInterface*(stream: SocketStream; registerFun: proc(fd: int)): BufferInterface = let opaque = InterfaceOpaque(stream: stream) result = BufferInterface( @@ -161,7 +161,7 @@ proc newBufferInterface*(stream: SocketStream, registerFun: proc(fd: int)): # After cloning a buffer, we need a new interface to the new buffer process. # Here we create a new interface for that clone. -proc cloneInterface*(stream: SocketStream, registerFun: proc(fd: int)): +proc cloneInterface*(stream: SocketStream; registerFun: proc(fd: int)): BufferInterface = let iface = newBufferInterface(stream, registerFun) #TODO buffered data should probably be copied here @@ -174,7 +174,7 @@ proc cloneInterface*(stream: SocketStream, registerFun: proc(fd: int)): r.sread(pid) return iface -proc resolve*(iface: BufferInterface, packetid, len: int) = +proc resolve*(iface: BufferInterface; packetid, len: int) = iface.opaque.len = len iface.map.resolve(packetid) # Protection against accidentally not exhausting data available to read, @@ -191,7 +191,8 @@ func getFunId(fun: NimNode): string = let name = fun[0] # sym return "bc" & name.strVal[0].toUpperAscii() & name.strVal.substr(1) -proc buildInterfaceProc(fun: NimNode, funid: string): tuple[fun, name: NimNode] = +proc buildInterfaceProc(fun: NimNode; funid: string): + tuple[fun, name: NimNode] = let name = fun[0] # sym let params = fun[3] # formalparams let retval = params[0] # sym @@ -296,7 +297,7 @@ macro task(fun: typed) = func getTitleAttr(node: StyledNode): string = if node == nil: return "" - if node.t == STYLED_ELEMENT and node.node != nil: + if node.t == stElement and node.node != nil: let element = Element(node.node) if element.attrb(satTitle): return element.attr(satTitle) @@ -313,9 +314,9 @@ const ClickableElements = { } func isClickable(styledNode: StyledNode): bool = - if styledNode.t != STYLED_ELEMENT or styledNode.node == nil: + if styledNode.t != stElement or styledNode.node == nil: return false - if styledNode.computed{"visibility"} != VISIBILITY_VISIBLE: + if styledNode.computed{"visibility"} != VisibilityVisible: return false let element = Element(styledNode.node) if element of HTMLAnchorElement: @@ -329,7 +330,7 @@ func getClickable(styledNode: StyledNode): Element = return Element(styledNode.node) styledNode = styledNode.parent -proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] +proc submitForm(form: HTMLFormElement; submitter: Element): Option[Request] func canSubmitOnClick(fae: FormAssociatedElement): bool = if fae.form == nil: @@ -363,7 +364,7 @@ proc getClickHover(styledNode: StyledNode): string = proc getImageHover(styledNode: StyledNode): string = var styledNode = styledNode while styledNode != nil: - if styledNode.t == STYLED_ELEMENT: + if styledNode.t == stElement: if styledNode.node of HTMLImageElement: let image = HTMLImageElement(styledNode.node) let src = image.attr(satSrc) @@ -388,26 +389,26 @@ proc getImageHover(styledNode: StyledNode): string = styledNode = styledNode.parent "" -func getCursorStyledNode(buffer: Buffer, cursorx, cursory: int): StyledNode = +func getCursorStyledNode(buffer: Buffer; cursorx, cursory: int): StyledNode = let i = buffer.lines[cursory].findFormatN(cursorx) - 1 if i >= 0: return buffer.lines[cursory].formats[i].node nil -func getCursorElement(buffer: Buffer, cursorx, cursory: int): Element = +func getCursorElement(buffer: Buffer; cursorx, cursory: int): Element = let styledNode = buffer.getCursorStyledNode(cursorx, cursory) if styledNode == nil or styledNode.node == nil: return nil - if styledNode.t == STYLED_ELEMENT: + if styledNode.t == stElement: return Element(styledNode.node) return styledNode.node.parentElement -func getCursorClickable(buffer: Buffer, cursorx, cursory: int): Element = +func getCursorClickable(buffer: Buffer; cursorx, cursory: int): Element = let styledNode = buffer.getCursorStyledNode(cursorx, cursory) if styledNode != nil: return styledNode.getClickable() -func cursorBytes(buffer: Buffer, y: int, cc: int): int = +func cursorBytes(buffer: Buffer; y, cc: int): int = let line = buffer.lines[y].str var w = 0 var i = 0 @@ -417,11 +418,11 @@ func cursorBytes(buffer: Buffer, y: int, cc: int): int = w += r.twidth(w) return i -proc navigate(buffer: Buffer, url: URL) = +proc navigate(buffer: Buffer; url: URL) = #TODO how? stderr.write("navigate to " & $url & "\n") -proc findPrevLink*(buffer: Buffer, cursorx, cursory, n: int): +proc findPrevLink*(buffer: Buffer; cursorx, cursory, n: int): tuple[x, y: int] {.proxy.} = if cursory >= buffer.lines.len: return (-1, -1) var found = 0 @@ -468,7 +469,7 @@ proc findPrevLink*(buffer: Buffer, cursorx, cursory, n: int): # an efficient and correct way to do this. break - template found_pos(x, y: int, fl: Element) = + template found_pos(x, y: int; fl: Element) = inc found link = fl if found == n: @@ -495,7 +496,7 @@ proc findPrevLink*(buffer: Buffer, cursorx, cursory, n: int): dec i return (-1, -1) -proc findNextLink*(buffer: Buffer, cursorx, cursory, n: int): +proc findNextLink*(buffer: Buffer; cursorx, cursory, n: int): tuple[x, y: int] {.proxy.} = if cursory >= buffer.lines.len: return (-1, -1) let line = buffer.lines[cursory] @@ -506,7 +507,7 @@ proc findNextLink*(buffer: Buffer, cursorx, cursory, n: int): inc i var found = 0 - template found_pos(x, y: int, fl: Element) = + template found_pos(x, y: int; fl: Element) = inc found link = fl if found == n: @@ -519,7 +520,7 @@ proc findNextLink*(buffer: Buffer, cursorx, cursory, n: int): found_pos format.pos, cursory, fl inc i - for y in (cursory + 1)..(buffer.lines.len - 1): + for y in cursory + 1 .. buffer.lines.len - 1: let line = buffer.lines[y] for i in 0 ..< line.formats.len: let format = line.formats[i] @@ -528,7 +529,7 @@ proc findNextLink*(buffer: Buffer, cursorx, cursory, n: int): found_pos format.pos, y, fl return (-1, -1) -proc findPrevParagraph*(buffer: Buffer, cursory, n: int): int {.proxy.} = +proc findPrevParagraph*(buffer: Buffer; cursory, n: int): int {.proxy.} = var y = cursory for i in 0 ..< n: while y >= 0 and buffer.lines[y].str.onlyWhitespace(): @@ -537,7 +538,7 @@ proc findPrevParagraph*(buffer: Buffer, cursory, n: int): int {.proxy.} = dec y return y -proc findNextParagraph*(buffer: Buffer, cursory, n: int): int {.proxy.} = +proc findNextParagraph*(buffer: Buffer; cursory, n: int): int {.proxy.} = var y = cursory for i in 0 ..< n: while y < buffer.lines.len and buffer.lines[y].str.onlyWhitespace(): @@ -546,7 +547,7 @@ proc findNextParagraph*(buffer: Buffer, cursory, n: int): int {.proxy.} = inc y return y -proc findNthLink*(buffer: Buffer, i: int): tuple[x, y: int] {.proxy.} = +proc findNthLink*(buffer: Buffer; i: int): tuple[x, y: int] {.proxy.} = if i == 0: return (-1, -1) var k = 0 @@ -563,7 +564,7 @@ proc findNthLink*(buffer: Buffer, i: int): tuple[x, y: int] {.proxy.} = link = fl return (-1, -1) -proc findRevNthLink*(buffer: Buffer, i: int): tuple[x, y: int] {.proxy.} = +proc findRevNthLink*(buffer: Buffer; i: int): tuple[x, y: int] {.proxy.} = if i == 0: return (-1, -1) var k = 0 @@ -580,7 +581,7 @@ proc findRevNthLink*(buffer: Buffer, i: int): tuple[x, y: int] {.proxy.} = link = fl return (-1, -1) -proc findPrevMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, +proc findPrevMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; wrap: bool, n: int): BufferMatch {.proxy.} = if cursory >= buffer.lines.len: return var y = cursory @@ -613,8 +614,8 @@ proc findPrevMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, break dec y -proc findNextMatch*(buffer: Buffer, regex: Regex, cursorx, cursory: int, - wrap: bool, n: int): BufferMatch {.proxy.} = +proc findNextMatch*(buffer: Buffer; regex: Regex; cursorx, cursory: int; + wrap: bool; n: int): BufferMatch {.proxy.} = if cursory >= buffer.lines.len: return var y = cursory let b = buffer.cursorBytes(y, cursorx + 1) @@ -674,7 +675,7 @@ proc do_reshape(buffer: Buffer) = buffer.lines.renderDocument(buffer.bgcolor, styledRoot, addr buffer.attrs) buffer.prevStyled = styledRoot -proc processData0(buffer: Buffer, data: openArray[char]): bool = +proc processData0(buffer: Buffer; data: openArray[char]): bool = if buffer.ishtml: if buffer.htmlParser.parseBuffer(data) == PRES_STOP: buffer.charsetStack = @[buffer.htmlParser.builder.charset] @@ -715,7 +716,7 @@ proc switchCharset(buffer: Buffer) = const BufferSize = 16384 -proc decodeData(buffer: Buffer, iq: openArray[uint8]): bool = +proc decodeData(buffer: Buffer; iq: openArray[uint8]): bool = var oq {.noinit.}: array[BufferSize, char] var n = 0 while true: @@ -738,7 +739,7 @@ proc decodeData(buffer: Buffer, iq: openArray[uint8]): bool = doAssert buffer.processData0("\uFFFD") true -proc validateData(buffer: Buffer, iq: openArray[char]): bool = +proc validateData(buffer: Buffer; iq: openArray[char]): bool = var pi = 0 var n = 0 while true: @@ -765,7 +766,7 @@ proc validateData(buffer: Buffer, iq: openArray[char]): bool = pi = buffer.validator.i true -proc bomSniff(buffer: Buffer, iq: openArray[char]): int = +proc bomSniff(buffer: Buffer; iq: openArray[char]): int = if iq[0] == '\xFE' and iq[1] == '\xFF': buffer.charsetStack = @[CHARSET_UTF_16_BE] buffer.switchCharset() @@ -780,7 +781,7 @@ proc bomSniff(buffer: Buffer, iq: openArray[char]): int = return 3 return 0 -proc processData(buffer: Buffer, iq: openArray[char]): bool = +proc processData(buffer: Buffer; iq: openArray[char]): bool = var start = 0 if buffer.needsBOMSniff: if iq.len >= 3: # ehm... TODO @@ -790,7 +791,7 @@ proc processData(buffer: Buffer, iq: openArray[char]): bool = return buffer.decodeData(iq.toOpenArrayByte(start, iq.high)) return buffer.validateData(iq.toOpenArray(start, iq.high)) -proc windowChange*(buffer: Buffer, attrs: WindowAttributes) {.proxy.} = +proc windowChange*(buffer: Buffer; attrs: WindowAttributes) {.proxy.} = buffer.attrs = attrs buffer.prevStyled = nil if buffer.window != nil: @@ -806,7 +807,7 @@ const HoverFun = [ htLink: getClickHover, htImage: getImageHover ] -proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult +proc updateHover*(buffer: Buffer; cursorx, cursory: int): UpdateHoverResult {.proxy.} = if cursory >= buffer.lines.len: return UpdateHoverResult() @@ -820,7 +821,7 @@ proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult if thisnode != prevnode and (thisnode == nil or prevnode == nil or thisnode.node != prevnode.node): for styledNode in thisnode.branch: - if styledNode.t == STYLED_ELEMENT and styledNode.node != nil: + if styledNode.t == stElement and styledNode.node != nil: let elem = Element(styledNode.node) if not elem.hover: elem.hover = true @@ -831,7 +832,7 @@ proc updateHover*(buffer: Buffer, cursorx, cursory: int): UpdateHoverResult hover.add((ht, s)) buffer.hoverText[ht] = s for styledNode in prevnode.branch: - if styledNode.t == STYLED_ELEMENT and styledNode.node != nil: + if styledNode.t == stElement and styledNode.node != nil: let elem = Element(styledNode.node) if elem.hover: elem.hover = false @@ -910,7 +911,7 @@ when defined(freebsd) or defined(openbsd): # Create an exact clone of the current buffer. # This clone will share the loader process with the previous buffer. -proc clone*(buffer: Buffer, newurl: URL): int {.proxy.} = +proc clone*(buffer: Buffer; newurl: URL): int {.proxy.} = var pipefd: array[2, cint] if pipe(pipefd) == -1: buffer.estream.write("Failed to open pipe.\n") @@ -1019,7 +1020,7 @@ proc dispatchDOMContentLoadedEvent(buffer: Buffer) = ctx.writeException(buffer.estream) JS_FreeValue(ctx, e) called = true - if FLAG_STOP_IMMEDIATE_PROPAGATION in event.flags: + if efStopImmediatePropagation in event.flags: break if called: buffer.do_reshape() @@ -1041,7 +1042,7 @@ proc dispatchLoadEvent(buffer: Buffer) = ctx.writeException(buffer.estream) JS_FreeValue(ctx, e) called = true - if FLAG_STOP_IMMEDIATE_PROPAGATION in event.flags: + if efStopImmediatePropagation in event.flags: break if called: buffer.do_reshape() @@ -1069,12 +1070,12 @@ proc dispatchEvent(buffer: Buffer; ctype, jsName: string; elem: Element): if JS_IsException(e): ctx.writeException(buffer.estream) JS_FreeValue(ctx, e) - if FLAG_STOP_IMMEDIATE_PROPAGATION in event.flags: + if efStopImmediatePropagation in event.flags: stop = true break - if FLAG_STOP_PROPAGATION in event.flags: + if efStopPropagation in event.flags: stop = true - if FLAG_CANCELED in event.flags: + if efCanceled in event.flags: canceled = true if stop: break @@ -1258,7 +1259,7 @@ func pickCharset(form: HTMLFormElement): Charset = return form.document.charset.getOutputEncoding() # https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm -proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] = +proc submitForm(form: HTMLFormElement; submitter: Element): Option[Request] = if form.constructingEntryList: return none(Request) #TODO submit() @@ -1281,13 +1282,13 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] = let scheme = parsedaction.scheme let enctype = submitter.enctype() let formmethod = submitter.formmethod() - if formmethod == FORM_METHOD_DIALOG: + if formmethod == fmDialog: #TODO return none(Request) - let httpmethod = if formmethod == FORM_METHOD_GET: + let httpmethod = if formmethod == fmGet: HTTP_GET else: - assert formmethod == FORM_METHOD_POST + assert formmethod == fmPost HTTP_POST #let target = if submitter.isSubmitButton() and submitter.attrb("formtarget"): @@ -1308,16 +1309,16 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] = var body: Option[string] var multipart: Option[FormData] case enctype - of FORM_ENCODING_TYPE_URLENCODED: + of fetUrlencoded: #TODO with charset let kvlist = entrylist.toNameValuePairs() body = some(serializeApplicationXWWWFormUrlEncoded(kvlist)) mimeType = $enctype - of FORM_ENCODING_TYPE_MULTIPART: + of fetMultipart: #TODO with charset multipart = some(serializeMultipartFormData(entrylist)) mimetype = $enctype - of FORM_ENCODING_TYPE_TEXT_PLAIN: + of fetTextPlain: #TODO with charset let kvlist = entrylist.toNameValuePairs() body = some(serializePlainTextFormData(kvlist)) @@ -1339,7 +1340,7 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] = template mailAsBody() = let kvlist = entrylist.toNameValuePairs() - let body = if enctype == FORM_ENCODING_TYPE_TEXT_PLAIN: + let body = if enctype == fetTextPlain: let text = serializePlainTextFormData(kvlist) percentEncode(text, PathPercentEncodeSet) else: @@ -1356,27 +1357,27 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] = of "ftp", "javascript": getActionUrl of "data": - if formmethod == FORM_METHOD_GET: + if formmethod == fmGet: mutateActionUrl else: - assert formmethod == FORM_METHOD_POST + assert formmethod == fmPost getActionUrl of "mailto": - if formmethod == FORM_METHOD_GET: + if formmethod == fmGet: mailWithHeaders else: - assert formmethod == FORM_METHOD_POST + assert formmethod == fmPost mailAsBody else: # Note: only http & https are defined by the standard. # Assume an HTTP-like protocol. - if formmethod == FORM_METHOD_GET: + if formmethod == fmGet: mutateActionUrl else: - assert formmethod == FORM_METHOD_POST + assert formmethod == fmPost submitAsEntityBody -proc setFocus(buffer: Buffer, e: Element): bool = +proc setFocus(buffer: Buffer; e: Element): bool = if buffer.document.focus != e: buffer.document.focus = e buffer.do_reshape() @@ -1405,7 +1406,7 @@ proc implicitSubmit(input: HTMLInputElement): Option[Request] = else: return submitForm(form, form) -proc readSuccess*(buffer: Buffer, s: string): ReadSuccessResult {.proxy.} = +proc readSuccess*(buffer: Buffer; s: string): ReadSuccessResult {.proxy.} = if buffer.document.focus != nil: case buffer.document.focus.tagType of TAG_INPUT: @@ -1455,14 +1456,14 @@ type repaint*: bool select*: Option[SelectResult] -proc click(buffer: Buffer, clickable: Element): ClickResult +proc click(buffer: Buffer; clickable: Element): ClickResult -proc click(buffer: Buffer, label: HTMLLabelElement): ClickResult = +proc click(buffer: Buffer; label: HTMLLabelElement): ClickResult = let control = label.control if control != nil: return buffer.click(control) -proc click(buffer: Buffer, select: HTMLSelectElement): ClickResult = +proc click(buffer: Buffer; select: HTMLSelectElement): ClickResult = let repaint = buffer.setFocus(select) var options: seq[string] var selected: seq[int] @@ -1485,7 +1486,7 @@ proc click(buffer: Buffer, select: HTMLSelectElement): ClickResult = func baseURL(buffer: Buffer): URL = return buffer.document.baseURL -proc evalJSURL(buffer: Buffer, url: URL): Opt[string] = +proc evalJSURL(buffer: Buffer; url: URL): Opt[string] = let encodedScriptSource = ($url)["javascript:".len..^1] let scriptSource = percentDecode(encodedScriptSource) let ctx = buffer.window.jsctx @@ -1500,7 +1501,7 @@ proc evalJSURL(buffer: Buffer, url: URL): Opt[string] = # Navigate to result. return ok(s) -proc click(buffer: Buffer, anchor: HTMLAnchorElement): ClickResult = +proc click(buffer: Buffer; anchor: HTMLAnchorElement): ClickResult = var repaint = buffer.restoreFocus() let url = parseURL(anchor.href, some(buffer.baseURL)) if url.isSome: @@ -1528,12 +1529,12 @@ proc click(buffer: Buffer, anchor: HTMLAnchorElement): ClickResult = repaint: repaint ) -proc click(buffer: Buffer, option: HTMLOptionElement): ClickResult = +proc click(buffer: Buffer; option: HTMLOptionElement): ClickResult = let select = option.select if select != nil: return buffer.click(select) -proc click(buffer: Buffer, button: HTMLButtonElement): ClickResult = +proc click(buffer: Buffer; button: HTMLButtonElement): ClickResult = if button.form != nil: case button.ctype of BUTTON_SUBMIT: result.open = submitForm(button.form, button) @@ -1544,7 +1545,7 @@ proc click(buffer: Buffer, button: HTMLButtonElement): ClickResult = of BUTTON_BUTTON: discard result.repaint = buffer.setFocus(button) -proc click(buffer: Buffer, textarea: HTMLTextAreaElement): ClickResult = +proc click(buffer: Buffer; textarea: HTMLTextAreaElement): ClickResult = let repaint = buffer.setFocus(textarea) let readline = ReadLineResult( value: textarea.value, @@ -1580,7 +1581,7 @@ const InputTypePrompt = [ itWeek: "Week" ] -proc click(buffer: Buffer, input: HTMLInputElement): ClickResult = +proc click(buffer: Buffer; input: HTMLInputElement): ClickResult = let repaint = buffer.restoreFocus() case input.inputType of itFile: @@ -1843,7 +1844,7 @@ proc readCommand(buffer: Buffer) = r.sread(packetid) bufferDispatcher(ProxyFunctions, buffer, cmd, packetid, r) -proc handleRead(buffer: Buffer, fd: int): bool = +proc handleRead(buffer: Buffer; fd: int): bool = if fd == buffer.rfd: try: buffer.readCommand() @@ -1868,7 +1869,7 @@ proc handleRead(buffer: Buffer, fd: int): bool = else: assert false true -proc handleError(buffer: Buffer, fd: int, err: OSErrorCode): bool = +proc handleError(buffer: Buffer; fd: int; err: OSErrorCode): bool = if fd == buffer.rfd: # Connection reset by peer, probably. Close the buffer. return false diff --git a/src/server/forkserver.nim b/src/server/forkserver.nim index a5a9ff64..e3f210f8 100644 --- a/src/server/forkserver.nim +++ b/src/server/forkserver.nim @@ -48,12 +48,12 @@ proc forkLoader*(forkserver: ForkServer; config: LoaderConfig): int = r.sread(process) return process -proc loadForkServerConfig*(forkserver: ForkServer, config: Config) = +proc loadForkServerConfig*(forkserver: ForkServer; config: Config) = forkserver.ostream.withPacketWriter w: w.swrite(fcLoadConfig) w.swrite(config.getForkServerConfig()) -proc removeChild*(forkserver: ForkServer, pid: int) = +proc removeChild*(forkserver: ForkServer; pid: int) = forkserver.ostream.withPacketWriter w: w.swrite(fcRemoveChild) w.swrite(pid) @@ -81,7 +81,7 @@ proc trapSIGINT() = # all child processes as well). setControlCHook(proc() {.noconv.} = discard) -proc forkLoader(ctx: var ForkServerContext, config: LoaderConfig): int = +proc forkLoader(ctx: var ForkServerContext; config: LoaderConfig): int = var pipefd: array[2, cint] if pipe(pipefd) == -1: raise newException(Defect, "Failed to open pipe.") diff --git a/src/types/blob.nim b/src/types/blob.nim index 5b1efa65..c3d9a071 100644 --- a/src/types/blob.nim +++ b/src/types/blob.nim @@ -26,7 +26,7 @@ type jsDestructor(Blob) jsDestructor(WebFile) -proc newBlob*(buffer: pointer, size: int, ctype: string, +proc newBlob*(buffer: pointer; size: int; ctype: string; deallocFun: DeallocFun): Blob = return Blob( buffer: buffer, @@ -45,7 +45,7 @@ proc finalize(file: WebFile) {.jsfin.} = file.deallocFun() file.buffer = nil -proc newWebFile*(path: string, webkitRelativePath = ""): WebFile = +proc newWebFile*(path: string; webkitRelativePath = ""): WebFile = var file: File if not open(file, path, fmRead): raise newException(IOError, "Failed to open file") @@ -65,7 +65,7 @@ type FilePropertyBag = object of BlobPropertyBag #TODO lastModified: int64 -proc newWebFile(ctx: JSContext, fileBits: seq[string], fileName: string, +proc newWebFile(ctx: JSContext; fileBits: seq[string]; fileName: string; options = FilePropertyBag()): WebFile {.jsctor.} = let file = WebFile( isfile: false, diff --git a/src/types/cell.nim b/src/types/cell.nim index cca9618b..8820f351 100644 --- a/src/types/cell.nim +++ b/src/types/cell.nim @@ -34,17 +34,22 @@ type width*, height*: int cells*: seq[FixedCell] -proc `[]=`*(grid: var FixedGrid, i: int, cell: FixedCell) = grid.cells[i] = cell -proc `[]=`*(grid: var FixedGrid, i: BackwardsIndex, cell: FixedCell) = grid.cells[i] = cell -proc `[]`*(grid: var FixedGrid, i: int): var FixedCell = grid.cells[i] -proc `[]`*(grid: var FixedGrid, i: BackwardsIndex): var FixedCell = grid.cells[i] -proc `[]`*(grid: FixedGrid, i: int): FixedCell = grid.cells[i] -proc `[]`*(grid: FixedGrid, i: BackwardsIndex): FixedCell = grid.cells[i] -iterator items*(grid: FixedGrid): FixedCell {.inline.} = - for cell in grid.cells: yield cell +proc `[]=`*(grid: var FixedGrid; i: int; cell: FixedCell) = grid.cells[i] = cell +proc `[]=`*(grid: var FixedGrid; i: BackwardsIndex; cell: FixedCell) = + grid.cells[i] = cell +proc `[]`*(grid: var FixedGrid; i: int): var FixedCell = grid.cells[i] +proc `[]`*(grid: var FixedGrid; i: BackwardsIndex): var FixedCell = + grid.cells[i] +proc `[]`*(grid: FixedGrid; i: int): FixedCell = grid.cells[i] +proc `[]`*(grid: FixedGrid; i: BackwardsIndex): FixedCell = grid.cells[i] + proc len*(grid: FixedGrid): int = grid.cells.len proc high*(grid: FixedGrid): int = grid.cells.high +iterator items*(grid: FixedGrid): FixedCell {.inline.} = + for cell in grid.cells: + yield cell + const FormatCodes*: array[FormatFlags, tuple[s, e: uint8]] = [ ffBold: (1u8, 22u8), ffItalic: (3u8, 23u8), @@ -55,14 +60,14 @@ const FormatCodes*: array[FormatFlags, tuple[s, e: uint8]] = [ ffBlink: (5u8, 25u8), ] -func newFixedGrid*(w: int, h: int = 1): FixedGrid = +func newFixedGrid*(w: int; h: int = 1): FixedGrid = return FixedGrid(width: w, height: h, cells: newSeq[FixedCell](w * h)) func width*(cell: FixedCell): int = return cell.str.width() # Get the first format cell after pos, if any. -func findFormatN*(line: SimpleFlexibleLine, pos: int): int = +func findFormatN*(line: SimpleFlexibleLine; pos: int): int = var i = 0 while i < line.formats.len: if line.formats[i].pos > pos: @@ -70,14 +75,14 @@ func findFormatN*(line: SimpleFlexibleLine, pos: int): int = inc i return i -func findFormat*(line: SimpleFlexibleLine, pos: int): SimpleFormatCell = +func findFormat*(line: SimpleFlexibleLine; pos: int): SimpleFormatCell = let i = line.findFormatN(pos) - 1 if i != -1: result = line.formats[i] else: result.pos = -1 -func findNextFormat*(line: SimpleFlexibleLine, pos: int): SimpleFormatCell = +func findNextFormat*(line: SimpleFlexibleLine; pos: int): SimpleFormatCell = let i = line.findFormatN(pos) if i < line.formats.len: result = line.formats[i] diff --git a/src/types/color.nim b/src/types/color.nim index 6d46031d..9f1f6298 100644 --- a/src/types/color.nim +++ b/src/types/color.nim @@ -302,7 +302,7 @@ func fastmul1(c, ca: uint32): uint32 = ga = ga and 0xFF00FF00u32 return ga or (rb shr 8) -func fastmul1(c: RGBAColor, ca: uint32): RGBAColor = +func fastmul1(c: RGBAColor; ca: uint32): RGBAColor = return RGBAColor(fastmul1(uint32(c), ca)) func rgba*(r, g, b, a: uint8): RGBAColor @@ -510,14 +510,14 @@ func parseLegacyColor*(s: string): JSResult[RGBColor] = return err(newTypeError("Color must not be transparent")) return ok(parseLegacyColor0(s)) -proc toJS*(ctx: JSContext, rgb: RGBColor): JSValue = +proc toJS*(ctx: JSContext; rgb: RGBColor): JSValue = var res = "#" res.pushHex(rgb.r) res.pushHex(rgb.g) res.pushHex(rgb.b) return toJS(ctx, res) -proc fromJSRGBColor*(ctx: JSContext, val: JSValue): JSResult[RGBColor] = +proc fromJSRGBColor*(ctx: JSContext; val: JSValue): JSResult[RGBColor] = return parseLegacyColor(?fromJS[string](ctx, val)) proc toJS*(ctx: JSContext; rgba: RGBAColor): JSValue = diff --git a/src/types/cookie.nim b/src/types/cookie.nim index 82c9d780..6918648f 100644 --- a/src/types/cookie.nim +++ b/src/types/cookie.nim @@ -103,14 +103,16 @@ proc parseCookieDate(val: string): Option[DateTime] = year = n foundYear = true continue - if not (foundDayOfMonth and foundMonth and foundYear and foundTime): return none(DateTime) + if not (foundDayOfMonth and foundMonth and foundYear and foundTime): + return none(DateTime) if dayOfMonth notin 0..31: return none(DateTime) if year < 1601: return none(DateTime) if time[0] > 23: return none(DateTime) if time[1] > 59: return none(DateTime) if time[2] > 59: return none(DateTime) - var dateTime = dateTime(year, Month(month), MonthdayRange(dayOfMonth), HourRange(time[0]), MinuteRange(time[1]), SecondRange(time[2])) - return some(dateTime) + let dt = dateTime(year, Month(month), MonthdayRange(dayOfMonth), + HourRange(time[0]), MinuteRange(time[1]), SecondRange(time[2])) + return some(dt) # For debugging proc `$`*(cookiejar: CookieJar): string = @@ -152,7 +154,7 @@ func cookiePathMatches(cookiePath, requestPath: string): bool = # * The last character of the string that is not included in the # domain string is a %x2E (".") character. (???) # * The string is a host name (i.e., not an IP address).) -func cookieDomainMatches(cookieDomain: string, url: URL): bool = +func cookieDomainMatches(cookieDomain: string; url: URL): bool = let host = url.host if host == cookieDomain: return true @@ -164,7 +166,7 @@ func cookieDomainMatches(cookieDomain: string, url: URL): bool = cookieDomain return host.endsWith(cookieDomain) -proc add*(cookieJar: CookieJar, cookie: Cookie) = +proc add*(cookieJar: CookieJar; cookie: Cookie) = var i = -1 for j in 0 ..< cookieJar.cookies.len: let old = cookieJar.cookies[j] @@ -178,12 +180,12 @@ proc add*(cookieJar: CookieJar, cookie: Cookie) = cookieJar.cookies.del(i) cookieJar.cookies.add(cookie) -proc add*(cookiejar: CookieJar, cookies: seq[Cookie]) = +proc add*(cookiejar: CookieJar; cookies: seq[Cookie]) = for cookie in cookies: cookiejar.add(cookie) # https://www.rfc-editor.org/rfc/rfc6265#section-5.4 -proc serialize*(cookiejar: CookieJar, url: URL): string = +proc serialize*(cookiejar: CookieJar; url: URL): string = if not cookiejar.filter.match(url): return "" # fail let t = now().toTime().toUnix() @@ -205,7 +207,7 @@ proc serialize*(cookiejar: CookieJar, url: URL): string = result &= "=" result &= cookie.value -proc newCookie*(str: string, url: URL = nil): JSResult[Cookie] +proc newCookie*(str: string; url: URL = nil): JSResult[Cookie] {.jsctor.} = let cookie = Cookie( expires: -1, @@ -262,7 +264,7 @@ proc newCookie*(str: string, url: URL = nil): JSResult[Cookie] cookie.path = defaultCookiePath(url) return ok(cookie) -proc newCookieJar*(location: URL, allowhosts: seq[Regex]): CookieJar = +proc newCookieJar*(location: URL; allowhosts: seq[Regex]): CookieJar = return CookieJar( filter: newURLFilter( scheme = some(location.scheme), diff --git a/src/types/matrix.nim b/src/types/matrix.nim index 17ff3c0d..99deb4f2 100644 --- a/src/types/matrix.nim +++ b/src/types/matrix.nim @@ -3,7 +3,7 @@ type Matrix* = object w: int h: int -proc newMatrix*(me: seq[float64], w: int, h: int): Matrix = +proc newMatrix*(me: seq[float64]; w, h: int): Matrix = return Matrix( me: me, w: w, @@ -28,7 +28,7 @@ proc newMatrixUninitialized*(w, h: int): Matrix = ) #TODO this is extremely inefficient -proc `*`*(a: Matrix, b: Matrix): Matrix = +proc `*`*(a, b: Matrix): Matrix = assert a.w == b.h let h = a.h let w = b.w @@ -42,5 +42,5 @@ proc `*`*(a: Matrix, b: Matrix): Matrix = c.me[y * c.w + x] = val return c -proc `*=`*(a: var Matrix, b: Matrix) = +proc `*=`*(a: var Matrix; b: Matrix) = a = a * b diff --git a/src/types/referrer.nim b/src/types/referrer.nim index 8d1d9b87..ec9acc76 100644 --- a/src/types/referrer.nim +++ b/src/types/referrer.nim @@ -33,7 +33,7 @@ proc getReferrerPolicy*(s: string): Option[ReferrerPolicy] = of "unsafe-url": return some(UNSAFE_URL) -proc getReferrer*(prev, target: URL, policy: ReferrerPolicy): string = +proc getReferrer*(prev, target: URL; policy: ReferrerPolicy): string = let origin = prev.origin0 if origin.isNone: return "" diff --git a/src/types/urimethodmap.nim b/src/types/urimethodmap.nim index 41e887c6..eed8b112 100644 --- a/src/types/urimethodmap.nim +++ b/src/types/urimethodmap.nim @@ -33,7 +33,7 @@ func rewriteURL(pattern, surl: string): string = type URIMethodMapResult* = enum URI_RESULT_NOT_FOUND, URI_RESULT_SUCCESS, URI_RESULT_WRONG_URL -proc findAndRewrite*(this: URIMethodMap, url: var URL): URIMethodMapResult = +proc findAndRewrite*(this: URIMethodMap; url: var URL): URIMethodMapResult = let protocol = url.protocol if protocol in this.map: let surl = this.map[protocol].rewriteURL($url) @@ -44,7 +44,7 @@ proc findAndRewrite*(this: URIMethodMap, url: var URL): URIMethodMapResult = return URI_RESULT_SUCCESS return URI_RESULT_NOT_FOUND -proc parseURIMethodMap*(this: var URIMethodMap, s: string) = +proc parseURIMethodMap*(this: var URIMethodMap; s: string) = for line in s.split('\n'): if line.len == 0 or line[0] == '#': continue # comments @@ -74,6 +74,6 @@ proc parseURIMethodMap*(s: string): URIMethodMap = result = URIMethodMap() result.parseURIMethodMap(s) -proc append*(this: var URIMethodMap, that: URIMethodMap) = +proc append*(this: var URIMethodMap; that: URIMethodMap) = for k, v in that.map: discard this.map.hasKeyOrPut(k, v) diff --git a/src/types/url.nim b/src/types/url.nim index db0946e3..b72fb8af 100644 --- a/src/types/url.nim +++ b/src/types/url.nim @@ -419,7 +419,7 @@ proc shortenPath(url: URL) {.inline.} = if url.path.ss.len > 0: discard url.path.ss.pop() -proc append(path: var URLPath, s: string) = +proc append(path: var URLPath; s: string) = if path.opaque: path.s &= s else: @@ -1013,7 +1013,7 @@ proc serializeApplicationXWWWFormUrlEncoded*(kvs: seq[(string, string)]; result &= '=' result.percentEncode(value, ApplicationXWWWFormUrlEncodedSet, spaceAsPlus) -proc initURLSearchParams(params: URLSearchParams, init: string) = +proc initURLSearchParams(params: URLSearchParams; init: string) = params.list = parseApplicationXWWWFormUrlEncoded(init) proc newURLSearchParams[ diff --git a/src/utils/luwrap.nim b/src/utils/luwrap.nim index 41a58701..330a5d1e 100644 --- a/src/utils/luwrap.nim +++ b/src/utils/luwrap.nim @@ -4,23 +4,23 @@ import std/unicode import bindings/libunicode import utils/charcategory -proc passRealloc(opaque: pointer, p: pointer, size: csize_t): pointer - {.cdecl.} = +proc passRealloc(opaque, p: pointer; size: csize_t): pointer {.cdecl.} = return realloc(p, size) -proc mnormalize*(rs: var seq[Rune], form = UNICODE_NFC) = {.cast(noSideEffect).}: - if rs.len == 0: return - var outbuf: ptr uint32 - let p = cast[ptr uint32](unsafeAddr rs[0]) - let out_len = unicode_normalize(addr outbuf, p, cint(rs.len), form, nil, - passRealloc) - if out_len < 0: - raise newException(Defect, "Unicode normalization failed") - if out_len == 0: - return - rs = cast[seq[Rune]](newSeqUninitialized[uint32](out_len)) - copyMem(addr rs[0], outbuf, out_len * sizeof(uint32)) - dealloc(outbuf) +proc mnormalize*(rs: var seq[Rune]; form = UNICODE_NFC) = + {.cast(noSideEffect).}: + if rs.len == 0: return + var outbuf: ptr uint32 + let p = cast[ptr uint32](unsafeAddr rs[0]) + let out_len = unicode_normalize(addr outbuf, p, cint(rs.len), form, nil, + passRealloc) + if out_len < 0: + raise newException(Defect, "Unicode normalization failed") + if out_len == 0: + return + rs = cast[seq[Rune]](newSeqUninitialized[uint32](out_len)) + copyMem(addr rs[0], outbuf, out_len * sizeof(uint32)) + dealloc(outbuf) #TODO maybe a utf8 normalization procedure? proc mnormalize*(s: var string) = @@ -30,7 +30,7 @@ proc mnormalize*(s: var string) = rs.mnormalize() s = $rs -func normalize*(rs: seq[Rune], form = UNICODE_NFC): seq[Rune] = +func normalize*(rs: seq[Rune]; form = UNICODE_NFC): seq[Rune] = {.cast(noSideEffect).}: if rs.len == 0: return var outbuf: ptr uint32 diff --git a/src/utils/proptable.nim b/src/utils/proptable.nim index 0087dd80..02a342f5 100644 --- a/src/utils/proptable.nim +++ b/src/utils/proptable.nim @@ -8,7 +8,7 @@ type PropertyTable* = array[0x10000 div (sizeof(ptint) * 8), ptint] RangeMap* = openArray[(uint32, uint32)] -func makePropertyTable*(ranges: RangeMap, skip: RangeMap = @[]): PropertyTable = +func makePropertyTable*(ranges: RangeMap; skip: RangeMap = @[]): PropertyTable = var ucs: uint32 = 0 var j = 0 var k = 0 @@ -30,7 +30,7 @@ func makePropertyTable*(ranges: RangeMap, skip: RangeMap = @[]): PropertyTable = inc ucs {.push boundChecks:off.} -func contains*(props: PropertyTable, u: ptint): bool {.inline.} = +func contains*(props: PropertyTable; u: ptint): bool {.inline.} = const isz = sizeof(ptint) * 8 let i = u div isz let m = u mod isz diff --git a/src/utils/strwidth.nim b/src/utils/strwidth.nim index 9cb115cc..5bfea156 100644 --- a/src/utils/strwidth.nim +++ b/src/utils/strwidth.nim @@ -35,7 +35,7 @@ func width*(r: Rune): int = # Width, but also works with tabs. # Needs the column width of the text so far. -func twidth*(r: Rune, w: int): int = +func twidth*(r: Rune; w: int): int = if r != Rune('\t'): return r.width() return ((w div 8) + 1) * 8 - w @@ -44,7 +44,7 @@ func width*(s: string): int = for r in s.runes(): result += r.twidth(result) -func width*(s: string, start, len: int): int = +func width*(s: string; start, len: int): int = var i = start var m = len if m > s.len: m = s.len @@ -57,13 +57,13 @@ func notwidth*(s: string): int = for r in s.runes: result += r.width() -func twidth*(s: string, w: int): int = +func twidth*(s: string; w: int): int = var i = w for r in s.runes(): i += r.twidth(w) return i - w -func padToWidth*(str: string, size: int, schar = '$'): string = +func padToWidth*(str: string; size: int; schar = '$'): string = if str.width() < size: return str & ' '.repeat(size - str.width()) else: @@ -83,24 +83,24 @@ func isDigitAscii(r: Rune): bool = return uint32(r) < 128 and char(r) in AsciiDigit type BreakCategory* = enum - BREAK_ALPHA, BREAK_SPACE, BREAK_SYMBOL + bcAlpha, bcSpace, bcSymbol func breaksWord*(r: Rune): bool = return not (r.isDigitAscii() or r.width() == 0 or r.isAlpha()) func breaksViWordCat*(r: Rune): BreakCategory = if r.isWhiteSpace(): - return BREAK_SPACE + return bcSpace elif r.breaksWord(): - return BREAK_SYMBOL - return BREAK_ALPHA + return bcSymbol + return bcAlpha func breaksWordCat*(r: Rune): BreakCategory = if not r.breaksWord(): - return BREAK_ALPHA - return BREAK_SPACE + return bcAlpha + return bcSpace func breaksBigWordCat*(r: Rune): BreakCategory = if not r.isWhiteSpace(): - return BREAK_ALPHA - return BREAK_SPACE + return bcAlpha + return bcSpace diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim index 91f7a4ab..31ceeec2 100644 --- a/src/utils/twtstr.nim +++ b/src/utils/twtstr.nim @@ -86,11 +86,11 @@ func decValue*(c: char): int = const HexCharsUpper = "0123456789ABCDEF" const HexCharsLower = "0123456789abcdef" -func pushHex*(buf: var string, u: uint8) = +func pushHex*(buf: var string; u: uint8) = buf &= HexCharsUpper[u shr 4] buf &= HexCharsUpper[u and 0xF] -func pushHex*(buf: var string, c: char) = +func pushHex*(buf: var string; c: char) = buf.pushHex(cast[uint8](c)) func toHexLower*(u: uint16): string = @@ -143,36 +143,38 @@ func stripAndCollapse*(s: string): string = result &= ' ' inc i -func skipBlanks*(buf: string, at: int): int = +func skipBlanks*(buf: string; at: int): int = result = at while result < buf.len and buf[result] in AsciiWhitespace: inc result -func until*(s: string, c: set[char], starti = 0): string = +func until*(s: string; c: set[char]; starti = 0): string = + result = "" for i in starti ..< s.len: if s[i] in c: break result.add(s[i]) -func untilLower*(s: string, c: set[char], starti = 0): string = +func untilLower*(s: string; c: set[char]; starti = 0): string = + result = "" for i in starti ..< s.len: if s[i] in c: break result.add(s[i].toLowerAscii()) -func until*(s: string, c: char, starti = 0): string = +func until*(s: string; c: char; starti = 0): string = s.until({c}, starti) -func after*(s: string, c: set[char]): string = +func after*(s: string; c: set[char]): string = var i = 0 while i < s.len: if s[i] in c: return s.substr(i + 1) inc i -func after*(s: string, c: char): string = s.after({c}) +func after*(s: string; c: char): string = s.after({c}) -func afterLast*(s: string, c: set[char], n = 1): string = +func afterLast*(s: string; c: set[char]; n = 1): string = var j = 0 for i in countdown(s.high, 0): if s[i] in c: @@ -181,9 +183,9 @@ func afterLast*(s: string, c: set[char], n = 1): string = return s.substr(i + 1) return s -func afterLast*(s: string, c: char, n = 1): string = s.afterLast({c}, n) +func afterLast*(s: string; c: char; n = 1): string = s.afterLast({c}, n) -func beforeLast*(s: string, c: set[char], n = 1): string = +func beforeLast*(s: string; c: set[char]; n = 1): string = var j = 0 for i in countdown(s.high, 0): if s[i] in c: @@ -192,7 +194,7 @@ func beforeLast*(s: string, c: set[char], n = 1): string = return s.substr(0, i) return s -func beforeLast*(s: string, c: char, n = 1): string = s.beforeLast({c}, n) +func beforeLast*(s: string; c: char; n = 1): string = s.beforeLast({c}, n) proc c_sprintf(buf, fm: cstring): cint {.header: "<stdio.h>", importc: "sprintf", varargs} @@ -213,7 +215,7 @@ func convertSize*(size: int): string = discard c_sprintf(cstring(result), cstring("%.3g%s"), f, SizeUnit[sizepos]) result.setLen(cstring(result).len) -func numberAdditive*(i: int, range: HSlice[int, int], +func numberAdditive*(i: int; range: HSlice[int, int]; symbols: openArray[(int, string)]): string = if i notin range: return $i @@ -432,7 +434,7 @@ else: const LocalPathPercentEncodeSet* = Ascii - AsciiAlpha - AsciiDigit - {'.', '/'} -proc percentEncode*(append: var string, c: char, set: set[char], +proc percentEncode*(append: var string; c: char; set: set[char]; spaceAsPlus = false) {.inline.} = if spaceAsPlus and c == ' ': append &= '+' @@ -442,19 +444,19 @@ proc percentEncode*(append: var string, c: char, set: set[char], append &= '%' append.pushHex(c) -proc percentEncode*(append: var string, s: string, set: set[char], +proc percentEncode*(append: var string; s: string; set: set[char]; spaceAsPlus = false) {.inline.} = for c in s: append.percentEncode(c, set, spaceAsPlus) -func percentEncode*(c: char, set: set[char], spaceAsPlus = false): string +func percentEncode*(c: char; set: set[char]; spaceAsPlus = false): string {.inline.} = result.percentEncode(c, set, spaceAsPlus) -func percentEncode*(s: string, set: set[char], spaceAsPlus = false): string = +func percentEncode*(s: string; set: set[char]; spaceAsPlus = false): string = result.percentEncode(s, set, spaceAsPlus) -func percentDecode*(input: string, si = 0): string = +func percentDecode*(input: string; si = 0): string = var i = si while i < input.len: let c = input[i] @@ -489,7 +491,7 @@ func dqEscape*(s: string): string = result &= c #basically std join but with char -func join*(ss: openArray[string], sep: char): string = +func join*(ss: openArray[string]; sep: char): string = if ss.len == 0: return "" var n = ss.high - 1 @@ -501,7 +503,7 @@ func join*(ss: openArray[string], sep: char): string = result &= sep result &= ss[i] -proc passRealloc*(opaque, p: pointer, size: csize_t): pointer {.cdecl.} = +proc passRealloc*(opaque, p: pointer; size: csize_t): pointer {.cdecl.} = return realloc(p, size) # https://www.w3.org/TR/xml/#NT-Name @@ -657,6 +659,22 @@ func strictParseEnum*[T: enum](s: string): Opt[T] = return ok(tab[s]) return err() +func parseEnumNoCase*[T: enum](s: string): Opt[T] = + # cmp when len is small enough, otherwise hashmap + when {T.low..T.high}.len <= 4: + for e in T.low .. T.high: + if $e.equalsIgnoreCase(s): + return ok(e) + else: + const tab = (func(): Table[string, T] = + result = initTable[string, T]() + for e in T.low .. T.high: + result[$e] = e + )() + if s in tab: + return ok(tab[s]) + return err() + proc getContentTypeAttr*(contentType, attrname: string): string = var i = contentType.find(';') if i == -1: diff --git a/src/version.nim b/src/version.nim index 5a482dbb..66e81a9f 100644 --- a/src/version.nim +++ b/src/version.nim @@ -4,7 +4,7 @@ import std/macros template imp(x: untyped) = import x -macro tryImport(x: untyped, name: static string) = +macro tryImport(x: untyped; name: static string) = let vs = ident(name & "Version") quote do: when not compiles(imp `x`): @@ -13,7 +13,7 @@ macro tryImport(x: untyped, name: static string) = ". Please run `make submodule` to fetch the required submodules.") import `x` as `vs` -macro checkVersion(xs: static string, major, minor, patch: int) = +macro checkVersion(xs: static string; major, minor, patch: int) = let x = ident(xs & "Version") quote do: when `x`.Major < `major` or `x`.Minor < `minor` or `x`.Patch < `patch`: |