Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

単にテンプレート的にhtmlを吐き出す

単純に関数に代入してhtmlを作ってみたがお世辞にも簡潔には書けなかった。。

import Data.List

main = putStrLn html

tag_doctype = "<!DOCTYPE html>\n"
tag_html txt = "\n<html>\n" ++ txt ++ "\n</html>\n"
tag_head txt = "\n<head>\n" ++ txt ++ "\n</head>\n"
tag_body txt = "\n<body>\n" ++ txt ++ "\n</body>\n"
tag_title txt = "\n<title>\n" ++ txt ++ "\n</title>\n"
tag_meta charset = "\n<meta charset=" ++ charset ++ ">\n"
tag_header txt = "\n<header class='header'>\n" ++ txt ++ "\n</header>\n"
tag_footer txt = "\n<footer class='footer'>\n" ++ txt ++ "\n</footer>\n"
tag_div cls txt = "\n<div class='"++cls++"'>\n" ++ txt ++ "\n</div>\n"
tag_main cls txt = "\n<main class='" ++cls++ "'>\n" ++ txt ++ "\n</main>\n"
tag_style txt = "\n<style type='text/css'>\n" ++ txt ++ "\n</style>\n"
tag_h1 cls txt = "\n<h1 class='" ++cls++ "'>\n" ++ txt ++ "\n</h1>\n"
tag_h2 cls txt = "\n<h2 class='" ++cls++ "'>\n" ++ txt ++ "\n</h2>\n"
tag_h3 cls txt = "\n<h3 class='" ++cls++ "'>\n" ++ txt ++ "\n</h3>\n"
tag_p cls txt = "\n<p class='" ++cls++ "'>\n" ++ txt ++ "\n</p>\n"
tag_time cls datetime txt = "\n<h3 class='" ++cls++ "' datetime='" ++datetime++ "'>\n" ++ txt ++ "\n</h3>\n"



tag_a cls href txt = "\n<a class='" ++cls++ "' href='" ++href++ "'>\n" ++ txt ++ "\n</a>\n"
tag_nav cls txt = "\n<nav class='" ++cls++ "'>\n" ++ txt ++ "\n</nav>\n"
tag_ul cls txt = "\n<ul class='" ++cls++ "'>\n" ++ txt ++ "\n</ul>\n"
tag_li cls txt = "\n<li class='" ++cls++ "'>\n" ++ txt ++ "\n</li>\n"
tag_img cls src alt =  "\n<img class='" ++cls++ "'" ++" src=" ++ src ++ " alt=" ++ alt ++ ">\n"
tag_link rel href = "\n<link rel=" ++ "'"++ rel ++"'" ++ " href=" ++ href ++ ">\n"
tag_span cls txt = "\n<span class='" ++cls++ "'>\n" ++ txt ++ "\n</span>\n"



hiragino = "'Hiragino Kaku Gothic ProN', Meiryo, sans-serif"
fontsize txt = "font-size:" ++ txt ++ ";"
font_weight txt = "font-weight:" ++ txt ++ ";"
font_family txt = "font-family:" ++ txt ++ ";"
box_sizing txt = "box-sizing:" ++ txt ++ ";"
text_decoration txt = "text-decoration:" ++ txt ++ ";"
padding txt = "padding:" ++ txt ++ ";"
color txt = "color:" ++ txt ++ ";"
background txt = "background:" ++ txt ++ ";"
background_color txt = "background-color:" ++ txt ++ ";"
box_shadow txt = "box-shadow:" ++ txt ++ ";"
width txt = "width:" ++ txt ++ ";"
height txt = "height:" ++ txt ++ ";"
margin txt = "margin:" ++ txt ++ ";"
margin_top txt = "margin-top:" ++ txt ++ ";"
margin_bottom txt = "margin-bottom:" ++ txt ++ ";"
opacity txt = "opacity:" ++ txt ++ ";"
float txt = "float:" ++ txt ++ ";"
top txt = "top:" ++ txt ++ ";"
left txt = "left:" ++ txt ++ ";"
position txt = "position:" ++ txt ++ ";"

overflow txt = "overflow:" ++ txt ++ ";"
text_indent txt = "text-indent:" ++ txt ++ ";"
text_align txt = "text-align:" ++ txt ++ ";"

white_space txt = "white-space:" ++ txt ++ ";"
display txt = "display:" ++ txt ++ ";"

line_height txt = "line-height:" ++ txt ++ ";"
border_radius txt = "border-radius:" ++ txt ++ ";"
letter_spacing txt = "letter-spacing:" ++ txt ++ ";"
transition txt = "transition:" ++ txt ++ ";"





csscls::String->[String]->String
csscls cls props = cls ++ " {\n" ++ (intercalate "\n" props) ++ "\n}\n"


tag_canvas txt = "<canvas id='canvas' width='200' height='200'>\n" ++ txt ++ "\n</canvas>"
tag_script txt = "<script>\n" ++ txt ++ "\n</script>"






-------------------- カスタマイズ部分

-- css設定
css::String
css = tag_style (intercalate "\n" [
  csscls ".header" [
                  "width:100%;",
                  padding "28px 0 10px",
                  background "url('./e.png') repeat-x",
                  box_shadow "0 0 10px 1px #e3e3e3"
    ],
  csscls ".wrapper" ["width:970px;","margin: 30px auto 40px;"],
  csscls ".main" ["display:block;","float:left;","width:80%;"],
  csscls ".sidemenu" ["float:right;","width:20%;"],
  csscls ".footer" ["width:100%;"],
  csscls ".clearfix::after" ["content:'';","display:block;","clear:both;"],
--  csscls ".header, .main, .sidemenu, .footer" ["border: 1px solid #aaa;","background-color:#ccc;"],
--  csscls ".header, .footer" ["height:100px;"],
--  csscls ".main, .sidemenu" ["height:500px;"],
  csscls "html" [fontsize "62.5%"],
  csscls "body" [color "#333", fontsize "1.2rem", font_family hiragino],
  csscls "*,*::before *::after" [box_sizing "border-box"],
  csscls "a:link a:visited a:hover a:active" [color "#d03c56",text_decoration "none"],
  csscls ".logo" [width "225px",
                  height "56px",
                  margin "0 auto", -- 中央寄せ
                  background "url('./logo.gif') no-repeat",
                  overflow "hidden", -- テキスト隠し
                  text_indent "100%", -- テキスト隠し
                  white_space "nowrap"
                  ],
  csscls ".logo a" [display "block", -- width,heightの指定をきかせるため(aはこれがinline)
                    width "100%",
                    height "100%"],
  csscls ".hidden" [display "none"],
  navicss,
  maincss
  ])

---------

html = commonMake "title" css header footer wrapper


-- 共通
commonMake title css header footer x = result where
  result = tag_doctype ++ html
  html = tag_html (head ++ body)
  head = tag_head (meta ++ title ++ (tag_link "stylesheet" "reset200802") ++ css)
  meta = tag_meta "'UTF-8'"
  title = tag_title "title"
  body = tag_body (header ++ x ++ footer)

-- ヘッダー
header::String
header = tag_header (logo ++ navi)

-- フッター
footer::String
footer = tag_footer ""

-- ラッパー
wrapper = tag_div "wrapper clearfix" (maincontents ++ (tag_div "sidemenu" ""))


-- ロゴ
logo = tag_h1 "logo" (tag_a "" "'/'" "Logo")

-- ナビ
navi = tag_nav "global-nav" list where
  list = tag_ul "" (intercalate "\n" contents) where
    contents = [tag_li "nav-item active" (tag_a "" "#" "HOME"),
                tag_li "nav-item" (tag_a "" "#" "ABOUT"),
                tag_li "nav-item" (tag_a "" "#" "NEWS"),
                tag_li "nav-item" (tag_a "" "#" "TOPICS"),
                tag_li "nav-item" (tag_a "" "#" "DOCS"),
                tag_li "nav-item" (tag_a "" "#" "BLOG")]

navicss = (intercalate "\n" [center, align_x, link, linkdynamics]) where
  center = csscls ".global-nav" [margin_top "15px",
                                 text_align "center" -- 子も中央寄せになる
                        ]
  align_x = csscls ".global-nav .nav-item" [
            display "inline-block", -- 横に並ぶ
            margin "0 10px"
            -- 高さしていいてないのでアイテムの高さはaによる
          ]
  link = csscls ".global-nav .nav-item a" [
            display "inline-block", -- 幅と高さ指定の有効化
            width "100px",
            height "30px",
            line_height "30px", -- 行の高さをheightと同じにして縦方向の中央よせ
            text_align "center", -- 横方向の中央よせ
            border_radius "8px",
            color "#666",
            fontsize "1.3rem",
            letter_spacing "1px", -- 文字間隔
            transition "0.15s"
          ]
  linkdynamics = csscls ".global-nav .nav-item.active a, .global-nav .nav-item a:hover" [
    background_color "#d03c56",
    color "#fff"
    ]


