ソフトウェア/pukiwiki/uml.inc.php の変更点

更新


[[公開メモ]]

#contents

* UML を貼るためのプラグインです [#w0b69192]

このように書くと、

 &uml(
 [*] -> コマンド待ち
 コマンド待ち: rready = 1
 コマンド待ち: rvalid = 0
 コマンド待ち --> 読み出し: arvalid & \narready
 読み出し: rready = 0
 読み出し: rvalid = 0
 読み出し-right--> 結果送信: 読み出し終了
 結果送信: rready = 0
 結果送信: rvalid = 1
 結果送信 --> コマンド待ち : rready
 );

こう表示されます。

&uml(
[*] -> コマンド待ち
コマンド待ち: rready = 1
コマンド待ち: rvalid = 0
コマンド待ち --> 読み出し: arvalid & \narready
読み出し: rready = 0
読み出し: rvalid = 0
読み出し-right--> 結果送信: 読み出し終了
結果送信: rready = 0
結果送信: rvalid = 1
結果送信 --> コマンド待ち : rready
);

先頭に "skinparam handwritten true" という行を加えると、
手書き風にもできます。

&uml(
skinparam handwritten true

[*] -> コマンド待ち
コマンド待ち: rready = 1
コマンド待ち: rvalid = 0
コマンド待ち --> 読み出し: arvalid & \narready
読み出し: rready = 0
読み出し: rvalid = 0
読み出し-right--> 結果送信: 読み出し終了
結果送信: rready = 0
結果送信: rvalid = 1
結果送信 --> コマンド待ち : rready
);
* 謝辞 [#yde90f7f]

図の作成には PlantUML を利用させていただきました 

http://ja.plantuml.com/

/usr/local/bin に plantuml.jar を置いて使っています。

表示には、

ダーツフォント~
http://www.p-darts.jp/font/dartsfont/

を使わせていただきました。

%%cdn.rawgit.com で公開されているようでしたので、そちらを参照するようにしています。%%


* ソースファイル [#s0919acf]

cache/uml_svg/ というフォルダの下に .svg ファイルをキャッシュします。

plugin/uml.inc.php

 LANG:php
 <?php
 
 $plugin_uml_initialized = false;
 
 function plantuml($source)
 {
     $tmp = tempnam("/tmp", "plantuml");
 
     if (preg_match('/skinparam\s+handwritten\s+true/', $source)) {
       $source = <<<"EOS"
 @startuml
 skinparam defaultFontName dartsfont
 skinparam defaultFontStyle bold
 skinparam monochrome true
 skinparam shadowing false
 $source
 @enduml
 EOS;
     } else {
       $source = <<<"EOS"
 @startuml
 skinparam defaultFontName umldefault
 $source
 @enduml
 EOS;
     }
 
     $handle = fopen($tmp, "w");
     fwrite($handle, preg_replace("/\\r?\\n/","\r\n",$source));
     fclose($handle);
     system("/usr/bin/java -Dfile.encoding=utf-8 -jar /usr/local/bin/plantuml.jar ".$tmp." -tsvg");
     unlink($tmp);
 
     $svg = file_get_contents($tmp.".svg");
     unlink($tmp.".svg");
 
     return preg_replace('/^<\\?xml.*?>/', '', $svg);
 }
 
 function plantuml_convert($source)
 {
     $image_base = sha1($source);
     $image_dir = "cache/uml_svg/{$image_base[0]}/{$image_base[1]}";
     $image_svg = "{$image_dir}/{$image_base}.svg";
 
     if(!file_exists($image_svg)) {
         $svg = plantuml($source);
         
         if (mb_substr($svg,0,4)=="<svg") {
             if(!file_exists($image_dir)){
                 mkdir($image_dir, 0770, true);
             }
             $fh = fopen($image_svg, "w");
             fwrite($fh, $svg);
             fclose($fh);
         }
     } else {
         $svg = file_get_contents($image_svg);
     }
 
     return $svg;
 }
 
 function plugin_uml_header()
 {
     $style = '';
     global $plugin_uml_initialized;
     if (!$plugin_uml_initialized) {
       $style = <<<'EOS'
 <style type="text/css">
 @font-face {
   font-family: "dartsfont";
   src: url("http://dora.bk.tsukuba.ac.jp/~takeuchi/skin/font/dartsfont.eot?#iefix") format('eot'),
        url("http://dora.bk.tsukuba.ac.jp/~takeuchi/skin/font/dartsfont.woff") format('woff');
 }
 
 svg text[font-family="dartsfont"] {
   font-family: "dartsfont";
 }
 
 svg text[font-family="umldefault"] {
   font-family:Arial,Helvetica,'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ',Meiryo,'MS Pゴシック',sans-serif;
 }
 </style>
 EOS;
       $plugin_uml_initialized = true;
     }
     return $style;
 }
 
 function plugin_uml_inline()
 {
     $aryargs = func_get_args();
     $source = join(",", $aryargs);
     $source = rtrim($source, ",");  //remove extra comma at the end.
     $source = str_replace("<br>", "\n",$source);
 
     $style = plugin_uml_header();
     return $style . plantuml_convert($source);
 }
 
 ?>

* pukiwiki.php の改造 [#na6a8784]

複数行のパラメータを渡せるように、次のように改造しました。

 LANG:php
 //      $body  = convert_html(get_source($base));
 
         $lines = get_source($base); 
 
         for($i=0;$i<count($lines);$i++)
             if (preg_match('/\&uml\(/', $lines[$i]) && $lines[$i][0]!=' ') 
                 while(!preg_match('/\&uml\(.*?\)\;/', $lines[$i]) && ($i+1<count($lines)))
                     array_splice($lines, $i, 2, chop($lines[$i]) . '<br>' . $lines[$i+1] );
 
         $body  = convert_html($lines);

* plantuml のソースコードを簡単に書くには [#r1ff6881]

こちらが参考になりそうです。

Qiita - AtomとPlantUMLで爆速UMLモデリング~
http://qiita.com/nakahashi/items/3d88655f055ca6a2617c

- 右下の言語設定で PlantUML を選びます
- メニューから [Package]-[plantuml-viewer]-[Toggle] でプレビューウィンドウを表示します

Windows7 64bit 上でリアルタイムに図を確認できました。

&ref(atom-plugim-plantuml.png,,66%);

以下では Sublime 3 でも似たようなことができると書かれているのですが、

http://qiita.com/ogomr/items/0b5c4de7f38fd1482a48

まだうまくいってません。

* 使用例 [#u1c9b03d]

http://ja.plantuml.com/ の例をいくつか。

 skinparam handwritten true
 
 actor Foo1
 boundary Foo2
 control Foo3
 entity Foo4
 database Foo5
 Foo1 -> Foo2 : To boundary
 Foo1 -> Foo3 : To control
 Foo1 -> Foo4 : To entity
 Foo1 -> Foo5 : To database

&uml(
skinparam handwritten true

actor Foo1
boundary Foo2
control Foo3
entity Foo4
database Foo5
Foo1 -> Foo2 : To boundary
Foo1 -> Foo3 : To control
Foo1 -> Foo4 : To entity
Foo1 -> Foo5 : To database
);

handwritten true が無ければ次のようになります。

&uml(
actor Foo1
boundary Foo2
control Foo3
entity Foo4
database Foo5
Foo1 -> Foo2 : To boundary
Foo1 -> Foo3 : To control
Foo1 -> Foo4 : To entity
Foo1 -> Foo5 : To database
);

 skinparam handwritten true
 
 :Main Admin: as Admin
  (Use the application) as (Use)
 
 User -> (Start)
 User --> (Use)
 
 Admin ---> (Use)
 
 note right of Admin : This is an example.
 
 note right of (Use)
   A note can also
   be on several lines
 end note
 
 note "This note is connected\nto several objects." as N2
 (Start) .. N2
 N2 .. (Use)

&uml(
skinparam handwritten true

:Main Admin: as Admin
(Use the application) as (Use)

User -> (Start)
User --> (Use)

Admin ---> (Use)

note right of Admin : This is an example.

note right of (Use)
  A note can also
  be on several lines
end note

note "This note is connected\nto several objects." as N2
(Start) .. N2
N2 .. (Use)
);

 package "Classic Collections" #DDDDDD {
 abstract class AbstractList
 abstract AbstractCollection
 interface List
 interface Collection
 }
 
 List <|-- AbstractList
 Collection <|-- AbstractCollection
 
 Collection <|- List
 AbstractCollection <|- AbstractList
 
 AbstractList <|-- ArrayList
 
 class ArrayList {
   Object[] elementData
   size()
 }
 
 enum TimeUnit {
   DAYS
   HOURS
   MINUTES
 }
 
 annotation SuppressWarnings

&uml(
package "Classic Collections" #DDDDDD {
abstract class AbstractList
abstract AbstractCollection
interface List
interface Collection
}

List <|-- AbstractList
Collection <|-- AbstractCollection

Collection <|- List
AbstractCollection <|- AbstractList

AbstractList <|-- ArrayList

class ArrayList {
  Object[] elementData
  size()
}

enum TimeUnit {
  DAYS
  HOURS
  MINUTES
}

annotation SuppressWarnings
);

 start
 :ClickServlet.handleRequest() ;
 :new page;
 if (Page.onSecurityCheck) then (true)
   :Page.onInit() ;
   if (isForward?) then (no)
     :Process controls;
     if (continue processing?) then (no)
       stop
     endif
     
     if (isPost?) then (yes)
       :Page.onPost() ;
     else (no)
       :Page.onGet() ;
     endif
     :Page.onRender() ;
   endif
 else (false)
 endif
 
 if (do redirect?) then (yes)
   :redirect process;
 else
   if (do forward?) then (yes)
     :Forward request;
   else (no)
     :Render page template;
   endif
 endif
 
 stop

&uml(
start
:ClickServlet.handleRequest() ;
:new page;
if (Page.onSecurityCheck) then (true)
  :Page.onInit() ;
  if (isForward?) then (no)
    :Process controls;
    if (continue processing?) then (no)
      stop
    endif
    
    if (isPost?) then (yes)
      :Page.onPost() ;
    else (no)
      :Page.onGet() ;
    endif
    :Page.onRender() ;
  endif
else (false)
endif

if (do redirect?) then (yes)
  :redirect process;
else
  if (do forward?) then (yes)
    :Forward request;
  else (no)
    :Render page template;
  endif
endif

stop
);

* 質問・コメント [#y0f6fa29]

#article_kcaptcha
**usrについて [#i89abd19]
>[[ま]] (&timetag(2023-06-23T05:02:03+09:00, 2023-06-23 (金) 14:02:03);)~
~
素人質問で申し訳ありません。~
>/usr/local/bin に plantuml.jar を置いて使っています。~
usrフォルダはpluginと同じレベルでよかったですか?ないので新規作成しました。~
~
同様に"/usr/bin/java"がないのですが、どのようにすればいいでしょうか?~

//
- java はお使いの Linux ディストリビューションに合わせて apt あるいは rpm などでインストールするのが普通です。例えば openjdk jre などのパッケージを入れることになります。/usr/local/bin の /usr はルート直下の usr フォルダという意味です。管理者権限がない場合には /usr の下にインストールすることはできませんので何とか自分でインストールして使うことになりますが、オーナーやパーミッションの設定などいろいろ気を付けなければならなくなるので全く分からないところから動くところまで持っていくのは非常に大変だと思います。 -- [[武内(管理人)]] &new{2023-06-26 (月) 15:42:39};

#comment_kcaptcha

**pukiwikiの改造について [#u543e626]
> (&timetag(2016-07-01T10:16:46+09:00, 2016-07-01 (金) 19:16:46);)~
~
便利に使わせてもらっています。~
~
 lib/pukiwiki.phpですが、こちらの環境では$lines  = get_source($base);~
を追加したら動くようになりました。(1.5.1)~
~
ご参考まで。~

//
- ご指摘ありがとうございます。本当ですね、一行抜けていました。本文を修正いたしました。 -- [[武内 (管理人)]] &new{2016-07-01 (金) 23:17:25};

#comment_kcaptcha

Counter: 6593 (from 2010/06/03), today: 5, yesterday: 2