Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions assets/templates/events_index.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
{% if has_articles %}
{% if has_upcoming_events %}
<section class="events-list">
<h2 class="text-3xl font-bold mb-8">開催予定のイベント</h2>
<div class="space-y-6">
{% for article in upcoming_events %}
<article class="event-item bg-white p-6 rounded-lg shadow-md border border-gray-200 hover:shadow-lg transition-shadow">
<h3 class="text-2xl font-bold">
<a href="{{ article.url }}" class="text-gray-900 hover:text-orange-500 no-underline">
{{ article.title }}
</a>
<p class="text-gray-500 text-sm">{{ article.date.year }}/{{ article.date.month }}/{{ article.date.day }}</p>
</h3>
</article>
{% endfor %}
</div>
</section>
{% endif %}

{% if has_past_events %}
<section class="events-list mt-12">
<h2 class="text-3xl font-bold mb-8">過去のイベント</h2>
<div class="space-y-6">
{% for article in articles %}
{% for article in past_events %}
<article class="event-item bg-white p-6 rounded-lg shadow-md border border-gray-200 hover:shadow-lg transition-shadow">
<h3 class="text-2xl font-bold">
<a href="{{ article.url }}" class="text-gray-900 hover:text-orange-500 no-underline">
Expand All @@ -14,11 +32,12 @@ <h3 class="text-2xl font-bold">
{% endfor %}
</div>
</section>
{% else %}
{% endif %}

{% if not has_upcoming_events and not has_past_events %}
<section class="events-list">
<p class="text-gray-500 text-center py-12">
現在、イベント情報はありません。
</p>
</section>
{% endif %}

