[backport] run nimpretty on web stuff

This commit is contained in:
narimiran 2019-09-27 11:08:54 +02:00
commit 0ca9cc7419
8 changed files with 103 additions and 92 deletions

View file

@ -40,7 +40,7 @@ proc openDefaultBrowser*(url: string) =
for b in getEnv("BROWSER").string.split(PathSep): for b in getEnv("BROWSER").string.split(PathSep):
try: try:
# we use ``startProcess`` here because we don't want to block! # we use ``startProcess`` here because we don't want to block!
discard startProcess(command=b, args=[url], options={poUsePath}) discard startProcess(command = b, args = [url], options = {poUsePath})
return return
except OSError: except OSError:
discard discard

View file

@ -32,7 +32,7 @@ import
const const
coreAttr* = " accesskey class contenteditable dir hidden id lang " & coreAttr* = " accesskey class contenteditable dir hidden id lang " &
"spellcheck style tabindex title translate " ## HTML DOM Core Attributes "spellcheck style tabindex title translate " ## HTML DOM Core Attributes
eventAttr* = "onabort onblur oncancel oncanplay oncanplaythrough onchange " & eventAttr* = "onabort onblur oncancel oncanplay oncanplaythrough onchange " &
"onclick oncuechange ondblclick ondurationchange onemptied onended " & "onclick oncuechange ondblclick ondurationchange onemptied onended " &
"onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload " & "onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload " &
@ -41,7 +41,7 @@ const
"onpause onplay onplaying onprogress onratechange onreset onresize " & "onpause onplay onplaying onprogress onratechange onreset onresize " &
"onscroll onseeked onseeking onselect onshow onstalled onsubmit " & "onscroll onseeked onseeking onselect onshow onstalled onsubmit " &
"onsuspend ontimeupdate ontoggle onvolumechange onwaiting " ## HTML DOM Event Attributes "onsuspend ontimeupdate ontoggle onvolumechange onwaiting " ## HTML DOM Event Attributes
ariaAttr* = " role " ## HTML DOM Aria Attributes ariaAttr* = " role " ## HTML DOM Aria Attributes
commonAttr* = coreAttr & eventAttr & ariaAttr ## HTML DOM Common Attributes commonAttr* = coreAttr & eventAttr & ariaAttr ## HTML DOM Common Attributes
proc getIdent(e: NimNode): string {.compileTime.} = proc getIdent(e: NimNode): string {.compileTime.} =
@ -572,7 +572,7 @@ macro title*(e: varargs[untyped]): untyped =
macro tr*(e: varargs[untyped]): untyped = macro tr*(e: varargs[untyped]): untyped =
## generates the HTML ``tr`` element. ## generates the HTML ``tr`` element.
result = xmlCheckedTag(e, "tr", commonAttr) result = xmlCheckedTag(e, "tr", commonAttr)
macro track*(e: varargs[untyped]): untyped = macro track*(e: varargs[untyped]): untyped =
## generates the HTML ``track`` element. ## generates the HTML ``track`` element.
@ -606,7 +606,7 @@ macro wbr*(e: varargs[untyped]): untyped =
runnableExamples: runnableExamples:
let nim = "Nim" let nim = "Nim"
assert h1(a(href="http://nim-lang.org", nim)) == assert h1(a(href = "http://nim-lang.org", nim)) ==
"""<h1><a href="http://nim-lang.org">Nim</a></h1>""" """<h1><a href="http://nim-lang.org">Nim</a></h1>"""
assert form(action="test", `accept-charset` = "Content-Type") == assert form(action = "test", `accept-charset` = "Content-Type") ==
"""<form action="test" accept-charset="Content-Type"></form>""" """<form action="test" accept-charset="Content-Type"></form>"""

View file

@ -254,9 +254,9 @@ type
MultipartData* = ref object MultipartData* = ref object
content: seq[string] content: seq[string]
ProtocolError* = object of IOError ## exception that is raised when server ProtocolError* = object of IOError ## exception that is raised when server
## does not conform to the implemented ## does not conform to the implemented
## protocol ## protocol
HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc HttpRequestError* = object of IOError ## Thrown in the ``getContent`` proc
## and ``postContent`` proc, ## and ``postContent`` proc,
@ -302,11 +302,11 @@ proc add*(p: var MultipartData, name, content: string, filename: string = "",
## Add a value to the multipart data. Raises a `ValueError` exception if ## Add a value to the multipart data. Raises a `ValueError` exception if
## `name`, `filename` or `contentType` contain newline characters. ## `name`, `filename` or `contentType` contain newline characters.
if {'\c','\L'} in name: if {'\c', '\L'} in name:
raise newException(ValueError, "name contains a newline character") raise newException(ValueError, "name contains a newline character")
if {'\c','\L'} in filename: if {'\c', '\L'} in filename:
raise newException(ValueError, "filename contains a newline character") raise newException(ValueError, "filename contains a newline character")
if {'\c','\L'} in contentType: if {'\c', '\L'} in contentType:
raise newException(ValueError, "contentType contains a newline character") raise newException(ValueError, "contentType contains a newline character")
var str = "Content-Disposition: form-data; name=\"" & name & "\"" var str = "Content-Disposition: form-data; name=\"" & name & "\""
@ -470,11 +470,11 @@ type
HttpClientBase*[SocketType] = ref object HttpClientBase*[SocketType] = ref object
socket: SocketType socket: SocketType
connected: bool connected: bool
currentURL: Uri ## Where we are currently connected. currentURL: Uri ## Where we are currently connected.
headers*: HttpHeaders ## Headers to send in requests. headers*: HttpHeaders ## Headers to send in requests.
maxRedirects: int maxRedirects: int
userAgent: string userAgent: string
timeout*: int ## Only used for blocking HttpClient for now. timeout*: int ## Only used for blocking HttpClient for now.
proxy: Proxy proxy: Proxy
## ``nil`` or the callback to call when request progress changes. ## ``nil`` or the callback to call when request progress changes.
when SocketType is Socket: when SocketType is Socket:
@ -492,7 +492,7 @@ type
parseBodyFut: Future[void] parseBodyFut: Future[void]
else: else:
bodyStream: Stream bodyStream: Stream
getBody: bool ## When `false`, the body is never read in requestAux. getBody: bool ## When `false`, the body is never read in requestAux.
type type
HttpClient* = HttpClientBase[Socket] HttpClient* = HttpClientBase[Socket]
@ -563,7 +563,7 @@ proc close*(client: HttpClient | AsyncHttpClient) =
client.socket.close() client.socket.close()
client.connected = false client.connected = false
proc getSocket*(client: HttpClient): Socket = proc getSocket*(client: HttpClient): Socket =
## Get network socket, useful if you want to find out more details about the connection ## Get network socket, useful if you want to find out more details about the connection
## ##
## this example shows info about local and remote endpoints ## this example shows info about local and remote endpoints
@ -575,7 +575,7 @@ proc getSocket*(client: HttpClient): Socket =
## ##
return client.socket return client.socket
proc getSocket*(client: AsyncHttpClient): AsyncSocket = proc getSocket*(client: AsyncHttpClient): AsyncSocket =
return client.socket return client.socket
proc reportProgress(client: HttpClient | AsyncHttpClient, proc reportProgress(client: HttpClient | AsyncHttpClient,
@ -756,7 +756,7 @@ proc parseResponse(client: HttpClient | AsyncHttpClient,
if line[linei] != ':': httpError("invalid headers") if line[linei] != ':': httpError("invalid headers")
inc(linei) # Skip : inc(linei) # Skip :
result.headers.add(name, line[linei.. ^1].strip()) result.headers.add(name, line[linei .. ^1].strip())
if result.headers.len > headerLimit: if result.headers.len > headerLimit:
httpError("too many headers") httpError("too many headers")
@ -827,7 +827,8 @@ proc newConnection(client: HttpClient | AsyncHttpClient,
connectUrl.hostname = url.hostname connectUrl.hostname = url.hostname
connectUrl.port = if url.port != "": url.port else: "443" connectUrl.port = if url.port != "": url.port else: "443"
let proxyHeaderString = generateHeaders(connectUrl, $HttpConnect, newHttpHeaders(), "", client.proxy) let proxyHeaderString = generateHeaders(connectUrl, $HttpConnect,
newHttpHeaders(), "", client.proxy)
await client.socket.send(proxyHeaderString) await client.socket.send(proxyHeaderString)
let proxyResp = await parseResponse(client, false) let proxyResp = await parseResponse(client, false)

View file

@ -28,24 +28,24 @@ type
HttpVer11, HttpVer11,
HttpVer10 HttpVer10
HttpMethod* = enum ## the requested HttpMethod HttpMethod* = enum ## the requested HttpMethod
HttpHead, ## Asks for the response identical to the one that would HttpHead, ## Asks for the response identical to the one that would
## correspond to a GET request, but without the response ## correspond to a GET request, but without the response
## body. ## body.
HttpGet, ## Retrieves the specified resource. HttpGet, ## Retrieves the specified resource.
HttpPost, ## Submits data to be processed to the identified HttpPost, ## Submits data to be processed to the identified
## resource. The data is included in the body of the ## resource. The data is included in the body of the
## request. ## request.
HttpPut, ## Uploads a representation of the specified resource. HttpPut, ## Uploads a representation of the specified resource.
HttpDelete, ## Deletes the specified resource. HttpDelete, ## Deletes the specified resource.
HttpTrace, ## Echoes back the received request, so that a client HttpTrace, ## Echoes back the received request, so that a client
## can see what intermediate servers are adding or ## can see what intermediate servers are adding or
## changing in the request. ## changing in the request.
HttpOptions, ## Returns the HTTP methods that the server supports HttpOptions, ## Returns the HTTP methods that the server supports
## for specified address. ## for specified address.
HttpConnect, ## Converts the request connection to a transparent HttpConnect, ## Converts the request connection to a transparent
## TCP/IP tunnel, usually used for proxies. ## TCP/IP tunnel, usually used for proxies.
HttpPatch ## Applies partial modifications to a resource. HttpPatch ## Applies partial modifications to a resource.
const const

View file

@ -64,7 +64,7 @@
## socket.acceptAddr(client, address) ## socket.acceptAddr(client, address)
## echo("Client connected from: ", address) ## echo("Client connected from: ", address)
{.deadCodeElim: on.} # dce option deprecated {.deadCodeElim: on.} # dce option deprecated
import nativesockets, os, strutils, parseutils, times, sets, options, import nativesockets, os, strutils, parseutils, times, sets, options,
std/monotimes std/monotimes
export nativesockets.Port, nativesockets.`$`, nativesockets.`==` export nativesockets.Port, nativesockets.`$`, nativesockets.`==`
@ -116,12 +116,12 @@ const
MaxLineLength* = 1_000_000 MaxLineLength* = 1_000_000
type type
SocketImpl* = object ## socket type SocketImpl* = object ## socket type
fd: SocketHandle fd: SocketHandle
isBuffered: bool # determines whether this socket is buffered. isBuffered: bool # determines whether this socket is buffered.
buffer: array[0..BufferSize, char] buffer: array[0..BufferSize, char]
currPos: int # current index in buffer currPos: int # current index in buffer
bufLen: int # current length of buffer bufLen: int # current length of buffer
when defineSsl: when defineSsl:
isSsl: bool isSsl: bool
sslHandle: SSLPtr sslHandle: SSLPtr
@ -154,17 +154,17 @@ when defined(nimHasStyleChecks):
type type
IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address
IPv6, ## IPv6 address IPv6, ## IPv6 address
IPv4 ## IPv4 address IPv4 ## IPv4 address
IpAddress* = object ## stores an arbitrary IP address IpAddress* = object ## stores an arbitrary IP address
case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6) case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
of IpAddressFamily.IPv6: of IpAddressFamily.IPv6:
address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
## case of IPv6 ## case of IPv6
of IpAddressFamily.IPv4: of IpAddressFamily.IPv4:
address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
## case of IPv4 ## case of IPv4
when defined(nimHasStyleChecks): when defined(nimHasStyleChecks):
{.pop.} {.pop.}
@ -234,7 +234,7 @@ proc parseIPv4Address(addressStr: string): IpAddress =
## Raises ValueError on errors ## Raises ValueError on errors
var var
byteCount = 0 byteCount = 0
currentByte:uint16 = 0 currentByte: uint16 = 0
separatorValid = false separatorValid = false
result = IpAddress(family: IpAddressFamily.IPv4) result = IpAddress(family: IpAddressFamily.IPv4)
@ -273,14 +273,14 @@ proc parseIPv6Address(addressStr: string): IpAddress =
var var
groupCount = 0 groupCount = 0
currentGroupStart = 0 currentGroupStart = 0
currentShort:uint32 = 0 currentShort: uint32 = 0
separatorValid = true separatorValid = true
dualColonGroup = -1 dualColonGroup = -1
lastWasColon = false lastWasColon = false
v4StartPos = -1 v4StartPos = -1
byteCount = 0 byteCount = 0
for i,c in addressStr: for i, c in addressStr:
if c == ':': if c == ':':
if not separatorValid: if not separatorValid:
raise newException(ValueError, raise newException(ValueError,
@ -343,7 +343,7 @@ proc parseIPv6Address(addressStr: string): IpAddress =
result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
groupCount.inc() groupCount.inc()
else: # Must parse IPv4 address else: # Must parse IPv4 address
for i,c in addressStr[v4StartPos..high(addressStr)]: for i, c in addressStr[v4StartPos..high(addressStr)]:
if c in strutils.Digits: # Character is a number if c in strutils.Digits: # Character is a number
currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0')) currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
if currentShort > 255'u32: if currentShort > 255'u32:
@ -497,7 +497,8 @@ when defineSsl:
# http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html # http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html
proc loadCertificates(ctx: SSL_CTX, certFile, keyFile: string) = proc loadCertificates(ctx: SSL_CTX, certFile, keyFile: string) =
if certFile != "" and not existsFile(certFile): if certFile != "" and not existsFile(certFile):
raise newException(system.IOError, "Certificate file could not be found: " & certFile) raise newException(system.IOError,
"Certificate file could not be found: " & certFile)
if keyFile != "" and not existsFile(keyFile): if keyFile != "" and not existsFile(keyFile):
raise newException(system.IOError, "Key file could not be found: " & keyFile) raise newException(system.IOError, "Key file could not be found: " & keyFile)
@ -516,7 +517,7 @@ when defineSsl:
raiseSSLError("Verification of private key file failed.") raiseSSLError("Verification of private key file failed.")
proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer, proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer,
certFile = "", keyFile = "", cipherList = "ALL"): SSLContext = certFile = "", keyFile = "", cipherList = "ALL"): SSLContext =
## Creates an SSL context. ## Creates an SSL context.
## ##
## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 ## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1
@ -586,8 +587,9 @@ when defineSsl:
proc clientGetPskFunc*(ctx: SSLContext): SslClientGetPskFunc = proc clientGetPskFunc*(ctx: SSLContext): SslClientGetPskFunc =
return ctx.getExtraInternal().clientGetPskFunc return ctx.getExtraInternal().clientGetPskFunc
proc pskClientCallback(ssl: SslPtr; hint: cstring; identity: cstring; max_identity_len: cuint; psk: ptr cuchar; proc pskClientCallback(ssl: SslPtr; hint: cstring; identity: cstring;
max_psk_len: cuint): cuint {.cdecl.} = max_identity_len: cuint; psk: ptr cuchar;
max_psk_len: cuint): cuint {.cdecl.} =
let ctx = SSLContext(context: ssl.SSL_get_SSL_CTX) let ctx = SSLContext(context: ssl.SSL_get_SSL_CTX)
let hintString = if hint == nil: "" else: $hint let hintString = if hint == nil: "" else: $hint
let (identityString, pskString) = (ctx.clientGetPskFunc)(hintString) let (identityString, pskString) = (ctx.clientGetPskFunc)(hintString)
@ -613,7 +615,8 @@ when defineSsl:
proc serverGetPskFunc*(ctx: SSLContext): SslServerGetPskFunc = proc serverGetPskFunc*(ctx: SSLContext): SslServerGetPskFunc =
return ctx.getExtraInternal().serverGetPskFunc return ctx.getExtraInternal().serverGetPskFunc
proc pskServerCallback(ssl: SslCtx; identity: cstring; psk: ptr cuchar; max_psk_len: cint): cuint {.cdecl.} = proc pskServerCallback(ssl: SslCtx; identity: cstring; psk: ptr cuchar;
max_psk_len: cint): cuint {.cdecl.} =
let ctx = SSLContext(context: ssl.SSL_get_SSL_CTX) let ctx = SSLContext(context: ssl.SSL_get_SSL_CTX)
let pskString = (ctx.serverGetPskFunc)($identity) let pskString = (ctx.serverGetPskFunc)($identity)
if psk.len.cint > max_psk_len: if psk.len.cint > max_psk_len:
@ -765,7 +768,7 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
if realaddr == "": if realaddr == "":
case socket.domain case socket.domain
of AF_INET6: realaddr = "::" of AF_INET6: realaddr = "::"
of AF_INET: realaddr = "0.0.0.0" of AF_INET: realaddr = "0.0.0.0"
else: else:
raise newException(ValueError, raise newException(ValueError,
"Unknown socket address family and no address specified to bindAddr") "Unknown socket address family and no address specified to bindAddr")
@ -940,8 +943,8 @@ proc getPeerAddr*(socket: Socket): (string, Port) =
## This is high-level interface for `getpeername`:idx:. ## This is high-level interface for `getpeername`:idx:.
getPeerAddr(socket.fd, socket.domain) getPeerAddr(socket.fd, socket.domain)
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {. proc setSockOpt*(socket: Socket, opt: SOBool, value: bool,
tags: [WriteIOEffect].} = level = SOL_SOCKET) {.tags: [WriteIOEffect].} =
## Sets option ``opt`` to a boolean value specified by ``value``. ## Sets option ``opt`` to a boolean value specified by ``value``.
## ##
## .. code-block:: Nim ## .. code-block:: Nim
@ -959,7 +962,7 @@ when defined(posix) or defined(nimdoc):
when not defined(nimdoc): when not defined(nimdoc):
var socketAddr = makeUnixAddr(path) var socketAddr = makeUnixAddr(path)
if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), if socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
(sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32: (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
proc bindUnix*(socket: Socket, path: string) = proc bindUnix*(socket: Socket, path: string) =
@ -968,7 +971,7 @@ when defined(posix) or defined(nimdoc):
when not defined(nimdoc): when not defined(nimdoc):
var socketAddr = makeUnixAddr(path) var socketAddr = makeUnixAddr(path)
if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
(sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32: (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
when defined(ssl): when defined(ssl):
@ -1038,7 +1041,8 @@ template retRead(flags, readBytes: int) {.dirty.} =
else: else:
return res return res
proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [ReadIOEffect].} = proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [
ReadIOEffect].} =
## Receives data from a socket. ## Receives data from a socket.
## ##
## **Note**: This is a low-level function, you may be interested in the higher ## **Note**: This is a low-level function, you may be interested in the higher
@ -1093,7 +1097,8 @@ proc waitFor(socket: Socket, waited: var Duration, timeout, size: int,
result = 1 result = 1
if size <= 0: assert false if size <= 0: assert false
if timeout == -1: return size if timeout == -1: return size
if socket.isBuffered and socket.bufLen != 0 and socket.bufLen != socket.currPos: if socket.isBuffered and socket.bufLen != 0 and
socket.bufLen != socket.currPos:
result = socket.bufLen - socket.currPos result = socket.bufLen - socket.currPos
result = min(result, size) result = min(result, size)
else: else:
@ -1499,7 +1504,7 @@ proc `$`*(address: IpAddress): string =
else: # Print address else: # Print address
var printedLastGroup = false var printedLastGroup = false
for i in 0..7: for i in 0..7:
var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8 var word: uint16 = (cast[uint16](address.address_v6[i*2])) shl 8
word = word or cast[uint16](address.address_v6[i*2+1]) word = word or cast[uint16](address.address_v6[i*2+1])
if biggestZeroCount != 0 and # Check if group is in skip group if biggestZeroCount != 0 and # Check if group is in skip group

View file

@ -127,7 +127,7 @@ proc `$`*(msg: Message): string =
result.add("\c\L") result.add("\c\L")
result.add(msg.msgBody) result.add(msg.msgBody)
proc newSmtp*(useSsl = false, debug=false, proc newSmtp*(useSsl = false, debug = false,
sslContext: SSLContext = nil): Smtp = sslContext: SSLContext = nil): Smtp =
## Creates a new ``Smtp`` instance. ## Creates a new ``Smtp`` instance.
new result new result
@ -142,7 +142,7 @@ proc newSmtp*(useSsl = false, debug=false,
else: else:
{.error: "SMTP module compiled without SSL support".} {.error: "SMTP module compiled without SSL support".}
proc newAsyncSmtp*(useSsl = false, debug=false, proc newAsyncSmtp*(useSsl = false, debug = false,
sslContext: SSLContext = nil): AsyncSmtp = sslContext: SSLContext = nil): AsyncSmtp =
## Creates a new ``AsyncSmtp`` instance. ## Creates a new ``AsyncSmtp`` instance.
new result new result
@ -256,7 +256,7 @@ when not defined(testing) and isMainModule:
proc async_test() {.async.} = proc async_test() {.async.} =
let client = newAsyncSmtp( let client = newAsyncSmtp(
conf["use_tls"].parseBool, conf["use_tls"].parseBool,
debug=true debug = true
) )
await client.connect(conf["smtphost"], conf["port"].parseInt.Port) await client.connect(conf["smtphost"], conf["port"].parseInt.Port)
await client.auth(conf["username"], conf["password"]) await client.auth(conf["username"], conf["password"])
@ -267,7 +267,7 @@ when not defined(testing) and isMainModule:
proc sync_test() = proc sync_test() =
var smtpConn = newSmtp( var smtpConn = newSmtp(
conf["use_tls"].parseBool, conf["use_tls"].parseBool,
debug=true debug = true
) )
smtpConn.connect(conf["smtphost"], conf["port"].parseInt.Port) smtpConn.connect(conf["smtphost"], conf["port"].parseInt.Port)
smtpConn.auth(conf["username"], conf["password"]) smtpConn.auth(conf["username"], conf["password"])

View file

@ -46,7 +46,7 @@ type
hostname*, port*, path*, query*, anchor*: string hostname*, port*, path*, query*, anchor*: string
opaque*: bool opaque*: bool
proc encodeUrl*(s: string, usePlus=true): string = proc encodeUrl*(s: string, usePlus = true): string =
## Encodes a URL according to RFC3986. ## Encodes a URL according to RFC3986.
## ##
## This means that characters in the set ## This means that characters in the set
@ -75,7 +75,7 @@ proc encodeUrl*(s: string, usePlus=true): string =
add(result, '%') add(result, '%')
add(result, toHex(ord(c), 2)) add(result, toHex(ord(c), 2))
proc decodeUrl*(s: string, decodePlus=true): string = proc decodeUrl*(s: string, decodePlus = true): string =
## Decodes a URL according to RFC3986. ## Decodes a URL according to RFC3986.
## ##
## This means that any ``%xx`` (where ``xx`` denotes a hexadecimal ## This means that any ``%xx`` (where ``xx`` denotes a hexadecimal
@ -90,7 +90,8 @@ proc decodeUrl*(s: string, decodePlus=true): string =
runnableExamples: runnableExamples:
assert decodeUrl("https%3A%2F%2Fnim-lang.org") == "https://nim-lang.org" assert decodeUrl("https%3A%2F%2Fnim-lang.org") == "https://nim-lang.org"
assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis+is+a+test") == "https://nim-lang.org/this is a test" assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis+is+a+test") == "https://nim-lang.org/this is a test"
assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis%20is%20a%20test", false) == "https://nim-lang.org/this is a test" assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis%20is%20a%20test",
false) == "https://nim-lang.org/this is a test"
proc handleHexChar(c: char, x: var int) {.inline.} = proc handleHexChar(c: char, x: var int) {.inline.} =
case c case c
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
@ -119,7 +120,8 @@ proc decodeUrl*(s: string, decodePlus=true): string =
inc(j) inc(j)
setLen(result, j) setLen(result, j)
proc encodeQuery*(query: openArray[(string, string)], usePlus=true, omitEq=true): string = proc encodeQuery*(query: openArray[(string, string)], usePlus = true,
omitEq = true): string =
## Encodes a set of (key, value) parameters into a URL query string. ## Encodes a set of (key, value) parameters into a URL query string.
## ##
## Every (key, value) pair is URL-encoded and written as ``key=value``. If the ## Every (key, value) pair is URL-encoded and written as ``key=value``. If the
@ -133,7 +135,7 @@ proc encodeQuery*(query: openArray[(string, string)], usePlus=true, omitEq=true)
## **See also:** ## **See also:**
## * `encodeUrl proc<#encodeUrl,string>`_ ## * `encodeUrl proc<#encodeUrl,string>`_
runnableExamples: runnableExamples:
assert encodeQuery({:}) == "" assert encodeQuery({: }) == ""
assert encodeQuery({"a": "1", "b": "2"}) == "a=1&b=2" assert encodeQuery({"a": "1", "b": "2"}) == "a=1&b=2"
assert encodeQuery({"a": "1", "b": ""}) == "a=1&b" assert encodeQuery({"a": "1", "b": ""}) == "a=1&b"
for elem in query: for elem in query:
@ -369,7 +371,8 @@ proc combine*(uris: varargs[Uri]): Uri =
## **See also:** ## **See also:**
## * `/ proc <#/,Uri,string>`_ for building URIs ## * `/ proc <#/,Uri,string>`_ for building URIs
runnableExamples: runnableExamples:
let foo = combine(parseUri("https://nim-lang.org/"), parseUri("docs/"), parseUri("manual.html")) let foo = combine(parseUri("https://nim-lang.org/"), parseUri("docs/"),
parseUri("manual.html"))
assert foo.hostname == "nim-lang.org" assert foo.hostname == "nim-lang.org"
assert foo.path == "/docs/manual.html" assert foo.path == "/docs/manual.html"
result = uris[0] result = uris[0]
@ -716,11 +719,11 @@ when isMainModule:
doAssert encodeQuery({:}) == "" doAssert encodeQuery({:}) == ""
doAssert encodeQuery({"foo": "bar"}) == "foo=bar" doAssert encodeQuery({"foo": "bar"}) == "foo=bar"
doAssert encodeQuery({"foo": "bar & baz"}) == "foo=bar+%26+baz" doAssert encodeQuery({"foo": "bar & baz"}) == "foo=bar+%26+baz"
doAssert encodeQuery({"foo": "bar & baz"}, usePlus=false) == "foo=bar%20%26%20baz" doAssert encodeQuery({"foo": "bar & baz"}, usePlus = false) == "foo=bar%20%26%20baz"
doAssert encodeQuery({"foo": ""}) == "foo" doAssert encodeQuery({"foo": ""}) == "foo"
doAssert encodeQuery({"foo": ""}, omitEq=false) == "foo=" doAssert encodeQuery({"foo": ""}, omitEq = false) == "foo="
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3" doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3"
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq=false) == "a=1&b=&c=3" doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false) == "a=1&b=&c=3"
block: block:
var foo = parseUri("http://example.com") / "foo" ? {"bar": "1", "baz": "qux"} var foo = parseUri("http://example.com") / "foo" ? {"bar": "1", "baz": "qux"}

View file

@ -42,12 +42,12 @@ type
## Use `newXmlTree proc <#newXmlTree,string,openArray[XmlNode],XmlAttributes>`_ ## Use `newXmlTree proc <#newXmlTree,string,openArray[XmlNode],XmlAttributes>`_
## for creating a new tree. ## for creating a new tree.
XmlNodeKind* = enum ## Different kinds of XML nodes. XmlNodeKind* = enum ## Different kinds of XML nodes.
xnText, ## a text element xnText, ## a text element
xnElement, ## an element with 0 or more children xnElement, ## an element with 0 or more children
xnCData, ## a CDATA node xnCData, ## a CDATA node
xnEntity, ## an entity (like ``&thing;``) xnEntity, ## an entity (like ``&thing;``)
xnComment ## an XML comment xnComment ## an XML comment
XmlAttributes* = StringTableRef ## An alias for a string to string mapping. XmlAttributes* = StringTableRef ## An alias for a string to string mapping.
## ##
@ -62,7 +62,7 @@ type
fTag: string fTag: string
s: seq[XmlNode] s: seq[XmlNode]
fAttr: XmlAttributes fAttr: XmlAttributes
fClientData: int ## for other clients fClientData: int ## for other clients
const const
xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
@ -344,7 +344,7 @@ proc kind*(n: XmlNode): XmlNodeKind {.inline.} =
assert b.kind == xnText assert b.kind == xnText
result = n.k result = n.k
proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} = proc `[]`*(n: XmlNode, i: int): XmlNode {.inline.} =
## Returns the `i`'th child of `n`. ## Returns the `i`'th child of `n`.
runnableExamples: runnableExamples:
var f = newElement("myTag") var f = newElement("myTag")
@ -356,7 +356,7 @@ proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} =
assert n.k == xnElement assert n.k == xnElement
result = n.s[i] result = n.s[i]
proc `[]`* (n: var XmlNode, i: int): var XmlNode {.inline.} = proc `[]`*(n: var XmlNode, i: int): var XmlNode {.inline.} =
## Returns the `i`'th child of `n` so that it can be modified. ## Returns the `i`'th child of `n` so that it can be modified.
assert n.k == xnElement assert n.k == xnElement
result = n.s[i] result = n.s[i]
@ -421,7 +421,8 @@ iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
assert n.k == xnElement assert n.k == xnElement
for i in 0 .. n.len-1: yield n[i] for i in 0 .. n.len-1: yield n[i]
proc toXmlAttributes*(keyValuePairs: varargs[tuple[key, val: string]]): XmlAttributes = proc toXmlAttributes*(keyValuePairs: varargs[tuple[key,
val: string]]): XmlAttributes =
## Converts `{key: value}` pairs into `XmlAttributes`. ## Converts `{key: value}` pairs into `XmlAttributes`.
## ##
## .. code-block:: ## .. code-block::
@ -558,7 +559,7 @@ proc noWhitespace(n: XmlNode): bool =
if n[i].kind in {xnText, xnEntity}: return true if n[i].kind in {xnText, xnEntity}: return true
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2, proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
addNewLines=true) = addNewLines = true) =
## Adds the textual representation of `n` to string `result`. ## Adds the textual representation of `n` to string `result`.
runnableExamples: runnableExamples:
var var
@ -654,7 +655,8 @@ proc child*(n: XmlNode, name: string): XmlNode =
if i.tag == name: if i.tag == name:
return i return i
proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode], caseInsensitive = false) = proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode],
caseInsensitive = false) =
## Iterates over all the children of `n` returning those matching `tag`. ## Iterates over all the children of `n` returning those matching `tag`.
## ##
## Found nodes satisfying the condition will be appended to the `result` ## Found nodes satisfying the condition will be appended to the `result`
@ -752,4 +754,4 @@ macro `<>`*(x: untyped): untyped =
when isMainModule: when isMainModule:
assert """<a href="http://nim-lang.org">Nim rules.</a>""" == assert """<a href="http://nim-lang.org">Nim rules.</a>""" ==
$(<>a(href="http://nim-lang.org", newText("Nim rules."))) $(<>a(href = "http://nim-lang.org", newText("Nim rules.")))