@@ -0,0 +1,195 @@
var _elm_lang$http$Http_Progress$onSelfMsg = F3(
function (router, _p0, state) {
return _elm_lang$core$Task$succeed(state);
});
var _elm_lang$http$Http_Progress$addSub = F2(
function (_p1, subDict) {
var _p2 = _p1;
var _p3 = _p2._1;
var request = _p3.request;
var uid = A2(
_elm_lang$core$Basics_ops['++'],
_p2._0,
A2(_elm_lang$core$Basics_ops['++'], request.method, request.url));
return A3(_elm_lang$core$Dict$insert, uid, _p3, subDict);
});
var _elm_lang$http$Http_Progress$collectSubs = function (subs) {
return A3(_elm_lang$core$List$foldl, _elm_lang$http$Http_Progress$addSub, _elm_lang$core$Dict$empty, subs);
};
var _elm_lang$http$Http_Progress$toTask = F2(
function (router, _p4) {
var _p5 = _p4;
return A2(
_elm_lang$core$Task$onError,
function (_p6) {
return A2(
_elm_lang$core$Platform$sendToApp,
router,
_p5.toError(_p6));
},
A2(
_elm_lang$core$Task$andThen,
_elm_lang$core$Platform$sendToApp(router),
A2(
_elm_lang$http$Native_Http.toTask,
_p5.request,
_elm_lang$core$Maybe$Just(
function (_p7) {
return A2(
_elm_lang$core$Platform$sendToApp,
router,
_p5.toProgress(_p7));
}))));
});
var _elm_lang$http$Http_Progress$spawnRequests = F3(
function (router, trackedRequests, state) {
var _p8 = trackedRequests;
if (_p8.ctor === '[]') {
return _elm_lang$core$Task$succeed(state);
} else {
return A2(
_elm_lang$core$Task$andThen,
function (process) {
return A3(
_elm_lang$http$Http_Progress$spawnRequests,
router,
_p8._1,
A3(_elm_lang$core$Dict$insert, _p8._0._0, process, state));
},
_elm_lang$core$Process$spawn(
A2(_elm_lang$http$Http_Progress$toTask, router, _p8._0._1)));
}
});
var _elm_lang$http$Http_Progress$onEffects = F3(
function (router, subs, state) {
var rightStep = F3(
function (id, trackedRequest, _p9) {
var _p10 = _p9;
return {
ctor: '_Tuple3',
_0: _p10._0,
_1: _p10._1,
_2: {
ctor: '::',
_0: {ctor: '_Tuple2', _0: id, _1: trackedRequest},
_1: _p10._2
}
};
});
var bothStep = F4(
function (id, process, _p12, _p11) {
var _p13 = _p11;
return {
ctor: '_Tuple3',
_0: _p13._0,
_1: A3(_elm_lang$core$Dict$insert, id, process, _p13._1),
_2: _p13._2
};
});
var leftStep = F3(
function (id, process, _p14) {
var _p15 = _p14;
return {
ctor: '_Tuple3',
_0: {
ctor: '::',
_0: _elm_lang$core$Process$kill(process),
_1: _p15._0
},
_1: _p15._1,
_2: _p15._2
};
});
var subDict = _elm_lang$http$Http_Progress$collectSubs(subs);
var _p16 = A6(
_elm_lang$core$Dict$merge,
leftStep,
bothStep,
rightStep,
state,
subDict,
{
ctor: '_Tuple3',
_0: {ctor: '[]'},
_1: _elm_lang$core$Dict$empty,
_2: {ctor: '[]'}
});
var dead = _p16._0;
var ongoing = _p16._1;
var $new = _p16._2;
return A2(
_elm_lang$core$Task$andThen,
function (_p17) {
return A3(_elm_lang$http$Http_Progress$spawnRequests, router, $new, ongoing);
},
_elm_lang$core$Task$sequence(dead));
});
var _elm_lang$http$Http_Progress$init = _elm_lang$core$Task$succeed(_elm_lang$core$Dict$empty);
var _elm_lang$http$Http_Progress$map = F2(
function (func, _p18) {
var _p19 = _p18;
return {
request: A2(_elm_lang$http$Http_Internal$map, func, _p19.request),
toProgress: function (_p20) {
return func(
_p19.toProgress(_p20));
},
toError: function (_p21) {
return func(
_p19.toError(_p21));
}
};
});
var _elm_lang$http$Http_Progress$subscription = _elm_lang$core$Native_Platform.leaf('Http.Progress');
var _elm_lang$http$Http_Progress$TrackedRequest = F3(
function (a, b, c) {
return {request: a, toProgress: b, toError: c};
});
var _elm_lang$http$Http_Progress$Done = function (a) {
return {ctor: 'Done', _0: a};
};
var _elm_lang$http$Http_Progress$Fail = function (a) {
return {ctor: 'Fail', _0: a};
};
var _elm_lang$http$Http_Progress$Some = function (a) {
return {ctor: 'Some', _0: a};
};
var _elm_lang$http$Http_Progress$None = {ctor: 'None'};
var _elm_lang$http$Http_Progress$Track = F2(
function (a, b) {
return {ctor: 'Track', _0: a, _1: b};
});
var _elm_lang$http$Http_Progress$track = F3(
function (id, toMessage, _p22) {
var _p23 = _p22;
return _elm_lang$http$Http_Progress$subscription(
A2(
_elm_lang$http$Http_Progress$Track,
id,
{
request: A2(
_elm_lang$http$Http_Internal$map,
function (_p24) {
return toMessage(
_elm_lang$http$Http_Progress$Done(_p24));
},
_p23._0),
toProgress: function (_p25) {
return toMessage(
_elm_lang$http$Http_Progress$Some(_p25));
},
toError: function (_p26) {
return toMessage(
_elm_lang$http$Http_Progress$Fail(_p26));
}
}));
});
var _elm_lang$http$Http_Progress$subMap = F2(
function (func, _p27) {
var _p28 = _p27;
return A2(
_elm_lang$http$Http_Progress$Track,
_p28._0,
A2(_elm_lang$http$Http_Progress$map, func, _p28._1));
});
_elm_lang$core$Native_Platform.effectManagers['Http.Progress'] = {pkg: 'elm-lang/http', init: _elm_lang$http$Http_Progress$init, onEffects: _elm_lang$http$Http_Progress$onEffects, onSelfMsg: _elm_lang$http$Http_Progress$onSelfMsg, tag: 'sub', subMap: _elm_lang$http$Http_Progress$subMap};
Binary file not shown.
@@ -0,0 +1,94 @@
var _elm_lang$http$Http$decodeUri = _elm_lang$http$Native_Http.decodeUri;
var _elm_lang$http$Http$encodeUri = _elm_lang$http$Native_Http.encodeUri;
var _elm_lang$http$Http$expectStringResponse = _elm_lang$http$Native_Http.expectStringResponse;
var _elm_lang$http$Http$expectJson = function (decoder) {
return _elm_lang$http$Http$expectStringResponse(
function (response) {
return A2(_elm_lang$core$Json_Decode$decodeString, decoder, response.body);
});
};
var _elm_lang$http$Http$expectString = _elm_lang$http$Http$expectStringResponse(
function (response) {
return _elm_lang$core$Result$Ok(response.body);
});
var _elm_lang$http$Http$multipartBody = _elm_lang$http$Native_Http.multipart;
var _elm_lang$http$Http$stringBody = _elm_lang$http$Http_Internal$StringBody;
var _elm_lang$http$Http$jsonBody = function (value) {
return A2(
_elm_lang$http$Http_Internal$StringBody,
'application/json',
A2(_elm_lang$core$Json_Encode$encode, 0, value));
};
var _elm_lang$http$Http$emptyBody = _elm_lang$http$Http_Internal$EmptyBody;
var _elm_lang$http$Http$header = _elm_lang$http$Http_Internal$Header;
var _elm_lang$http$Http$request = _elm_lang$http$Http_Internal$Request;
var _elm_lang$http$Http$post = F3(
function (url, body, decoder) {
return _elm_lang$http$Http$request(
{
method: 'POST',
headers: {ctor: '[]'},
url: url,
body: body,
expect: _elm_lang$http$Http$expectJson(decoder),
timeout: _elm_lang$core$Maybe$Nothing,
withCredentials: false
});
});
var _elm_lang$http$Http$get = F2(
function (url, decoder) {
return _elm_lang$http$Http$request(
{
method: 'GET',
headers: {ctor: '[]'},
url: url,
body: _elm_lang$http$Http$emptyBody,
expect: _elm_lang$http$Http$expectJson(decoder),
timeout: _elm_lang$core$Maybe$Nothing,
withCredentials: false
});
});
var _elm_lang$http$Http$getString = function (url) {
return _elm_lang$http$Http$request(
{
method: 'GET',
headers: {ctor: '[]'},
url: url,
body: _elm_lang$http$Http$emptyBody,
expect: _elm_lang$http$Http$expectString,
timeout: _elm_lang$core$Maybe$Nothing,
withCredentials: false
});
};
var _elm_lang$http$Http$toTask = function (_p0) {
var _p1 = _p0;
return A2(_elm_lang$http$Native_Http.toTask, _p1._0, _elm_lang$core$Maybe$Nothing);
};
var _elm_lang$http$Http$send = F2(
function (resultToMessage, request) {
return A2(
_elm_lang$core$Task$attempt,
resultToMessage,
_elm_lang$http$Http$toTask(request));
});
var _elm_lang$http$Http$Response = F4(
function (a, b, c, d) {
return {url: a, status: b, headers: c, body: d};
});
var _elm_lang$http$Http$BadPayload = F2(
function (a, b) {
return {ctor: 'BadPayload', _0: a, _1: b};
});
var _elm_lang$http$Http$BadStatus = function (a) {
return {ctor: 'BadStatus', _0: a};
};
var _elm_lang$http$Http$NetworkError = {ctor: 'NetworkError'};
var _elm_lang$http$Http$Timeout = {ctor: 'Timeout'};
var _elm_lang$http$Http$BadUrl = function (a) {
return {ctor: 'BadUrl', _0: a};
};
var _elm_lang$http$Http$StringPart = F2(
function (a, b) {
return {ctor: 'StringPart', _0: a, _1: b};
});
var _elm_lang$http$Http$stringPart = _elm_lang$http$Http$StringPart;
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,16 @@
var _evancz$elm_markdown$Markdown$toHtmlWith = _evancz$elm_markdown$Native_Markdown.toHtml;
var _evancz$elm_markdown$Markdown$defaultOptions = {
githubFlavored: _elm_lang$core$Maybe$Just(
{tables: false, breaks: false}),
defaultHighlighting: _elm_lang$core$Maybe$Nothing,
sanitize: false,
smartypants: false
};
var _evancz$elm_markdown$Markdown$toHtml = F2(
function (attrs, string) {
return A3(_evancz$elm_markdown$Native_Markdown.toHtml, _evancz$elm_markdown$Markdown$defaultOptions, attrs, string);
});
var _evancz$elm_markdown$Markdown$Options = F4(
function (a, b, c, d) {
return {githubFlavored: a, defaultHighlighting: b, sanitize: c, smartypants: d};
});
Binary file not shown.
Binary file not shown.
@@ -1,73 +1,63 @@
var _user$project$SeatSaver$update = F2(
function (action, model) {
var _p0 = action;
var updateSeat = function (seatFromModel) {
return _elm_lang$core$Native_Utils.eq(seatFromModel.seatNo, _p0._0.seatNo) ? _elm_lang$core$Native_Utils.update(
seatFromModel,
{occupied: !seatFromModel.occupied}) : seatFromModel;
};
return {
ctor: '_Tuple2',
_0: A2(_elm_lang$core$List$map, updateSeat, model),
_1: _elm_lang$core$Platform_Cmd$none
};
});
var _user$project$SeatSaver$init = function () {
var seats = {
ctor: '::',
_0: {seatNo: 1, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 2, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 3, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 4, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 5, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 6, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 7, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 8, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 9, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 10, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 11, occupied: false},
_1: {
ctor: '::',
_0: {seatNo: 12, occupied: false},
_1: {ctor: '[]'}
}
}
}
}
}
}
}
}
}
if (_p0.ctor === 'Toggle') {
var updateSeat = function (seatFromModel) {
return _elm_lang$core$Native_Utils.eq(seatFromModel.seatNo, _p0._0.seatNo) ? _elm_lang$core$Native_Utils.update(
seatFromModel,
{occupied: !seatFromModel.occupied}) : seatFromModel;
};
return {
ctor: '_Tuple2',
_0: A2(_elm_lang$core$List$map, updateSeat, model),
_1: _elm_lang$core$Platform_Cmd$none
};
} else {
if (_p0._0.ctor === 'Ok') {
var newModel = _p0._0._0;
return {ctor: '_Tuple2', _0: newModel, _1: _elm_lang$core$Platform_Cmd$none};
} else {
return {ctor: '_Tuple2', _0: model, _1: _elm_lang$core$Platform_Cmd$none};
}
}
};
return {ctor: '_Tuple2', _0: seats, _1: _elm_lang$core$Platform_Cmd$none};
}();
});
var _user$project$SeatSaver$Seat = F2(
function (a, b) {
return {seatNo: a, occupied: b};
});
var _user$project$SeatSaver$decodeSeats = function () {
var seat = A3(
_elm_lang$core$Json_Decode$map2,
F2(
function (seatNo, occupied) {
return A2(_user$project$SeatSaver$Seat, seatNo, occupied);
}),
A2(_elm_lang$core$Json_Decode$field, 'seatNo', _elm_lang$core$Json_Decode$int),
A2(_elm_lang$core$Json_Decode$field, 'occupied', _elm_lang$core$Json_Decode$bool));
return A2(
_elm_lang$core$Json_Decode$at,
{
ctor: '::',
_0: 'data',
_1: {ctor: '[]'}
},
_elm_lang$core$Json_Decode$list(seat));
}();
var _user$project$SeatSaver$SetSeats = function (a) {
return {ctor: 'SetSeats', _0: a};
};
var _user$project$SeatSaver$fetchSeats = function () {
var url = 'http://localhost:4000/api/seats';
return A2(
_elm_lang$http$Http$send,
_user$project$SeatSaver$SetSeats,
A2(_elm_lang$http$Http$get, url, _user$project$SeatSaver$decodeSeats));
}();
var _user$project$SeatSaver$init = {
ctor: '_Tuple2',
_0: {ctor: '[]'},
_1: _user$project$SeatSaver$fetchSeats
};
var _user$project$SeatSaver$Toggle = function (a) {
return {ctor: 'Toggle', _0: a};
};
@@ -1,5 +1,7 @@
{
"elm-lang/virtual-dom": "2.0.4",
"evancz/elm-markdown": "3.0.1",
"elm-lang/html": "2.0.0",
"elm-lang/http": "1.0.0",
"elm-lang/core": "5.1.1"
}
@@ -0,0 +1 @@
elm-stuff
@@ -0,0 +1,30 @@
Copyright (c) 2016-present, Evan Czaplicki

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

* Neither the name of Evan Czaplicki nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,57 @@
# HTTP in Elm

Make HTTP requests in Elm.

```elm
import Http
import Json.Decode as Decode
-- GET A STRING
getWarAndPeace : Http.Request String
getWarAndPeace =
Http.getString "https://example.com/books/war-and-peace"
-- GET JSON
getMetadata : Http.Request Metadata
getMetadata =
Http.get "https://example.com/books/war-and-peace/metadata" decodeMetadata
type alias Metadata =
{ author : String
, pages : Int
}
decodeMetadata : Decode.Decoder Metadata
decodeMetadata =
Decode.map2 Metadata
(Decode.field "author" Decode.string)
(Decode.field "pages" Decode.int)
-- SEND REQUESTS
type Msg
= LoadMetadata (Result Http.Error Metadata)
send : Cmd Msg
send =
Http.send LoadMetadata getMetadata
```


## Examples

- GET requests - [demo and code](http://elm-lang.org/examples/http)
- Download progress - [demo](https://hirafuji.com.br/elm/http-progress-example/) and [code](https://gist.github.com/pablohirafuji/fa373d07c42016756d5bca28962008c4)


## Learn More

To understand how HTTP works in Elm, check out:

- [The HTTP example in the guide](https://guide.elm-lang.org/architecture/effects/http.html) to see a simple usage with some explanation.
- [The Elm Architecture](https://guide.elm-lang.org/architecture/) to understand how HTTP fits into Elm in a more complete way. This will explain concepts like `Cmd` and `Sub` that appear in this package.
@@ -0,0 +1,220 @@
[
{
"name": "Http.Progress",
"comment": " Track the progress of an HTTP request. This can be useful if you are\nrequesting a large amount of data and want to show the user a progress bar\nor something.\n\nHere is an example usage: [demo][] and [code][].\n\n[demo]: https://hirafuji.com.br/elm/http-progress-example/\n[code]: https://gist.github.com/pablohirafuji/fa373d07c42016756d5bca28962008c4\n\n**Note:** If you stop tracking progress, you cancel the request.\n\n# Progress\n@docs Progress, track\n\n",
"aliases": [],
"types": [
{
"name": "Progress",
"comment": " The progress of an HTTP request.\n\nYou start with `None`. As data starts to come in, you will see `Some`. The\n`bytesExpected` field will match the `Content-Length` header, indicating how\nlong the response body is in bytes (8-bits). The `bytes` field indicates how\nmany bytes have been loaded so far, so if you want progress as a percentage,\nyou would say:\n\n Some { bytes, bytesExpected } ->\n toFloat bytes / toFloat bytesExpected\n\nYou will end up with `Fail` or `Done` depending on the success of the request.\n",
"args": [
"data"
],
"cases": [
[
"None",
[]
],
[
"Some",
[
"{ bytes : Int, bytesExpected : Int }"
]
],
[
"Fail",
[
"Http.Error"
]
],
[
"Done",
[
"data"
]
]
]
}
],
"values": [
{
"name": "track",
"comment": " Create a subscription that tracks the progress of an HTTP request.\n\nSee it in action in this example: [demo][] and [code][].\n\n[demo]: https://hirafuji.com.br/elm/http-progress-example/\n[code]: https://gist.github.com/pablohirafuji/fa373d07c42016756d5bca28962008c4\n",
"type": "String -> (Http.Progress.Progress data -> msg) -> Http.Request data -> Platform.Sub.Sub msg"
}
],
"generated-with-elm-version": "0.18.0"
},
{
"name": "Http",
"comment": " Create and send HTTP requests.\n\n# Send Requests\n@docs Request, send, Error\n\n# GET\n@docs getString, get\n\n# POST\n@docs post\n\n# Custom Requests\n@docs request\n\n## Headers\n@docs Header, header\n\n## Request Bodies\n@docs Body, emptyBody, jsonBody, stringBody, multipartBody, Part, stringPart\n\n## Responses\n@docs Expect, expectString, expectJson, expectStringResponse, Response\n\n# Low-Level\n@docs encodeUri, decodeUri, toTask\n\n",
"aliases": [
{
"name": "Body",
"comment": " Represents the body of a `Request`.\n",
"args": [],
"type": "Http.Internal.Body"
},
{
"name": "Expect",
"comment": " Logic for interpreting a response body.\n",
"args": [
"a"
],
"type": "Http.Internal.Expect a"
},
{
"name": "Header",
"comment": " An HTTP header for configuring requests. See a bunch of common headers\n[here][].\n\n[here]: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields\n",
"args": [],
"type": "Http.Internal.Header"
},
{
"name": "Request",
"comment": " Describes an HTTP request.\n",
"args": [
"a"
],
"type": "Http.Internal.Request a"
},
{
"name": "Response",
"comment": " The response from a `Request`.\n",
"args": [
"body"
],
"type": "{ url : String , status : { code : Int, message : String } , headers : Dict.Dict String String , body : body }"
}
],
"types": [
{
"name": "Error",
"comment": " A `Request` can fail in a couple ways:\n\n - `BadUrl` means you did not provide a valid URL.\n - `Timeout` means it took too long to get a response.\n - `NetworkError` means the user turned off their wifi, went in a cave, etc.\n - `BadStatus` means you got a response back, but the [status code][sc]\n indicates failure.\n - `BadPayload` means you got a response back with a nice status code, but\n the body of the response was something unexpected. The `String` in this\n case is a debugging message that explains what went wrong with your JSON\n decoder or whatever.\n\n[sc]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html\n",
"args": [],
"cases": [
[
"BadUrl",
[
"String"
]
],
[
"Timeout",
[]
],
[
"NetworkError",
[]
],
[
"BadStatus",
[
"Http.Response String"
]
],
[
"BadPayload",
[
"String",
"Http.Response String"
]
]
]
},
{
"name": "Part",
"comment": " Contents of a multi-part body. Right now it only supports strings, but we\nwill support blobs and files when we get an API for them in Elm.\n",
"args": [],
"cases": []
}
],
"values": [
{
"name": "decodeUri",
"comment": " Use this to unescape query parameters. It converts things like `%2F` to\n`/`. It can fail in some cases. For example, there is no way to unescape `%`\nbecause it could never appear alone in a properly escaped string.\n\nIt works just like `decodeURIComponent` in JavaScript.\n",
"type": "String -> Maybe.Maybe String"
},
{
"name": "emptyBody",
"comment": " Create an empty body for your `Request`. This is useful for GET requests\nand POST requests where you are not sending any data.\n",
"type": "Http.Body"
},
{
"name": "encodeUri",
"comment": " Use this to escape query parameters. Converts characters like `/` to `%2F`\nso that it does not clash with normal URL\n\nIt work just like `encodeURIComponent` in JavaScript.\n",
"type": "String -> String"
},
{
"name": "expectJson",
"comment": " Expect the response body to be JSON. You provide a `Decoder` to turn that\nJSON into an Elm value. If the body cannot be parsed as JSON or if the JSON\ndoes not match the decoder, the request will resolve to a `BadPayload` error.\n",
"type": "Json.Decode.Decoder a -> Http.Expect a"
},
{
"name": "expectString",
"comment": " Expect the response body to be a `String`.\n",
"type": "Http.Expect String"
},
{
"name": "expectStringResponse",
"comment": " Maybe you want the whole `Response`: status code, headers, body, etc. This\nlets you get all of that information. From there you can use functions like\n`Json.Decode.decodeString` to interpret it as JSON or whatever else you want.\n",
"type": "(Http.Response String -> Result.Result String a) -> Http.Expect a"
},
{
"name": "get",
"comment": " Create a `GET` request and try to decode the response body from JSON to\nsome Elm value.\n\n import Http\n import Json.Decode exposing (list, string)\n\n getBooks : Http.Request (List String)\n getBooks =\n Http.get \"https://example.com/books\" (list string)\n\nYou can learn more about how JSON decoders work [here][] in the guide.\n\n[here]: https://guide.elm-lang.org/interop/json.html\n",
"type": "String -> Json.Decode.Decoder a -> Http.Request a"
},
{
"name": "getString",
"comment": " Create a `GET` request and interpret the response body as a `String`.\n\n import Http\n\n getWarAndPeace : Http.Request String\n getWarAndPeace =\n Http.getString \"https://example.com/books/war-and-peace\"\n",
"type": "String -> Http.Request String"
},
{
"name": "header",
"comment": " Create a `Header`.\n\n header \"If-Modified-Since\" \"Sat 29 Oct 1994 19:43:31 GMT\"\n header \"Max-Forwards\" \"10\"\n header \"X-Requested-With\" \"XMLHttpRequest\"\n\n**Note:** In the future, we may split this out into an `Http.Headers` module\nand provide helpers for cases that are common on the client-side. If this\nsounds nice to you, open an issue [here][] describing the helper you want and\nwhy you need it.\n\n[here]: https://github.com/elm-lang/http/issues\n",
"type": "String -> String -> Http.Header"
},
{
"name": "jsonBody",
"comment": " Put some JSON value in the body of your `Request`. This will automatically\nadd the `Content-Type: application/json` header.\n",
"type": "Json.Encode.Value -> Http.Body"
},
{
"name": "multipartBody",
"comment": " Create multi-part bodies for your `Request`, automatically adding the\n`Content-Type: multipart/form-data` header.\n",
"type": "List Http.Part -> Http.Body"
},
{
"name": "post",
"comment": " Create a `POST` request and try to decode the response body from JSON to\nan Elm value. For example, if we want to send a POST without any data in the\nrequest body, it would be like this:\n\n import Http\n import Json.Decode exposing (list, string)\n\n postBooks : Http.Request (List String)\n postBooks =\n Http.post \"https://example.com/books\" Http.emptyBody (list string)\n\nSee [`jsonBody`](#jsonBody) to learn how to have a more interesting request\nbody. And check out [this section][here] of the guide to learn more about\nJSON decoders.\n\n[here]: https://guide.elm-lang.org/interop/json.html\n\n",
"type": "String -> Http.Body -> Json.Decode.Decoder a -> Http.Request a"
},
{
"name": "request",
"comment": " Create a custom request. For example, a custom PUT request would look like\nthis:\n\n put : String -> Body -> Request ()\n put url body =\n request\n { method = \"PUT\"\n , headers = []\n , url = url\n , body = body\n , expect = expectStringResponse (\\_ -> Ok ())\n , timeout = Nothing\n , withCredentials = False\n }\n",
"type": "{ method : String , headers : List Http.Header , url : String , body : Http.Body , expect : Http.Expect a , timeout : Maybe.Maybe Time.Time , withCredentials : Bool } -> Http.Request a"
},
{
"name": "send",
"comment": " Send a `Request`. We could get the text of “War and Peace” like this:\n\n import Http\n\n type Msg = Click | NewBook (Result Http.Error String)\n\n update : Msg -> Model -> Model\n update msg model =\n case msg of\n Click ->\n ( model, getWarAndPeace )\n\n NewBook (Ok book) ->\n ...\n\n NewBook (Err _) ->\n ...\n\n getWarAndPeace : Cmd Msg\n getWarAndPeace =\n Http.send NewBook <|\n Http.getString \"https://example.com/books/war-and-peace.md\"\n",
"type": "(Result.Result Http.Error a -> msg) -> Http.Request a -> Platform.Cmd.Cmd msg"
},
{
"name": "stringBody",
"comment": " Put some string in the body of your `Request`. Defining `jsonBody` looks\nlike this:\n\n import Json.Encode as Encode\n\n jsonBody : Encode.Value -> Body\n jsonBody value =\n stringBody \"application/json\" (Encode.encode 0 value)\n\nNotice that the first argument is a [MIME type][mime] so we know to add\n`Content-Type: application/json` to our request headers. Make sure your\nMIME type matches your data. Some servers are strict about this!\n\n[mime]: https://en.wikipedia.org/wiki/Media_type\n",
"type": "String -> String -> Http.Body"
},
{
"name": "stringPart",
"comment": " A named chunk of string data.\n\n body =\n multipartBody\n [ stringPart \"user\" \"tom\"\n , stringPart \"payload\" \"42\"\n ]\n",
"type": "String -> String -> Http.Part"
},
{
"name": "toTask",
"comment": " Convert a `Request` into a `Task`. This is only really useful if you want\nto chain together a bunch of requests (or any other tasks) in a single command.\n",
"type": "Http.Request a -> Task.Task Http.Error a"
}
],
"generated-with-elm-version": "0.18.0"
}
]
@@ -0,0 +1,18 @@
{
"version": "1.0.0",
"summary": "Make HTTP requests (download progress, rate-limit, debounce, throttle)",
"repository": "https://github.com/elm-lang/http.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [
"Http",
"Http.Progress"
],
"native-modules": true,
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
@@ -0,0 +1,40 @@
## Custom Rate-Limiting Strategies

This package has `Http.RateLimit` which helps you rate-limit the HTTP requests you make. Instead of sending one request per keystroke, you filter it down because not all requests are important.

The `Http.RateLimit` module comes with a `debounce` strategy that covers the common case, but you may want to define a custom strategy with other characteristics. Maybe you want to send the first request. Maybe you want to send when the previous request is done instead of using timers. Etc.

If so, you can define a custom strategy with `Http.RateLimit.customStrategy`. For example, you would define `throttle` like this:

```elm
import Http.RateLimit as Limit
throttle : Time -> Limit.Strategy
throttle ms =
Limit.customStrategy <| \timeNow event state ->
case event of
Limit.New _ ->
-- wait after a new request
[ Limit.WakeUpIn ms ]
Limit.Done _ ->
-- we do not care when requests finish
[]
Limit.WakeUp ->
case state.next of
Nothing ->
-- do nothing if there is no pending request
[]
Just req ->
-- send if enough time has passed since the previous request
case state.prev of
Nothing ->
[ Limit.Send req.id ]
Just prev ->
if timeNow - prev.time >= ms then [ Limit.Send req.id ] else []
```

It would be nice to have some useful strategies defined in a separate package so folks can experiment and find names and implementations that work well for specific scenarios.

Large diffs are not rendered by default.

@@ -0,0 +1,45 @@
module Http.Internal exposing
( Request(..)
, RawRequest
, Expect
, Body(..)
, Header(..)
, map
)


import Native.Http
import Time exposing (Time)



type Request a = Request (RawRequest a)


type alias RawRequest a =
{ method : String
, headers : List Header
, url : String
, body : Body
, expect : Expect a
, timeout : Maybe Time
, withCredentials : Bool
}


type Expect a = Expect


type Body
= EmptyBody
| StringBody String String
| FormDataBody



type Header = Header String String


map : (a -> b) -> RawRequest a -> RawRequest b
map func request =
{ request | expect = Native.Http.mapExpect func request.expect }
@@ -0,0 +1,200 @@
effect module Http.Progress where { subscription = MySub } exposing
( Progress(..)
, track
)

{-| Track the progress of an HTTP request. This can be useful if you are
requesting a large amount of data and want to show the user a progress bar
or something.
Here is an example usage: [demo][] and [code][].
[demo]: https://hirafuji.com.br/elm/http-progress-example/
[code]: https://gist.github.com/pablohirafuji/fa373d07c42016756d5bca28962008c4
**Note:** If you stop tracking progress, you cancel the request.
# Progress
@docs Progress, track
-}


import Dict
import Http
import Http.Internal exposing ( Request(Request) )
import Task exposing (Task)
import Platform exposing (Router)
import Process



-- PROGRESS


{-| The progress of an HTTP request.
You start with `None`. As data starts to come in, you will see `Some`. The
`bytesExpected` field will match the `Content-Length` header, indicating how
long the response body is in bytes (8-bits). The `bytes` field indicates how
many bytes have been loaded so far, so if you want progress as a percentage,
you would say:
Some { bytes, bytesExpected } ->
toFloat bytes / toFloat bytesExpected
You will end up with `Fail` or `Done` depending on the success of the request.
-}
type Progress data
= None
| Some { bytes : Int, bytesExpected : Int}
| Fail Http.Error
| Done data



-- TRACK


{-| Create a subscription that tracks the progress of an HTTP request.
See it in action in this example: [demo][] and [code][].
[demo]: https://hirafuji.com.br/elm/http-progress-example/
[code]: https://gist.github.com/pablohirafuji/fa373d07c42016756d5bca28962008c4
-}
track : String -> (Progress data -> msg) -> Http.Request data -> Sub msg
track id toMessage (Request request) =
subscription <| Track id <|
{ request = Http.Internal.map (Done >> toMessage) request
, toProgress = Some >> toMessage
, toError = Fail >> toMessage
}


type alias TrackedRequest msg =
{ request : Http.Internal.RawRequest msg
, toProgress : { bytes : Int, bytesExpected : Int } -> msg
, toError : Http.Error -> msg
}


map : (a -> b) -> TrackedRequest a -> TrackedRequest b
map func { request, toProgress, toError } =
{ request = Http.Internal.map func request
, toProgress = toProgress >> func
, toError = toError >> func
}



-- SUBSCRIPTIONS


type MySub msg =
Track String (TrackedRequest msg)


subMap : (a -> b) -> MySub a -> MySub b
subMap func (Track id trackedRequest) =
Track id (map func trackedRequest)



-- EFFECT MANAGER


type alias State =
Dict.Dict String Process.Id


init : Task Never State
init =
Task.succeed Dict.empty



-- APP MESSAGES


onEffects : Platform.Router msg Never -> List (MySub msg) -> State -> Task Never State
onEffects router subs state =
let
subDict =
collectSubs subs

leftStep id process (dead, ongoing, new) =
( Process.kill process :: dead
, ongoing
, new
)

bothStep id process _ (dead, ongoing, new) =
( dead
, Dict.insert id process ongoing
, new
)

rightStep id trackedRequest (dead, ongoing, new) =
( dead
, ongoing
, (id, trackedRequest) :: new
)

(dead, ongoing, new) =
Dict.merge leftStep bothStep rightStep state subDict ([], Dict.empty, [])
in
Task.sequence dead
|> Task.andThen (\_ -> spawnRequests router new ongoing)


spawnRequests : Router msg Never -> List (String, TrackedRequest msg) -> State -> Task Never State
spawnRequests router trackedRequests state =
case trackedRequests of
[] ->
Task.succeed state

(id, trackedRequest) :: others ->
Process.spawn (toTask router trackedRequest)
|> Task.andThen (\process -> spawnRequests router others (Dict.insert id process state))


toTask : Router msg Never -> TrackedRequest msg -> Task Never ()
toTask router { request, toProgress, toError } =
Native.Http.toTask request (Just (Platform.sendToApp router << toProgress))
|> Task.andThen (Platform.sendToApp router)
|> Task.onError (Platform.sendToApp router << toError)



-- COLLECT SUBS AS DICT


type alias SubDict msg =
Dict.Dict String (TrackedRequest msg)


collectSubs : List (MySub msg) -> SubDict msg
collectSubs subs =
List.foldl addSub Dict.empty subs


addSub : MySub msg -> SubDict msg -> SubDict msg
addSub (Track id trackedRequest) subDict =
let
request =
trackedRequest.request

uid =
id ++ request.method ++ request.url
in
Dict.insert uid trackedRequest subDict



-- SELF MESSAGES


onSelfMsg : Platform.Router msg Never -> Never -> State -> Task Never State
onSelfMsg router _ state =
Task.succeed state
@@ -0,0 +1,238 @@
var _elm_lang$http$Native_Http = function() {


// ENCODING AND DECODING

function encodeUri(string)
{
return encodeURIComponent(string);
}

function decodeUri(string)
{
try
{
return _elm_lang$core$Maybe$Just(decodeURIComponent(string));
}
catch(e)
{
return _elm_lang$core$Maybe$Nothing;
}
}


// SEND REQUEST

function toTask(request, maybeProgress)
{
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback)
{
var xhr = new XMLHttpRequest();

configureProgress(xhr, maybeProgress);

xhr.addEventListener('error', function() {
callback(_elm_lang$core$Native_Scheduler.fail({ ctor: 'NetworkError' }));
});
xhr.addEventListener('timeout', function() {
callback(_elm_lang$core$Native_Scheduler.fail({ ctor: 'Timeout' }));
});
xhr.addEventListener('load', function() {
callback(handleResponse(xhr, request.expect.responseToResult));
});

try
{
xhr.open(request.method, request.url, true);
}
catch (e)
{
return callback(_elm_lang$core$Native_Scheduler.fail({ ctor: 'BadUrl', _0: request.url }));
}

configureRequest(xhr, request);
send(xhr, request.body);

return function() { xhr.abort(); };
});
}

function configureProgress(xhr, maybeProgress)
{
if (maybeProgress.ctor === 'Nothing')
{
return;
}

xhr.addEventListener('progress', function(event) {
if (!event.lengthComputable)
{
return;
}
_elm_lang$core$Native_Scheduler.rawSpawn(maybeProgress._0({
bytes: event.loaded,
bytesExpected: event.total
}));
});
}

function configureRequest(xhr, request)
{
function setHeader(pair)
{
xhr.setRequestHeader(pair._0, pair._1);
}

A2(_elm_lang$core$List$map, setHeader, request.headers);
xhr.responseType = request.expect.responseType;
xhr.withCredentials = request.withCredentials;

if (request.timeout.ctor === 'Just')
{
xhr.timeout = request.timeout._0;
}
}

function send(xhr, body)
{
switch (body.ctor)
{
case 'EmptyBody':
xhr.send();
return;

case 'StringBody':
xhr.setRequestHeader('Content-Type', body._0);
xhr.send(body._1);
return;

case 'FormDataBody':
xhr.send(body._0);
return;
}
}


// RESPONSES

function handleResponse(xhr, responseToResult)
{
var response = toResponse(xhr);

if (xhr.status < 200 || 300 <= xhr.status)
{
response.body = xhr.responseText;
return _elm_lang$core$Native_Scheduler.fail({
ctor: 'BadStatus',
_0: response
});
}

var result = responseToResult(response);

if (result.ctor === 'Ok')
{
return _elm_lang$core$Native_Scheduler.succeed(result._0);
}
else
{
response.body = xhr.responseText;
return _elm_lang$core$Native_Scheduler.fail({
ctor: 'BadPayload',
_0: result._0,
_1: response
});
}
}

function toResponse(xhr)
{
return {
status: { code: xhr.status, message: xhr.statusText },
headers: parseHeaders(xhr.getAllResponseHeaders()),
url: xhr.responseURL,
body: xhr.response
};
}

function parseHeaders(rawHeaders)
{
var headers = _elm_lang$core$Dict$empty;

if (!rawHeaders)
{
return headers;
}

var headerPairs = rawHeaders.split('\u000d\u000a');
for (var i = headerPairs.length; i--; )
{
var headerPair = headerPairs[i];
var index = headerPair.indexOf('\u003a\u0020');
if (index > 0)
{
var key = headerPair.substring(0, index);
var value = headerPair.substring(index + 2);

headers = A3(_elm_lang$core$Dict$update, key, function(oldValue) {
if (oldValue.ctor === 'Just')
{
return _elm_lang$core$Maybe$Just(value + ', ' + oldValue._0);
}
return _elm_lang$core$Maybe$Just(value);
}, headers);
}
}

return headers;
}


// EXPECTORS

function expectStringResponse(responseToResult)
{
return {
responseType: 'text',
responseToResult: responseToResult
};
}

function mapExpect(func, expect)
{
return {
responseType: expect.responseType,
responseToResult: function(response) {
var convertedResponse = expect.responseToResult(response);
return A2(_elm_lang$core$Result$map, func, convertedResponse);
}
};
}


// BODY

function multipart(parts)
{
var formData = new FormData();

while (parts.ctor !== '[]')
{
var part = parts._0;
formData.append(part._0, part._1);
parts = parts._1;
}

return { ctor: 'FormDataBody', _0: formData };
}

return {
toTask: F2(toTask),
expectStringResponse: expectStringResponse,
mapExpect: F2(mapExpect),
multipart: multipart,
encodeUri: encodeUri,
decodeUri: decodeUri
};

}();
@@ -0,0 +1 @@
elm-stuff
@@ -0,0 +1,30 @@
Copyright (c) 2014, Evan Czaplicki

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

* Neither the name of Evan Czaplicki nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,38 @@
# Markdown in Elm

This package is for markdown parsing and rendering. It is based on the [marked][] project
which focuses on speed.

[marked]: https://github.com/chjj/marked

## Basic Usage

```elm
content : Html msg
content =
Markdown.toHtml [class "content"] """
# Apple Pie Recipe
1. Invent the universe.
2. Bake an apple pie.
"""
```

**Warning:** Calling `Markdown.toHtml` parses the whole block, so try not to
call it for no reason. In the `content` example above we only have to parse
the text once, but if we put it in a function we may be doing a lot of
unnecessary parsing.


## Code Blocks

For highlighting any code blocks, the package relies on the
[highlight.js](https://highlightjs.org/) project. So if you want to
see highlighting of code blocks in the rendering result, you need to
make sure that your page/app binds a version of that library
(supporting the languages you want to handle) to `window.hljs` in
Javascript. [This is how package.elm-lang.org does
that.](https://github.com/elm-lang/package.elm-lang.org/blob/e0b7aa4282038475612722ff7a57195866f8645b/backend/ServeFile.hs#L54)

@@ -0,0 +1,33 @@
[
{
"name": "Markdown",
"comment": " A library for markdown parsing. This is just an Elm API built on top of the\n[marked](https://github.com/chjj/marked) project which focuses on speed.\n\n# Parsing Markdown\n@docs toHtml\n\n# Parsing with Custom Options\n@docs Options, defaultOptions, toHtmlWith\n",
"aliases": [
{
"name": "Options",
"comment": " Some parser options so you can tweak things for your particular case.\n\n * `githubFlavored` &mdash; overall reasonable improvements on the original\n markdown parser as described [here][gfm]. This includes stuff like [fenced\n code blocks][fenced]. There are some odd parts though, such as [tables][]\n and a setting to turn all newlines into newlines in the resulting output,\n so there are settings to turn those on or off based on your preference.\n\n * `defaultHighlighting` &mdash; a default language to use for code blocks that do\n not have a language tag. So setting this to `Just \"elm\"` will treat all\n unlabeled code blocks as Elm code. (This relies on [highlight.js][highlight]\n as explained in the README [here](../#code-blocks).)\n\n * `sanitize` &mdash; this determines if all HTML should be escaped. If you\n are parsing user markdown or user input can somehow reach the markdown\n parser, you should almost certainly turn on sanitation. If it is just you\n writing markdown, turning sanitation off is a nice way to do some HTML\n tricks if it is needed.\n\n * `smartypants` &mdash; This will automatically upgrade quotes to the\n prettier versions and turn dashes into [em dashes or en dashes][dash]\n\n\n[gfm]: https://help.github.com/articles/github-flavored-markdown/\n[fenced]: https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks\n[tables]: https://help.github.com/articles/github-flavored-markdown/#tables\n[highlight]: https://highlightjs.org/\n[dash]: http://en.wikipedia.org/wiki/Dash\n",
"args": [],
"type": "{ githubFlavored : Maybe.Maybe { tables : Bool, breaks : Bool } , defaultHighlighting : Maybe.Maybe String , sanitize : Bool , smartypants : Bool }"
}
],
"types": [],
"values": [
{
"name": "defaultOptions",
"comment": " The `Options` used by the `toElement` and `toHtml` functions.\n\n { githubFlavored = Just { tables = False, breaks = False }\n , defaultHighlighting = Nothing\n , sanitize = False\n , smartypants = False\n }\n",
"type": "Markdown.Options"
},
{
"name": "toHtml",
"comment": " Turn a markdown string into an HTML element, using the `defaultOptions`.\n\n recipe : Html msg\n recipe =\n Markdown.toHtml [class \"recipe\"] \"\"\"\n\n # Apple Pie Recipe\n\n First, invent the universe. Then bake an apple pie.\n\n \"\"\"\n",
"type": "List (Html.Attribute msg) -> String -> Html.Html msg"
},
{
"name": "toHtmlWith",
"comment": " Maybe you want to parse user input into markdown. To stop them from adding\n`<script>` tags, you can use modified parsing options.\n\n options : Options\n options =\n { defaultOptions | sanitize = True }\n\n toMarkdown : String -> Html\n toMarkdown userInput =\n Markdown.toHtmlWith options [] userInput\n",
"type": "Markdown.Options -> List (Html.Attribute msg) -> String -> Html.Html msg"
}
],
"generated-with-elm-version": "0.18.0"
}
]
@@ -0,0 +1,18 @@
{
"version": "3.0.1",
"summary": "Fast markdown parsing and rendering",
"repository": "https://github.com/evancz/elm-markdown.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [
"Markdown"
],
"native-modules": true,
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
@@ -0,0 +1,104 @@
module Markdown exposing
( toHtml
, Options, defaultOptions, toHtmlWith
)

{-| A library for markdown parsing. This is just an Elm API built on top of the
[marked](https://github.com/chjj/marked) project which focuses on speed.
# Parsing Markdown
@docs toHtml
# Parsing with Custom Options
@docs Options, defaultOptions, toHtmlWith
-}

import Html exposing (Html, Attribute)
import Native.Markdown


{-| Turn a markdown string into an HTML element, using the `defaultOptions`.
recipe : Html msg
recipe =
Markdown.toHtml [class "recipe"] """
# Apple Pie Recipe
First, invent the universe. Then bake an apple pie.
"""
-}
toHtml : List (Attribute msg) -> String -> Html msg
toHtml attrs string =
Native.Markdown.toHtml defaultOptions attrs string


{-| Some parser options so you can tweak things for your particular case.
* `githubFlavored` &mdash; overall reasonable improvements on the original
markdown parser as described [here][gfm]. This includes stuff like [fenced
code blocks][fenced]. There are some odd parts though, such as [tables][]
and a setting to turn all newlines into newlines in the resulting output,
so there are settings to turn those on or off based on your preference.
* `defaultHighlighting` &mdash; a default language to use for code blocks that do
not have a language tag. So setting this to `Just "elm"` will treat all
unlabeled code blocks as Elm code. (This relies on [highlight.js][highlight]
as explained in the README [here](../#code-blocks).)
* `sanitize` &mdash; this determines if all HTML should be escaped. If you
are parsing user markdown or user input can somehow reach the markdown
parser, you should almost certainly turn on sanitation. If it is just you
writing markdown, turning sanitation off is a nice way to do some HTML
tricks if it is needed.
* `smartypants` &mdash; This will automatically upgrade quotes to the
prettier versions and turn dashes into [em dashes or en dashes][dash]
[gfm]: https://help.github.com/articles/github-flavored-markdown/
[fenced]: https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks
[tables]: https://help.github.com/articles/github-flavored-markdown/#tables
[highlight]: https://highlightjs.org/
[dash]: http://en.wikipedia.org/wiki/Dash
-}
type alias Options =
{ githubFlavored : Maybe { tables : Bool, breaks : Bool }
, defaultHighlighting : Maybe String
, sanitize : Bool
, smartypants : Bool
}


{-| The `Options` used by the `toElement` and `toHtml` functions.
{ githubFlavored = Just { tables = False, breaks = False }
, defaultHighlighting = Nothing
, sanitize = False
, smartypants = False
}
-}
defaultOptions : Options
defaultOptions =
{ githubFlavored = Just { tables = False, breaks = False }
, defaultHighlighting = Nothing
, sanitize = False
, smartypants = False
}


{-| Maybe you want to parse user input into markdown. To stop them from adding
`<script>` tags, you can use modified parsing options.
options : Options
options =
{ defaultOptions | sanitize = True }
toMarkdown : String -> Html
toMarkdown userInput =
Markdown.toHtmlWith options [] userInput
-}
toHtmlWith : Options -> List (Attribute msg) -> String -> Html msg
toHtmlWith =
Native.Markdown.toHtml

Large diffs are not rendered by default.

@@ -0,0 +1,19 @@
defmodule LearningElm.Seat do
use LearningElm.Web, :model

schema "seats" do
field :seat_no, :integer
field :occupied, :boolean, default: false

timestamps()
end

@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:seat_no, :occupied])
|> validate_required([:seat_no, :occupied])
end
end
@@ -20,7 +20,9 @@ defmodule LearningElm.Router do
end

# Other scopes may use custom stacks.
# scope "/api", LearningElm do
# pipe_through :api
# end
scope "/api", LearningElm do
pipe_through :api

resources "/seats", SeatController, except: [:new, :edit]
end
end

Large diffs are not rendered by default.

@@ -0,0 +1,19 @@
defmodule LearningElm.ChangesetView do
use LearningElm.Web, :view

@doc """
Traverses and translates changeset errors.
See `Ecto.Changeset.traverse_errors/2` and
`LearningElm.ErrorHelpers.translate_error/1` for more details.
"""
def translate_errors(changeset) do
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
end

def render("error.json", %{changeset: changeset}) do
# When encoded, the changeset returns its errors
# as a JSON object. So we just pass it forward.
%{errors: translate_errors(changeset)}
end
end
@@ -0,0 +1,17 @@
defmodule LearningElm.SeatView do
use LearningElm.Web, :view

def render("index.json", %{seats: seats}) do
%{data: render_many(seats, LearningElm.SeatView, "seat.json")}
end

def render("show.json", %{seat: seat}) do
%{data: render_one(seat, LearningElm.SeatView, "seat.json")}
end

def render("seat.json", %{seat: seat}) do
%{id: seat.id,
seatNo: seat.seat_no,
occupied: seat.occupied}
end
end