-- メイン
maincontents = tag_main "main" (hot ++ news ++ articles) where
  hot = title ++ body where
    title = tag_h2 "hidden" "HOT TOPIC"
    body = hottopic
  news = title ++ body where
    title = tag_h2 "" "NEWS"
    body = tag_div "news" newstopic
  articles = title ++ body where
    title = tag_h2 "hidden" "ARTICLES"
    body = tag_div "articles" "内容"

-- 子がflowなので親にclearfix付与
hottopic = tag_a "hot-topic clearfix" "#" (intercalate "\n" [image,div]) where
  image = tag_img "image" "./logo.gif" "画像"
  div = tag_div "content" content where
    content = (intercalate "\n" [title,desc,time]) where
      title = tag_h3 "title" "実務で使えるHTML/CSS<br>モダンコーディングTIPS"
      desc = tag_p "desc" "Webフロントエンドの進化の勢いは留まるところをしりません。"
      time = tag_time "date" "2017-06-02" "2017.06.02"

maincss = (intercalate "\n" [hottpiccss])

hottpiccss = (intercalate "\n" [common, hover, image, content]) where
  common = csscls ".hot-topic" [
    display "block",
    height "300px",
    margin_bottom "30px",
    box_shadow "0 6px 4px -4px rgba(0,0,0,0.15)",
    transition "opacity 0.15s"
    ]
  hover = csscls ".hot-topic:hover" [
    opacity "0.85"
    ]
  image = csscls ".hot-topic .image" [
    float "left",
    width "50%",
    height "100%"
    ]
  content = (intercalate "\n" [base, title, desc, date]) where
    base = csscls ".hot-topic .content" [
      float "left",
      width "50%",
      height "100%",
      padding "25px 0",
      background_color "#2d3d54",
      position "relative", -- 子は相対座標
      line_height "1.6" -- フォントサイズ✕1.6
      ]
    title = csscls ".hot-topic .title" [
      margin_bottom "15px",
      color "#fff",
      font_weight "normal",
      fontsize "2.0rem"
      ]
    desc = csscls ".hot-topic .desc" [
      color "#ddc"
      ]
    date = csscls ".hot-topic .date" [
      position "absolute",
      top "0px",
      left "0px",
      width "140px",
      padding "4px",
      background_color "#fff",
      color "#2d3d54",
      letter_spacing "1px",
      font_weight "bold",
      fontsize "1.1rem",
      line_height "1"
      ]

-- news
newstopic = tag_ul "scroll-list" items where
  items = tag_li "scroll-item" (tag_a "" "#" (intercalate "\n" [
    newslist "2017-06-01" "2017.06.01 WED" "TOPIC" "CSSでここまでできる!?",
    newslist "2017-06-02" "2017.06.02 WED" "TOPIC" "CSSでここまでできた!?",
    newslist "2017-06-03" "2017.06.03 WED" "TOPIC" "CSSでここまでできます!?"
    ]))

newslist datetime datetimestr categorystr titlestr = tag_li "scroll-item" (tag_a "" "#" (intercalate "\n" [time, category, title])) where
  time = tag_time "date" datetime datetimestr
  category = tag_span "category" categorystr
  title = tag_span "title" titlestr

htmlを吐き出してみる。

データ型と型クラスを使って少しまとめてみた。
同じようなコードを書かなくてはいけなくて面倒に感じる。
良い方法はないのだろうか。

import Data.List
main = print (tag_doctype ++ html)

tag_doctype = "<!DOCTYPE html>"

html = string (HTML [header,body])
header = HeadTag (HEAD "OK!")
body = BodyTag (BODY (htmlbody ++ scriptpart))

htmlbody = foldr (++) "" [tag_p "hello", tag_div (tag_canvas ""), string (A "https://www.yahoo.co.jp/" "Link") ]
scriptpart = tag_script scriptlist