2 changes: 2 additions & 0 deletions bin/dune
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
(public_name ocaml-jp-site)
(name main)
(libraries
core
core_unix.sys_unix
yocaml
yocaml_unix
yocaml_jingoo
Expand Down
100 changes: 90 additions & 10 deletions bin/main.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
open Core
open Yocaml

let into = Path.rel [ "www" ]
Expand All @@ -11,7 +12,9 @@ let create_css =
|> Action.Static.write_file Path.(into / "style.css")
;;

let track_binary = Sys.executable_name |> Yocaml.Path.from_string |> Pipeline.track_file
let track_binary =
Sys_unix.executable_name |> Yocaml.Path.from_string |> Pipeline.track_file
;;

let create_index =
let source = Path.rel [ "contents"; "index_main.html" ] in
Expand Down Expand Up @@ -44,7 +47,7 @@ let write_markdown source ~into =
Action.Static.write_file page_path pipeline
;;

let with_ext exts file = List.exists (fun ext -> Path.has_extension ext file) exts
let with_ext exts file = List.exists exts ~f:(fun ext -> Path.has_extension ext file)
let is_markdown = with_ext [ "md" ]

let is_not_index file =
Expand All @@ -66,13 +69,90 @@ let compute_event_link source =
source |> Path.move ~into |> Path.change_extension "html"
;;

module Event = struct
let entity_name = "Event"

type t =
{ title : string
; date : Archetype.Datetime.t
; upcoming : bool
}

let neutral =
Data.Validation.fail_with ~given:"null" "Cannot be null"
|> Result.map_error ~f:(fun error ->
Required.Validation_error { entity = entity_name; error })
;;

let validate =
let open Data.Validation in
record (fun fields ->
let+ title = required fields "title" string
and+ date = required fields "date" Archetype.Datetime.validate
and+ upcoming = optional_or fields ~default:false "upcoming" bool in
{ title; date; upcoming })
;;

let normalize { title; date; upcoming } =
Data.
[ "title", string title
; "date", Archetype.Datetime.normalize date
; "upcoming", bool upcoming
]
;;
end

module Events = struct
type t =
{ page : Archetype.Page.t
; events : (Path.t * Event.t) list
}

let with_page ~events ~page = { page; events }

let sort_by_date events =
List.sort
events
~compare:
(Comparable.lift
(Comparable.reverse Archetype.Datetime.compare)
~f:(fun (_, (e : Event.t)) -> e.date))
;;

let normalize_event (path, event) =
Data.record (("url", Data.string @@ Path.to_string path) :: Event.normalize event)
;;

let normalize { page; events } =
let upcoming, past =
List.partition_tf events ~f:(fun (_, (e : Event.t)) -> e.upcoming)
in
Archetype.Page.normalize page
@ Data.
[ "upcoming_events", list_of normalize_event upcoming
; "past_events", list_of normalize_event past
; "has_upcoming_events", bool (not (List.is_empty upcoming))
; "has_past_events", bool (not (List.is_empty past))
]
;;
end

let fetch_events =
let where file = is_markdown file && is_not_index file in
Archetype.Articles.fetch
let open Task in
Pipeline.fetch
~only:`Files
~where
~compute_link:compute_event_link
(module Yocaml_yaml)
~on:`Source
(fun file ->
let open Eff in
let url = compute_event_link file in
let+ metadata, _content =
Eff.read_file_with_metadata (module Yocaml_yaml) (module Event) ~on:`Source file
in
url, metadata)
(Path.rel [ "contents"; "events" ])
>>| Events.sort_by_date
;;

let create_events_index =
Expand All @@ -89,13 +169,13 @@ let create_events_index =
; assets / "templates" / "page.html"
; assets / "templates" / "layout.html"
]
and+ articles = fetch_events
and+ events = fetch_events
and+ metadata, content =
Yocaml_yaml.Pipeline.read_file_with_metadata (module Archetype.Page) source
in
let metadata = Archetype.Articles.with_page ~page:metadata ~articles in
let metadata = Events.with_page ~page:metadata ~events in
Yocaml_markdown.from_string_to_html content
|> apply_templates (module Archetype.Articles) ~metadata
|> apply_templates (module Events) ~metadata
in
Action.Static.write_file index_path pipeline
;;
Expand All @@ -119,12 +199,12 @@ let () =
let level = `Debug in
let target = into in
let port = 8080 in
match Sys.argv with
match Sys.get_argv () with
| [| _ |] | [| _; "build" |] -> Yocaml_unix.run ~level process
| [| _; "serve" |] -> Yocaml_unix.serve ~level ~target ~port process
| _ ->
let open Printf in
eprintf "Usage: %s [build|serve]\n" Sys.argv.(0);
eprintf "Usage: %s [build|serve]\n" (Sys.get_argv ()).(0);
eprintf " build Generate static site (default)\n";
eprintf " serve Start development server on port 8000\n";
exit 1
Expand Down
2 changes: 1 addition & 1 deletion contents/events/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
page_title: イベント一覧
---

OCaml.jp では、日本のOCamlコミュニティを盛り上げるために、様々なイベントを開催してきました。このページでは、過去に開催されたイベントの記録を掲載しています。
OCaml.jp では、日本のOCamlコミュニティを盛り上げるために、様々なイベントを開催しています。このページでは、開催予定のイベントと、過去に開催されたイベントの記録を掲載しています。

33 changes: 33 additions & 0 deletions contents/events/ocaml_meeting_2026.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
page_title: OCaml Meeting 2026 in Tokyo
title: OCaml Meeting 2026 in Tokyo
date: 2026-08-22
upcoming: true
---

OCaml Meeting は、OCaml ユーザーによる技術交流会です。[2013 年の名古屋開催](/events/ocaml_meeting_2013.html)以来 13 年ぶりの開催となります。OCaml や関数型プログラミングに興味のある方であれば、初心者からエキスパートまでどなたでも歓迎です。

### 日時・場所

* 日程:2026/8/22(土) 10:00 - 18:00
* 会場:DeNA Lounge(渋谷スクランブルスクエア 40F)
* 住所:東京都渋谷区渋谷 2-24-12
* 受付:当日 10:00 - 10:30 にオフィスフロア(17F)にて

### プログラム

* 発表(30 - 45 分):6 名(抽選、発表枠での参加申込締切は 2026/7/27)
* ライトニングトーク(10 - 20 分):6 名(抽選、LT 枠での参加申込締切は 2026/7/27)
* 詳細なタイムテーブルは後日公開予定です。

### 参加方法

参加申込は connpass からお願いします。参加費は無料です。

* 申込ページ:[https://ocamljp.connpass.com/event/391765/](https://ocamljp.connpass.com/event/391765/)
* 一般参加:50 名(先着)
* 発表枠・LT 枠:各 6 名(抽選)

### お問い合わせ

発表・LT に関するご相談などは [OCaml.jp Discord](https://discord.gg/qQTbny8KF4) の `#ocaml-meeting-2026-in-tokyo` チャンネルまでお寄せください。
2 changes: 2 additions & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
(depends
ocaml
dune
core
core_unix
yocaml
yocaml_unix
yocaml_omd
Expand Down
2 changes: 2 additions & 0 deletions ocaml-jp.opam
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ license: "MIT"
depends: [
"ocaml"
"dune" {>= "3.20"}
"core"
"core_unix"
"yocaml"
"yocaml_unix"
"yocaml_omd"
Expand Down
Loading