fjktkm
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 知能プログラミング演習 II Grep9 ## 1. グループ グループ 06 グループメンバー - 33114074 高橋健人 - 33114095 西村光太郎 - 33114113 藤岡拓夢 - 33114141 渡邊修平 ## 2. 自己採点 自己採点は S である. 自己採点の理由は以下の通りである. - 独創的なアイデアを提案したから - 新規性のあるシステムを開発したから - 実用的なシステムを開発したから ## 3. 実装したシステムの説明 ### 3.1. システムの開発背景 名古屋工業大学の情報工学科の 1 年次には,「理系基礎演習」という講義がある. この講義は,Excel を用いたデータ分析を題材にグループワークやプレゼンを行い,情報工学科の学生としての基礎的なスキルを身につけることを目的としている. 担当の船瀬先生の人柄も相まって,理系基礎演習は情報工学科の学生にとって印象深い講義となっている. 情報工学科の学生にとって,理系基礎演習はまさに心のバイブル的な存在であると言えるだろう. プレゼンでは,スライドに対して船瀬先生によるダメだしが行われる. ダメ出しは,学生はスライドの改善点を学ぶための貴重な教育機会となっている. その一方で,ダメ出しは学生にとって過度な負担となっている側面がある. ダメ出しを取り巻く状況を整理すると,以下のようになる. - 発表者の立場 : ダメだしされたくない - 聞き手の立場 : ダメ出しをストレスに感じる - 先生の立場 : ダメ出しを自動化したい このような状況を踏まえて,船瀬先生の代わりにスライドへのダメ出しを行うシステムを開発することにした. ### 3.2. funase-lint の概要 作成したシステムは,Power Point 用のリンター `funase-lint` である. リンターとは,プログラムのソースコードに対して,構文やスタイルなどの問題を指摘するツールである. Power Point のファイル形式である pptx は,XML を ZIP で圧縮したものであるため,これを解凍して XML を解析することによりスライドの静的解析を行うという仕組みになっている. ルールは過去の理系基礎演習の Moodle のページから集めた. `funase-lint` は,Java で開発したコマンドラインツールである. 開発にあたっては,`picocli` というライブラリを利用し,様々なコマンドラインオプションを実装した. また,バージョン管理ツール Git の `.gitignore` を模した `.funaseignore` による無視ファイルの指定機能を実装した. JavaScript のリンター `ESLint` の `.eslintrc.json` を模した `.funaselintrc.json` によるカスタマイズ機能も実装した. 作成した funase-lint は以下の GitHub のページで公開している. https://github.com/funamusix/funase-lint ### 3.3. 作成したルール ルールは理系基礎演習の Moodle ページを参考に作成した. 作成したルールの一覧は以下の通りである. - TextFontRule - SlideTitleFontSizeRule - SlideThemeRule - SlideAspectRule - PunctuationMarkRule - AmbiguousWordRule - FontMinimumRule - QuestionMarkRule - CTRRule - FontSizeRule ### 3.3.1 TextFontRule テキストのフォントテーマが船瀬先生の好まない游書体か MS ゴシックのとき,見栄えの良いフォントを使うように警告する. ### 3.3.2 SlideTitleFontSizeRule スライドタイトルはそのスライドで1番重要であるため、スライドタイトルのフォントサイズが40pt未満のとき大きくするように警告する. ### 3.3.3 SlideThemeRule 見た目の悪いスライドは見る意欲を削いでしまうため,スライドテーマが白紙であったとき殺風景なテーマは使わないよう警告する. ### 3.3.4 SlideAspectRule 船瀬先生のスライドの教えの基本ともいえる内容. 16:9のスライドは文字が横長になって見づらいスライドになりやすいため,スライドサイズが4:3でないとき警告,修正する. ### 3.3.5 PunctuationMarkRule スライドにおいて本文は箇条書きで書く必要があり,句読点は文章であることの象徴であるため,文中に句読点が含まれているとき警告,修正する. ### 3.3.6 AmbiguousWordRule 工学では可能な限り主観的な評価を省き,客観的な情報のみを使うべきであるため,「かなり」,「とても」などの曖昧な言葉が使われているとき警告する. ### 3.3.7 FontMinimumRule スライドは見て分かることが重要であり,文字が小さいと読むことが出来なくなってしまうため,本文のフォントサイズが22pt未満のとき警告する. ### 3.3.8 QuestionMarkRule 「?」が文章中にあると稚拙な文章に見えてしまうため,文中に?が含まれているとき警告する. ### 3.3.9 CTRRule 表の文字が上下にセンタリングされていないと見栄えが悪いため,表の文字が上下にセンタリングされていないとき警告,修正する. ### 3.3.10 FontSizeRule スライドを作るうえで本文のフォントサイズが22~38ptだと見やすいスライドになる. また,スライドタイトルは文章の中で一番目立たせなければならないため,40pt以上でなければならない. したがって,本文のフォントサイズが22~38pt,スライドタイトルが40pt以上でないとき警告する. ### 3.4. .funaseignore による除外機能 バージョン管理ツール Git の .gitignore による除外機能を模倣して,.funaseignore による除外機能を実装した. たとえば,以下の機能を模倣して実現した. - ディレクトリ単位の指定 - ワイルドカードの利用 - `!` によるホワイトリスト - `#` によるコメント また,.funaseignore は,対象のファイルから最も近い上位ディレクトリ内に含まれる .funaseignore を参照するようにした. ### 3.5. .funaselintrc.json によるカスタマイズ機能 ## 4. 実装方法 ### 4.1. 独自の工夫点 #### 4.1.1. Git / GitHub Git でバージョン管理を行い,GitHub で共同開発した. 共同開発モデルは,Fork and Pull モデルを採用した. これは,グループメンバーの Git / GitHub への習熟度を考慮し,ブランチの扱いについて説明することは煩雑になると考えたからである. #### 4.1.2. 仮想環境 開発環境は,Visual Studio Code の Dev Container による仮想環境を採用した. 開発環境を Dev Container で統一することには以下のメリットがあった. - ローカルが汚れない - 開発環境の違いによるトラブルが発生しない - Docker を直接扱うよりも簡単 - Visual Studio Code の拡張機能も統一できる 知能プログラミング演習 II の Teams のチャンネルを見ていると,ZIP ファイルでソースコードを共有しているグループが散見された. このようなグループでは,しばしば開発環境の違いによるトラブルが発生していた. GitHub と Dev Container を利用することで,私たちのグループではこのようなトラブルを回避することができた. #### 4.1.3. ビルドツール ビルドツールは,Gradle を採用した. Maven を利用しなかったのは,Maven における XML を用いた設定が煩雑であると感じたためである. #### 4.1.4. CLI フレームワーク CLI フレームワークは,picocli を採用した. picocli では,コマンドラインオプションの解析をアノテーションで行うことができる. たとえば,以下のように記述する. ```java @Option(names = { "--list-rules", "-l" }, // description = "List all available rules.") private boolean listRules; ``` `@Option` アノテーションを付けたフィールドはオプションとして認識される. たとえば,フィールドのクラスが boolean の場合は,オプションが指定された場合のみ `true` が代入される. また,`parameterConsumer` を利用することで,入力に応じた事前処理を行う仕組みを実現することができる. たとえば,以下のように記述する. ```java @Option(names = { "--style", "-s" }, // description = "Specify output style.", // parameterConsumer = StyleParameterConsumer.class) private OutputStyle style; ``` `StyleParameterConsumer` は引数で与えられた文字列から出力形式を表す Enum の値に変換する処理を行うためクラスである. もし不正な値が与えられた場合には,エラーメッセージを表示して処理を終了する. また,picosli には以下の組み込みオプションがある. - -h, --help: ヘルプメッセージの表示 - -V, --version: バージョン情報の表示 特に,ヘルプメッセージはアノテーションで指定した内容から自動で生成されるため便利だった. ほかにも,今回は利用しなかったがサブコマンドを作成する機能もある. 以上のように,picocli を用いることで高機能なコマンドラインツールを手軽に実現することができた. #### 4.1.5. ルールの自動インポート機能 `refrections` ライブラリを利用して,`rules` パッケージに含まれる Rule クラスの派生クラスを自動でインポートする機能を作成した. これにより,以下のことが実現できた. - ルールの追加における手間の削減 - ルール一覧表示機能の保守性の向上 - `.funaselintrc.json` によるカスタマイズ ### 4.2. 実行例 #### 4.2.1. -h, --help: ヘルプメッセージの表示 -h, --help オプションを用いることで,ヘルプメッセージを表示できる. コマンドの入力例は以下のとおりである. ```bash funase-lint -h ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash Usage: funase-lint [-fhlvV] [-s=<style>] <inputPath> Lints and fixes PowerPoint presentations according to specified rules. <inputPath> The PowerPoint file or directory to lint. -f, --fix Automatically fix problems. -h, --help Show this help message and exit. -l, --list-rules List all available rules. -s, --style=<style> Specify output style. -v, --verbose Enable verbose output for more detailed information. -V, --version Print version information and exit. ``` #### 4.2.2. -V, --version: バージョン情報の表示 -V, --version オプションを用いることで,バージョン情報を表示できる. コマンドの入力例は以下のとおりである. ```bash funase-lint -V ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash funase-lint 1.0 ``` #### 4.2.3. 通常の実行 通常の実行のコマンドの入力例は以下のとおりである. ```bash funase-lint ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash ファイル: /workspaces/funase-lint/docs/regular/ideasketch_06.pptx スライドテーマが白紙になっています. スライドサイズの比率が 4:3 ではありません. 文中に句読点が含まれています. 曖昧な言葉が使用されています. フォントサイズが 22 pt 未満のものがあります. ``` #### 4.2.4. -l, --list-rules: ルールの一覧表示 -l, --list-rules オプションを用いることで,ルールの一覧を表示できる. コマンドの入力例は以下のとおりである. ```bash funase-lint -l ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash Available rules: TextFontRule SlideTitleFontSizeRule SlideThemeRule SlideAspectRule PunctuationMarkRule AmbiguousWordRule FontMinimumRule QuestionMarkRule CTRRule FontSizeRule ``` #### 4.2.5. -s, --style: 出力形式の指定 -s, --style オプションを用いることで,出力形式を指定できる. 指定可能な出力形式は以下の 3 つである. - japanese : 標準的な日本語 - funase : 船瀬先生の口調の模倣 - json : JSON 形式 コマンドの入力例は以下のとおりである. ```bash funase-lint -s=funase ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash ファイル: /workspaces/funase-lint/docs/regular/ideasketch_06.pptx 見た目ゴミだとスライドってね,見てもらえないのよ.白紙は殺風景だからやめてね. 16:9 のスライドはやめなさいよ,間延びしすぎて見づらいのよね. 『、』や『。』が出てくるのは文章だからだめだよね.箇条書きで書きなさいな. 可能な限り主観的な評価を取り除くことが工学の文章の考え方です.客観的に得られた情報を使いなさい. スライド読ませるつもりある?本文のフォントの大きさは最低でも 22 pt 以上にしなさいな. ``` #### 4.2.6. -f, --fix: 自動修正 -f, --fix オプションを用いることで,修正可能なルールについては自動修正できる. コマンドの入力例は以下のとおりである. ```bash funase-lint -f ./path/to/inputpath ``` 修正前後のスライドの例は以下のとおりである. ![スクリーンショット 2023-11-27 012722](https://hackmd.io/_uploads/rJF-a_oBp.png) ![スクリーンショット 2023-11-27 012739](https://hackmd.io/_uploads/HJhW6OjB6.png) #### 4.2.7. -v, --verbose: 詳細出力 -v, --verbose オプションを用いることで,詳細な出力を表示できる. コマンドの入力例は以下のとおりである. ```bash funase-lint -v ./path/to/inputpath ``` 実行結果の例は以下のとおりである. ```bash Applying rules to /workspaces/funase-lint/docs/regular/ideasketch_06.pptx... Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/slide4.xml Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/slide1.xml Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/_rels/slide5.xml.rels Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/_rels/slide3.xml.rels Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/_rels/slide1.xml.rels Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/_rels/slide2.xml.rels Applying rule TextFontRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/_rels/slide4.xml.rels (中略) Applying rule FontSizeRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/slide2.xml Applying rule FontSizeRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/slide3.xml Applying rule FontSizeRule to file: /tmp/unzippedPptx3136085862347650822/ppt/slides/slide5.xml ファイル: /workspaces/funase-lint/docs/regular/ideasketch_06.pptx スライドテーマが白紙になっています. スライドサイズの比率が 4:3 ではありません. 文中に句読点が含まれています. 曖昧な言葉が使用されています. フォントサイズが 22 pt 未満のものがあります. ``` #### 4.2.8. .funaseignore による除外機能 .funaseignore による除外設定は,指定されたファイルの親ディレクトリまたは指定されたディレクトリを上限として,リンターでチェックするファイルから最も近い上位ディレクトリに含まれる .funaseignore を自動で参照する. したがって,コマンドにおいて特に指定する必要はない. ここでは,例として以下のようなディレクトリ構成を想定する. ``` ./funaseignore ├── .funaseignore ├── ideasketch_06_1.pptx └── ideasketch_06_2.pptx ``` ただし,2 つの pptx ファイルは同一の内容である. .funaseignore は以下のように指定する. ```txt *1.pptx ``` コマンドの入力例は以下のとおりである. ```bash funase-lint ./path/to/inputpath ``` このときの実行結果の例は以下のとおりである. ``` ファイル: /workspaces/funase-lint/docs/funaseignore/ideasketch_06_2.pptx スライドテーマが白紙になっています. スライドサイズの比率が 4:3 ではありません. 文中に句読点が含まれています. 曖昧な言葉が使用されています. フォントサイズが 22 pt 未満のものがあります. ``` 実行結果から,`*1.pptx` にマッチする `ideasketch_06_1.pptx` がリンターによるチェックの対象から除外されていることが確認できる. したがって,たしかに除外ファイルの設定が機能していることがわかる. #### 4.2.9. .funaselintrc.json によるカスタマイズ機能 .funaselintrc.json によるカスタマイズ機能は,指定されたファイルの親ディレクトリまたは指定されたディレクトリの直下の .funaselintrc.json を自動で参照する. したがって,コマンドにおいて特に指定すうる必要はない. ここでは,例として以下のようなディレクトリ構成を想定する. ``` ./funaselintrc ├── .funaselintrc.json └── ideasketch_06.pptx ``` .funaselintrc.json は以下のように指定する. ```js { "fixEnabled": false, "verboseOutput": false, "outputStyle": "json", "rules": { "SlideAspectRule": false, "SlideThemeRule": false } } ``` コマンドの入力例は以下のとおりである. ```bash funase-lint ./path/to/inputpath ``` このときの実行結果の例は以下のとおりである. ```json [ { "filePath": "/workspaces/funase-lint/docs/funaselintrc/ideasketch_06.pptx", "results": [ { "ruleName": "PunctuationMarkRule", "modified": true, "source": "/tmp/unzippedPptx2548065859524461555/ppt/slides/slide4.xml", "message": "文中に句読点が含まれています." }, { "ruleName": "AmbiguousWordRule", "modified": false, "source": "/tmp/unzippedPptx2548065859524461555/ppt/slides/slide1.xml", "message": "曖昧な言葉が使用されています." }, { "ruleName": "FontMinimumRule", "modified": false, "source": "/tmp/unzippedPptx2548065859524461555/ppt/slides/slide1.xml", "message": "フォントサイズが 22 pt 未満のものがあります." } ] } ] ``` 実行結果から,出力形式が JSON に変更されていることが確認できる. また,SlideAspectRule と SlideThemeRule が無効になっていることも確認できる. したがって,たしかにカスタマイズ設定が機能していることがわかる. ### 4.3. 各メンバーの作業内容 開発期間の前半は以下の要領で役割分担をした. - 西村,高橋 : ルールの調査 - 藤岡,渡邊 : コア機能の実装 開発期間の後半は以下の要領で役割分担をした. - 西村,高橋,渡邊 : ルールの実装 - 藤岡 : 除外機能やカスタマイズ機能の実装 発表用のスライドおよびデモ動画の作成は藤岡が担当した. ## 5. 考察 ### 5.1. 自動修正は難しい 自動修正は見た目に反して難しいことがわかった. たとえば,自動修正の実行例として示したスライドのアスペクト比の修正について考えてみる. 16:9 のスライドを 4:3 に変更する場合,以下の 3 つの方法が考えられる. - 全体を引き延ばす - 背景だけ横方向に短くする - 背景だけ縦方向に長くする 1 つ目の方法は,画像が含まれていた場合に「画像の縦横比を変更してはいけない」というルールに反する. また,XML を操作してスライドコンテンツ全体を引き延ばす処理は複雑であり,実装が困難であった. 2 つ目の方法は,画像が見切れてしまうという問題がある. 3 つ目の方法は,スライドサイズが通常よりも大きくなってしまい,フォントサイズ関係のルールがうまく機能しなくなるという問題がある. 自動修正を行った結果別の問題点が生じてしまう場合には,元の問題点を自動修正すべきかという問題がある. また,もし自動修正するならば,その結果生じた問題点についても自動修正すべきかという問題がある. さらに,もしそこで自動修正を連鎖的に行う場合,ルールに矛盾があれば無限ループに陥るという問題もある. このあたりの議論については,既存のリンターの実装を参考にして,適切なアルゴリズムを考える必要があると考えられる. ### 5.2. pptx 形式と自動修正は相性が悪い pptx 形式は,XML を ZIP で圧縮したものである. このため,XML を操作することによってスライドの自動修正を行うことができる. とは言うものの,ZIP の圧縮および展開は処理が重たいので,インタラクティブに修正するのは難しいと考えられる. たとえば,当初は Visual Studio Code の拡張機能として実装し,ソースコードと同じように「問題」パネルから修正を行えるようにしたいと考えていた. この場合,問題点を修正するごとに展開と圧縮が実行されるため,処理が非効率になると考えられる. ## 6. 感想 ### 6.1. アイデア出し 今回作成したシステムは,ありていに言えば「過激」な部類に該当すると思われる. そのため,船瀬先生に対して失礼に当たらないように,当初より機能面についてはしっかりと作らなければいけないと考えていた. 結果として,まずまずの完成度までもっていくことができたので,この点については胸をなでおろしている. その一方で,他のグループを見ていると,もう少しこのような過激なアイデアが増えてもよいのではないかということを感じた. 過激なアイデアが少なかった要因として,「講義前半 2 週で学んだ技術を利用する」という技術的制約があると考えられる. 解決策として,たとえば「講義前半 2 週」ではなく「知能プログラミング演習」とすれば,知能プログラミング演習 I の後半で扱った機械学習を利用することができ,適度な自由度となり面白いアイデアも生まれたのではないだろうか. ### 6.2. 共同開発 今回,チームでプログラミングする際に便利な Git や GitHub を用いた. Git,GitHub で分からないことをネットを通して調べることでチーム開発で必要な知識を身に着けることができた. また,チームでプログラミング経験豊富なメンバーと組むことで新たな知識を得ることができた. 知能プログラミング演習 II の Teams のチャンネルを見ていると,ZIP ファイルでソースコードを共有しているグループが散見された. 情報工学科の学生であれば,GitHub などを用いて共同開発を行うことが望ましいと思われる. 共同開発に関する知識は,3 年次前期の「ソフトウェア工学」で学習できる. ただし,残念ながらこの講義は必修ではない. したがって,ハッカソンにあたって最低限 GitHub の利用について案内があるとよいのではないかと思う. また,先ほどの内容に関連して,「自分の環境で動作しない」といったやり取りも散見された. こうしたトラブルは仮想環境を利用することで解決することができる. 情報工学科の学生であれば,仮想環境を用いて開発を行うことが望ましいと思われる. しかしながら,CSE では Docker を利用することができないという問題がある. セキュリティ上の問題などでないのであれば CSE にも Docker をインストールしていただけると嬉しい. ## 7. 参考文献 理系基礎演習の Moodle のページ

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully