add init functionality

This commit is contained in:
Ryan Haskell-Glatz 2019-11-01 15:43:22 -05:00
parent f6999588e8
commit 1398e8ef7c
14 changed files with 8566 additions and 7 deletions

View File

@ -1,8 +1,23 @@
#!/usr/bin/env node #!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const cwd = process.cwd()
const utils = { const utils = {
all: fn => items => Promise.all(items.map(fn)), all: fn => items => Promise.all(items.map(fn)),
bold: str => '\033[1m' + str + '\033[0m' bold: str => '\033[1m' + str + '\033[0m',
cp (src, dest) {
const exists = fs.existsSync(src)
const stats = exists && fs.statSync(src)
if (stats.isDirectory()) {
fs.mkdirSync(dest)
fs.readdirSync(src).forEach(child =>
this.cp(path.join(src, child), path.join(dest, child))
)
} else {
fs.copyFileSync(src, dest)
}
}
} }
const main = ([ command, ...args ] = []) => { const main = ([ command, ...args ] = []) => {
@ -16,19 +31,20 @@ const help = _ => console.info(
commands: commands:
help prints this help screen help prints this help screen
build [options] <path> generates pages and routes build [options] <path> generates pages and routes
init [options] <path> scaffolds a new project at <path> init <path> scaffolds a new project at <path>
options: options:
--ui=<Html|Element> what your \`view\` returns (default: Html) --ui=<Html|Element> what your \`view\` returns (default: Html)
`) `)
const init = _ => const init = ([ relative = '.' ] = []) => {
console.info(`\nHey there! This still needs implementation... 😬\n`) const src = path.join(__dirname, 'initial-project')
const dest = path.join(cwd, relative)
if (fs.existsSync(dest)) fs.rmdirSync(dest)
utils.cp(src, dest)
}
const build = (args = []) => { const build = (args = []) => {
const fs = require('fs')
const path = require('path')
const cwd = process.cwd()
const { Elm } = require('./dist/elm.compiled.js') const { Elm } = require('./dist/elm.compiled.js')
const optionArgs = args.filter(a => a.startsWith('--')) const optionArgs = args.filter(a => a.startsWith('--'))

View File

@ -0,0 +1,20 @@
# your elm spa
> generated from `elm-spa init`!
## local development
1. `npm install`
1. `npm run dev`
## project structure
```elm
src/
Components/ -- reusable bits of UI
Layouts/ -- views that render pages
Pages/ -- where pages live
Global.elm -- info shared across pages
Main.elm -- entrypoint to app
```

View File

@ -0,0 +1,25 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.1",
"elm/core": "1.0.2",
"elm/html": "1.0.0",
"ryannhg/elm-spa": "1.0.0"
},
"indirect": {
"elm/json": "1.1.3",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.2"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>your-elm-spa</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
</head>
<body>
<script src="/dist/elm.compiled.js"></script>
<script>Elm.Main.init()</script>
</body>
</html>

1062
cli/initial-project/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
{
"name": "your-elm-spa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "npm run dev",
"build": "npm run elm-spa:build && npm run elm-build",
"dev": "npm run elm-spa:build && npm run elm-spa:watch & npm run elm-live",
"elm-build": "elm make src/Main.elm --output=dist/elm.compiled.js --optimize",
"elm-live": "elm-live src/Main.elm --start-page=index.html --pushstate --open -- --output=dist/elm.compiled.js --debug",
"elm-spa:build": "elm-spa build .",
"elm-spa:watch": "chokidar 'src/Pages' -c 'npm run elm-spa:build'"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@ryannhg/elm-spa": "1.0.1",
"chokidar-cli": "2.1.0",
"elm-live": "4.0.1"
}
}

View File

@ -0,0 +1,28 @@
module Components.Navbar exposing (view)
import Generated.Route as Route exposing (Route)
import Html exposing (..)
import Html.Attributes as Attr
view : Html msg
view =
header
[ Attr.class "navbar"
, Attr.style "margin-bottom" "32px"
]
(List.map viewLink
[ ( "homepage", Route.Index () )
, ( "docs", Route.Docs () )
]
)
viewLink : ( String, Route ) -> Html msg
viewLink ( label, route ) =
a
[ Attr.href (Route.toPath route)
, Attr.style "margin-right" "16px"
]
[ text label
]

View File

@ -0,0 +1,42 @@
module Global exposing
( Flags
, Model
, Msg(..)
, init
, subscriptions
, update
)
import Generated.Route exposing (Route)
type alias Flags =
()
type alias Model =
{}
type Msg
= NoOp
init : { navigate : Route -> Cmd msg } -> Flags -> ( Model, Cmd Msg, Cmd msg )
init _ _ =
( {}
, Cmd.none
, Cmd.none
)
update : { navigate : Route -> Cmd msg } -> Msg -> Model -> ( Model, Cmd Msg, Cmd msg )
update _ msg model =
case msg of
NoOp ->
( model, Cmd.none, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none

View File

@ -0,0 +1,24 @@
module Layouts.Main exposing (view)
import Components.Navbar
import Global
import Html exposing (..)
import Html.Attributes as Attr
view :
{ page : Html msg
, global : Global.Model
}
-> Html msg
view { page } =
div
[ Attr.class "layout"
, Attr.style "margin" "0 auto"
, Attr.style "max-width" "60ch"
, Attr.style "padding" "2rem 1rem"
, Attr.style "font-family" "sans-serif"
]
[ Components.Navbar.view
, page
]

View File

@ -0,0 +1,23 @@
module Main exposing (main)
import Application
import Generated.Pages as Pages
import Generated.Route as Route
import Global
main =
Application.create
{ ui = Application.usingHtml
, global =
{ init = Global.init
, update = Global.update
, subscriptions = Global.subscriptions
}
, routing =
{ routes = Route.routes
, toPath = Route.toPath
, notFound = Route.NotFound ()
}
, page = Pages.page
}

View File

@ -0,0 +1,52 @@
module Pages.Docs exposing
( Model
, Msg
, page
)
import Application.Page as Page
import Html exposing (..)
import Html.Attributes as Attr
type alias Model =
()
type alias Msg =
Never
page =
Page.static
{ title = "docs | elm-spa"
, view = view
}
view : Html msg
view =
div []
[ h1 [] [ text "Docs" ]
, h3 [] [ text "Want to learn more?" ]
, p [] [ text "An official documentation site (built with elm-spa) is coming soon!" ]
, p [] [ text "For now, feel free to check out:" ]
, ul []
(List.map viewBulletPoint
[ ( "the github repo", "https://github.com/ryannhg/elm-spa" )
, ( "the elm package docs", "https://package.elm-lang.org/packages/ryannhg/elm-spa/latest/" )
, ( "the cli docs", "https://github.com/ryannhg/elm-spa/tree/master/cli" )
]
)
]
viewBulletPoint : ( String, String ) -> Html msg
viewBulletPoint ( label, url ) =
li []
[ a
[ Attr.href url
, Attr.target "_blank"
]
[ text label ]
]

View File

@ -0,0 +1,35 @@
module Pages.Index exposing
( Model
, Msg
, page
)
import Application.Page as Page
import Html exposing (..)
type alias Model =
()
type alias Msg =
Never
page =
Page.static
{ title = "elm-spa"
, view = view
}
view =
div []
[ h1 [] [ text "Homepage" ]
, h3 [] [ text "Welcome to elm-spa!" ]
, p []
[ text "You should edit "
, code [] [ text "src/Pages/Index.elm" ]
, text " and see what happens!"
]
]

View File

@ -0,0 +1,28 @@
module Pages.NotFound exposing
( Model
, Msg
, page
)
import Application.Page as Page
import Html exposing (..)
import Html.Attributes as Attr
type alias Model =
()
type alias Msg =
Never
page =
Page.static
{ title = "not found | elm-spa"
, view =
div []
[ h1 [] [ text "Page not found!" ]
, p [] [ a [ Attr.href "/" ] [ text "Back to homepage" ] ]
]
}

7167
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff