summary refs log tree commit diff stats
path: root/lib/std/jsformdata.nim
blob: 120f8742d2935a4377454be31bef14d2a120d381 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
## - `FormData` for the JavaScript target: https://developer.mozilla.org/en-US/docs/Web/API/FormData
when not defined(js):
  {.fatal: "Module jsformdata is designed to be used with the JavaScript backend.".}

type FormData* = ref object of JsRoot ## FormData API.

func newFormData*(): FormData {.importjs: "new FormData()".}

func add*(self: FormData; name: cstring; value: SomeNumber | bool | cstring) {.importjs: "#.append(#, #)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
  ## Duplicate keys are allowed and order is preserved.

func add*(self: FormData; name: cstring; value: SomeNumber | bool | cstring, filename: cstring) {.importjs: "#.append(#, #, #)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
  ## Duplicate keys are allowed and order is preserved.

func delete*(self: FormData; name: cstring) {.importjs: "#.$1(#)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/delete
  ##
  ## .. warning:: Deletes *all items* with the same key name.

func getAll*(self: FormData; name: cstring): seq[cstring] {.importjs: "#.$1(#)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/getAll

func hasKey*(self: FormData; name: cstring): bool {.importjs: "#.has(#)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/has

func keys*(self: FormData): seq[cstring] {.importjs: "Array.from(#.$1())".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/keys

func values*(self: FormData): seq[cstring] {.importjs: "Array.from(#.$1())".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/values

func pairs*(self: FormData): seq[tuple[key, val: cstring]] {.importjs: "Array.from(#.entries())".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/entries

func put*(self: FormData; name, value, filename: cstring) {.importjs: "#.set(#, #, #)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/set

func `[]=`*(self: FormData; name, value: cstring) {.importjs: "#.set(#, #)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/set

func `[]`*(self: FormData; name: cstring): cstring {.importjs: "#.get(#)".}
  ## https://developer.mozilla.org/en-US/docs/Web/API/FormData/get

func clear*(self: FormData) {.importjs:
  "(() => { const frmdt = #; Array.from(frmdt.keys()).forEach((key) => frmdt.delete(key)) })()".}
  ## Convenience func to delete all items from `FormData`.

func toCstring*(self: FormData): cstring {.importjs: "JSON.stringify(#)".}

func `$`*(self: FormData): string = $toCstring(self)

func len*(self: FormData): int {.importjs: "Array.from(#.entries()).length".}


runnableExamples("-r:off"):
  let data: FormData = newFormData()
  data["key0"] = "value0".cstring
  data.add("key1".cstring, "value1".cstring)
  data.delete("key1")
  assert data.hasKey("key0")
  assert data["key0"] == "value0".cstring
  data.clear()
  assert data.len == 0
an>f, filename): rawMessage(errCannotOpenFile, filename) return OpenParsers(p, filename, LLStreamOpen(f)) result = ParseAll(p) CloseParsers(p) proc parseAll(p: var TParsers): PNode = case p.skin of skinStandard: result = parser.parseAll(p.parser) of skinBraces: result = pbraces.parseAll(p.parser) of skinEndX: InternalError("parser to implement") result = ast.emptyNode # skinEndX: result := pendx.parseAll(p.parser); proc parseTopLevelStmt(p: var TParsers): PNode = case p.skin of skinStandard: result = parser.parseTopLevelStmt(p.parser) of skinBraces: result = pbraces.parseTopLevelStmt(p.parser) of skinEndX: InternalError("parser to implement") result = ast.emptyNode #skinEndX: result := pendx.parseTopLevelStmt(p.parser); proc UTF8_BOM(s: string): int = if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'): result = 3 else: result = 0 proc containsShebang(s: string, i: int): bool = if (s[i] == '#') and (s[i + 1] == '!'): var j = i + 2 while s[j] in WhiteSpace: inc(j) result = s[j] == '/' proc parsePipe(filename: string, inputStream: PLLStream): PNode = result = ast.emptyNode var s = LLStreamOpen(filename, fmRead) if s != nil: var line = LLStreamReadLine(s) var i = UTF8_Bom(line) if containsShebang(line, i): line = LLStreamReadLine(s) i = 0 if (line[i] == '#') and (line[i + 1] == '!'): inc(i, 2) while line[i] in WhiteSpace: inc(i) var q: TParser OpenParser(q, filename, LLStreamOpen(substr(line, i))) result = parser.parseAll(q) CloseParser(q) LLStreamClose(s) proc getFilter(ident: PIdent): TFilterKind = for i in countup(low(TFilterKind), high(TFilterKind)): if IdentEq(ident, filterNames[i]): return i result = filtNone proc getParser(ident: PIdent): TParserKind = for i in countup(low(TParserKind), high(TParserKind)): if IdentEq(ident, parserNames[i]): return i rawMessage(errInvalidDirectiveX, ident.s) proc getCallee(n: PNode): PIdent = if (n.kind == nkCall) and (n.sons[0].kind == nkIdent): result = n.sons[0].ident elif n.kind == nkIdent: result = n.ident else: rawMessage(errXNotAllowedHere, renderTree(n)) proc applyFilter(p: var TParsers, n: PNode, filename: string, stdin: PLLStream): PLLStream = var ident = getCallee(n) var f = getFilter(ident) case f of filtNone: p.skin = getParser(ident) result = stdin of filtTemplate: result = filterTmpl(stdin, filename, n) of filtStrip: result = filterStrip(stdin, filename, n) of filtReplace: result = filterReplace(stdin, filename, n) if f != filtNone: if gVerbosity >= 2: rawMessage(hintCodeBegin, []) MsgWriteln(result.s) rawMessage(hintCodeEnd, []) proc evalPipe(p: var TParsers, n: PNode, filename: string, start: PLLStream): PLLStream = result = start if n.kind == nkEmpty: return if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and IdentEq(n.sons[0].ident, "|"): for i in countup(1, 2): if n.sons[i].kind == nkInfix: result = evalPipe(p, n.sons[i], filename, result) else: result = applyFilter(p, n.sons[i], filename, result) elif n.kind == nkStmtList: result = evalPipe(p, n.sons[0], filename, result) else: result = applyFilter(p, n, filename, result) proc openParsers(p: var TParsers, filename: string, inputstream: PLLStream) = var s: PLLStream p.skin = skinStandard var pipe = parsePipe(filename, inputStream) if pipe != nil: s = evalPipe(p, pipe, filename, inputStream) else: s = inputStream case p.skin of skinStandard, skinBraces, skinEndX: parser.openParser(p.parser, filename, s) proc closeParsers(p: var TParsers) = parser.closeParser(p.parser)