class TransString a where
  string::a -> String
  stringjoin::[a] -> String
  stringjoin list = intercalate "" (map string list)



data Anchor = A { aURL::String, aLabel::String}
instance TransString Anchor where
  string (A { aURL=u, aLabel=l}) = (tagatt "a" (attr "href" (qua u)) l)

-- 色々なタグをタグでまとめた。
data TAG = HeadTag HEADERTAG
          |BodyTag BODYTAG
          |TitleTag TITLETAG

instance TransString TAG where
  string (HeadTag tag) = string tag
  string (BodyTag tag) = string tag
  string (HeadTag tag) = string tag

data HTMLTAG = HTML { htmlText::[TAG]}
instance TransString HTMLTAG where
  string (HTML { htmlText=tags}) =  tag "html" (stringjoin tags)

data HEADERTAG = HEAD { headText::String}
instance TransString HEADERTAG where
  string (HEAD { headText=txt}) = tag "head" txt

data BODYTAG = BODY { bodyText::String}
instance TransString BODYTAG where
  string (BODY { bodyText=txt}) = tag "body" txt

data TITLETAG = TITLE { titleText::String}
instance TransString TITLETAG where
  string (TITLE { titleText=txt}) = tag "title" txt

tag name txt = "<"++name++">" ++ txt ++ "</"++name++">"

attr::String -> String -> String
attr name txt = name ++ "=" ++ txt
tagatt::String -> String -> String->String
tagatt name att txt = "<" ++ name ++ " " ++ att ++ ">" ++ txt ++ "</"++name++">"

qua::String->String
qua txt = "'" ++ txt ++ "'"

trycode::(TransString a) => a -> String
trycode x = string x

tag_div txt = "<div>" ++ txt ++ "</div>"
tag_canvas txt = "<canvas id='canvas' width='200' height='200'>" ++ txt ++ "</canvas>"
tag_p txt = "<p>" ++ txt ++ "</p>"
tag_script txt = "<script>" ++ txt ++ "</script>"

assign v e = v ++ " = " ++ e
variable v = "var " ++ v
action target message = " " ++ target ++ "." ++ message
func name v = name ++ "(" ++ v ++")"
quo el = "'" ++ el ++  "'"
getElement el= action "document" (func "getElementById" (quo el))
jsfunc funcname input block = "function " ++ funcname ++ "(" ++ input  ++ ")" ++ block

canvas = "canvas"
context = "context"
sc1 = assign (variable canvas) (getElement canvas)
sc2 = assign (variable context)  (action canvas (func "getContext" (quo "2d")))
sc3 = assign (variable "cx") "100"
sc4 = assign (variable "cy") "100"

sc5 = action context (func "beginPath" "")
sc6 = assign "context.strokeStyle" "'#ff0000'"
sc7 = action context (func "arc" "120, 80, 70, 0, Math.PI*2, false")
sc8 = action context (func "stroke" "")

--jsfunc "drawFillRect" "cx,cy,w,h" (action context (func "fillRect" "cx-w/2, cy-h/2, w, h"))

-- sc9 = "drawFillRect(10,10,40,40)"

scriptlist = intercalate ";" [sc1,sc2,sc3,sc4,sc5,sc6,sc7,sc8]

お絵かき

haskellでお絵かきをするhtmlのコードを無理やり吐き出させてみた。もっとスマートにやれるはず。。

import Data.List
main = print tag_doctype


tag_doctype = "<!DOCTYPE html>" ++ html
html = tag_html (tag_header (tag_title "OK!") ++ tag_body (tag_p "hello")  ++ tag_div (tag_canvas "") ++ tag_script scriptlist)

tag_html txt = "<html>" ++ txt ++ "</html>"
tag_header txt = "<head>" ++ txt ++ "</head>"
tag_body txt = "<body>" ++ txt ++ "</body>"
tag_title txt = "<title>" ++ txt ++ "</title>"

tag_div txt = "<div>" ++ txt ++ "</div>"
tag_canvas txt = "<canvas id='canvas' width='200' height='200'>" ++ txt ++ "</canvas>"
tag_p txt = "<p>" ++ txt ++ "</p>"
tag_script txt = "<script>" ++ txt ++ "</script>"

assign v e = v ++ " = " ++ e
variable v = "var " ++ v
action target message = " " ++ target ++ "." ++ message
func name v = name ++ "(" ++ v ++")"
quo el = "'" ++ el ++  "'"
getElement el= action "document" (func "getElementById" (quo el))
jsfunc funcname input block = "function " ++ funcname ++ "(" ++ input  ++ ")" ++ block

canvas = "canvas"
context = "context"
sc1 = assign (variable canvas) (getElement canvas)
sc2 = assign (variable context)  (action canvas (func "getContext" (quo "2d")))
sc3 = assign (variable "cx") "100"
sc4 = assign (variable "cy") "100"

sc5 = action context (func "beginPath" "")
sc6 = assign "context.strokeStyle" "'#ff0000'"
sc7 = action context (func "arc" "120, 80, 70, 0, Math.PI*2, false")
sc8 = action context (func "stroke" "")

--jsfunc "drawFillRect" "cx,cy,w,h" (action context (func "fillRect" "cx-w/2, cy-h/2, w, h"))

-- sc9 = "drawFillRect(10,10,40,40)"

scriptlist = intercalate ";" [sc1,sc2,sc3,sc4,sc5,sc6,sc7,sc8]

URLSessionConfigurationのメモ

URLSessionConfigurationのメモ

こちらに良い記事があった。
qiita.com




とりあえずメソッド一覧。あとから説明を追記する形で。

open class URLSessionConfiguration : NSObject, NSCopying {
    
// デフォルト
    open class var `default`: URLSessionConfiguration { get }

// 一時的
    open class var ephemeral: URLSessionConfiguration { get }


// バックグラウンド    
    @available(iOS 8.0, *)
    open class func background(withIdentifier identifier: String) -> URLSessionConfiguration

// backgroundクラスメソッドで作ったときのみ
    open var identifier: String? { get }

// キャッシュポリシー
    open var requestCachePolicy: NSURLRequest.CachePolicy

// リクエストに対するタイムアウト時間    
    open var timeoutIntervalForRequest: TimeInterval

// リソースに対するタイム時間
    open var timeoutIntervalForResource: TimeInterval

// ネットワークのサービスタイプ    
/*
    public enum NetworkServiceType : UInt {
        
        case `default` // Standard internet traffic

        case voip // Voice over IP control traffic

        case video // Video traffic

        case background // Background traffic

        case voice // Voice data

        @available(iOS 10.0, *)
        case networkServiceTypeCallSignaling // Call Signaling
    }
*/
    open var networkServiceType: NSURLRequest.NetworkServiceType

// 電話回線でのアクセスを許すか    
    open var allowsCellularAccess: Bool


//  状況により通信処理の優先度を下げてよいか
    @available(iOS 7.0, *)
    open var isDiscretionary: Bool

//     
    @available(iOS 8.0, *)
    open var sharedContainerIdentifier: String?

//     
    @available(iOS 7.0, *)
    open var sessionSendsLaunchEvents: Bool

//     
    open var connectionProxyDictionary: [AnyHashable : Any]?

//    
    open var tlsMinimumSupportedProtocol: SSLProtocol

//    
    open var tlsMaximumSupportedProtocol: SSLProtocol

//    
    open var httpShouldUsePipelining: Bool

//    
    open var httpShouldSetCookies: Bool

//    
    open var httpCookieAcceptPolicy: HTTPCookie.AcceptPolicy

 // ヘッダー  
    open var httpAdditionalHeaders: [AnyHashable : Any]?

 // ホストあたりの最大接続数   
    open var httpMaximumConnectionsPerHost: Int

// クッキー    
    open var httpCookieStorage: HTTPCookieStorage?

//    
    open var urlCredentialStorage: URLCredentialStorage?

// URLキャッシュ    
    open var urlCache: URLCache?

//    
    @available(iOS 9.0, *)
    open var shouldUseExtendedBackgroundIdleMode: Bool

//    
    open var protocolClasses: [Swift.AnyClass]?
}
extension URLSession {

canvasのサンプル

html5canvasで線を描く。

f:id:KatagiriSo:20170522181810p:plain

<!DOCTYPE html>
<head>
   <title>HTML5 canvas</title>
</head>
<body>
  <div align="center">
     <h1>sample</h1>
   </div>


<div align="center">
   <canvas id="canvas" width="200" height="200" >
      <p>error</p>
   </canvas>
 </div>

   <script>
   var example = document.getElementById('canvas');
   var context = example.getContext('2d');

   var cx = 100
   var cy = 100

   function drawFillRect(cx,cy,w,h) {
     context.fillRect(cx-w/2, cy-h/2, w, h);
   }

   context.fillStyle = "#ff8000";
   drawFillRect(cx,cy,100,100)
   context.fillStyle = "#EEEEEE";
   drawFillRect(cx,cy,40,40)


   context.beginPath();
   context.moveTo(10, 10);
   context.quadraticCurveTo(50, 90, 90, 10);//(seigyo, endpoint)
   context.stroke();


   var sx=30;
   var sy=30;
   var w=50;
   var corner = 40;

function drawRounddedCornerRect(sx,sy,w,corner) {
  context.beginPath();
  context.moveTo(sx+corner, sy);
  // top
  context.lineTo(sx + w,sy);
  context.quadraticCurveTo(sx+w+corner,sy,sx+w+corner,sy+corner);
  // right
  context.lineTo(sx+w+corner,sy+w);
  context.quadraticCurveTo(sx+w+corner,sy+w+corner,sx+w,sy+w+corner);

  //  bottom
  context.lineTo(sx+corner,sy+w+corner);
  context.quadraticCurveTo(sx,sy+w+corner,sx,sy+w);

 // left 
 context.lineTo(sx,sy+corner);
 context.quadraticCurveTo(sx,sy,sx+corner,sy);
  context.stroke();
}

  drawRounddedCornerRect(30,30,50,20)
  drawRounddedCornerRect(100,30,50,30)
  context.fill()


function drawBezier(sx,sy,c1x,c1y,c2x,c2y,ex,ey) {
  context.beginPath();
  context.moveTo(sx, sy);
  context.bezierCurveTo(c1x, c1y, c2x, c2y, ex, ey);
  context.stroke();
}

drawBezier(20,100,50,20,150,150,200,100)

context.beginPath();
context.strokeStyle='#ff0000';
context.arc(120, 80, 70, 0, Math.PI*2, false);
context.stroke();


   </script>

</body>
</html>

円を描く

extension CGRect {
    init(_ center:CGPoint, _ size:CGSize) {
        self.origin = CGPoint(x:center.x - size.width/2, y:center.y - size.height/2)
        self.size = size
    }
}

extension CGPoint {
    init(_ x:CGFloat, _ y:CGFloat) {
        self.x = x
        self.y = y
    }
}

extension CGSize {
    init(_ width:CGFloat, _ height:CGFloat) {
        self.width = width
        self.height = height
    }
}

class RDView:UIView {
    
    func drawCircle(context:CGContext) {
        context.setLineWidth(20)
        context.strokeEllipse(in: CGRect(CGPoint(100,100), CGSize(100,100)))
        context.setFillColor(red: 1.0, green: 1.0, blue: 0.3, alpha: 0.3)
        context.setStrokeColor(red: 1.0, green: 0.3, blue: 0.5, alpha: 0.3)
        context.strokeEllipse(in: CGRect(x: 100, y: 100, width: 100, height: 100))
        context.fillEllipse(in: CGRect(x:120, y:120, width:60, height:60))
    }
    
    override func draw(_ rect: CGRect) {
        // Drawing code
        let p = UIGraphicsGetCurrentContext()
        drawCircle(context: p!)
    }
}

上のextensionは簡便のため。

エレメント

レイアウトにはめ込んで使える。Templete/Elementフォルダにいれておき、

 <?=this->element("hoge") ?>

で読み込める。
値をわたしたければ

 <?=this->element("hoge", ['x'=>10,'y'=>5]) ?>

のように渡す。

色々部品化しておくと良いようだ。

レイアウト

使用するスタイルシートwebroot/css/cake.hello.cssを用意する。

body {
  background: #eee;
  color: #999;
  margin: 10px 8px
}

#header {
  font-size: 18pt;
  font-weight: bold;
  margin: 10px;
}

#content {
  background: #fff;
  color: #999;
  padding: 10px 25px 30px 25px;
  font-size: 14pt;
}

#footer {
  text-align: right;
  font-size: 12pt;
  margin: 10pt;
}

h1 {
  color: #aaa;
  font-size: 24pt;
  margin: 20pt 0pt 50pt 0pt;
}


cssを利用するレイアウトsrc/Template/Layout/hello.ctpファイルを用意する。

<!DOCTYPE html>
<html>
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <?= $this->fetch('title') ?>
    </title>
    <?= $this->Html->meta('icon') ?>

    <?= $this->Html->css('cake.hello.css') ?>

    <?= $this->fetch('meta') ?>
    <?= $this->fetch('css') ?>
    <?= $this->fetch('script') ?>
</head>

fetchでコントローラの変数を取ってきている。

<body>

<div id="container">
  <div id="header">header</div>

  <div id="content">
      <?=$this->fetch('content') ?>
  </div>

  <div id="footer">footer</div>

</body>
</html>


ここではcake.hello.cssを読み込んでいるが、javascriptも読み込みたい場合、
webroot/js/cake.hello/jsなどというファイルをつくり

    <?= $this->Html->script('cake.hello.js') ?>

を追加してやれば良い。


コントローラでレイアウトを指定する。

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = true;
    public function index() {
      $this->ViewBuilder()->layout('Hello');
    }
  }
?>

テンプレート

src/Template/Hello/index.ctpを作ってテンプレートを以下のように用意

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta http-equiv="content-type" content="text/html;
  charset=UTF-8">
  <title>Hello Page</title>
</head>

<body>
    <h1>midashi</h1>
    <p> hello hello </p>
</body>
</html>


コントローラ側でautoRenderをtrueにしてテンプレートを読み込む。

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = true;
    public function index() {
      $this->viewBuilder()->autoLayout(false);
    }
  }
?>


自動レイアウト(autoLayout)はなしにした。
テンプレート名を変えればその名前のアクションに適用される。

自動レイアウトを使用する場合はテンプレートは

    <h1>midashi</h1>
    <p> hello hello </p>

のみで良く。コントローラの方は $this->viewBuilder()->autoLayout(false);の行を削る。
これでデフォルトのレイアウト(src/Template/Layout/default.ctp)が適応される。

フォワードとリダイレクト

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = false;
    public function index() {
      echo "hello, world!!";
    }
    public function other() {
      echo "hello, other world!!";
    }

    public function forw() {
      $this->setAction(other);
    }

    public function red() {
      $this->redirect("/hello/other");
    }

  }
?>

フォワードはアクションを指定。サーバ内で閉じる。
リダイレクトはアドレスを指定、ブラウザにページ移動を依頼する。

Hello World

/helloにアクセス

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = false;
    public function index() {
      echo "hello world!!";
    }
  }
?>

/hello/otherにアクセス

<?php
  namespace App\Controller;

  class HelloController extends AppController {
    public $name = "Hello";
    public $autoRender = false;
    public function index() {
      echo "hello, world!!";
    }
    public function other() {
      echo "hello, other world!!";
    }
  }
?>

otherはotherアクションと呼ばれる。

プロトコルMisc

CustomStringConvertible description オブジェクトの文字表示 print
CustomDebugStringConvertible debugDescription オブジェクトの文字表示 debugPrint
LosslessStringConvertible 文字列からそのままオブジェクト構築できる
TextOutputStream  write(_ string: String)
TextOutputStreamable writeの拡張 write(to target: inout Target)
Hashable ハッシュ。ハッシュが違えば違う。ハッシュが同じでもおなじとは限らない。
Comparable 比較
Equatable 同じ
BitwiseOperations ビット計算できる
AnyObject 任意のオブジェクト
Error エラー
OptionSet ビットでつかっている。SetAlgebra, RawRepresentable。使うと便利かも?



AnyHashable構造体

任意のHashableなものなら受け入れる引数等を作りたいときにつかう。いわゆるtype-erased。

標準入力から一行受け取る。trueはその一行は標準入力から切り出すかを示す。

public func readLine(strippingNewline: Bool = default) -> String?

コマンドライン

public enum CommandLine {
    public static var argc: Int32 { get }
// argvの値
    public static var unsafeArgv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> { get }
// swift用に変換される?のか?
    public static var arguments: [String]
}

Unmanaged構造体

自分でメモリ管理するもの

強参照のチェック

isKnownUniquelyReferenced
一個だけから強参照されているかを見る。weakに複数参照されていてもOK。
blog.stablekernel.com