Readme.MD 例子

瞭解一個項目,恐怕首先都是經過其Readme文件瞭解信息。若是你覺得Readme文件都是隨便寫寫的那你就錯了。github,oschina git gitcafe的代碼託管平臺上的項目的Readme.MD文件都是有其特有的語法的。稱之爲Markdown語法。基本規則以下:
html

[html] view plain copy
  1. Markdown 語法速查表  
  2. 1 標題與文字格式  
  3. 標題  
  4. # 這是 H1 <一級標題>  
  5. ## 這是 H2 <二級標題>  
  6. ###### 這是 H6 <六級標題>  
  7. 文字格式  
  8. **這是文字粗體格式**  
  9. *這是文字斜體格式*  
  10. ~~在文字上添加刪除線~~  
  11. 2 列表  
  12. 無序列表  
  13. * 項目1  
  14. * 項目2  
  15. * 項目3  
  16. 有序列表  
  17. 1. 項目1  
  18. 2. 項目2  
  19. 3. 項目3  
  20.    * 項目1  
  21.    * 項目2  
  22. 3 其它  
  23. 圖片  
  24. ![圖片名稱](http://gitcafe.com/image.png)  
  25. 連接  
  26. [連接名稱](http://gitcafe.com)  
  27. 引用  
  28. > 第一行引用文字  
  29. > 第二行引用文字  
  30. 水平線  
  31. ***  
  32. 代碼  
  33. `<hello world>`  
  34. 代碼塊高亮  
  35. ```ruby  
  36.   def add(a, b)  
  37.     return a + b  
  38.   end  
  39. ```  
  40. 表格  
  41.   表頭  | 表頭  
  42.   ------------- | -------------  
  43.  單元格內容  | 單元格內容  
  44.  單元格內容l  | 單元格內容  

若是直接記語法,那彷佛困難了些。這裏OneCoder推薦兩個Markdown的編輯器。前端

在線編輯器:stackedit
網址:https://stackedit.io/java

Mac下離線編輯器Mou
下載地址:http://mouapp.com/git


OneCoder這裏使用的是後者爲本身的shurnim-storage項目寫Readme。至於這個項目是什麼,見Readme文檔,OneCoder也會在另外的博文作一些補充說明。成品Readme以下:
github

[html] view plain copy
  1. # shurnim-storage  
  2.   
  3. ![Shurnim icon](http://onecoder.qiniudn.com/8wuliao/DLPii2Jx/rEBO.jpg)  
  4.   
  5. ## 目錄  
  6. * [背景介紹](#背景介紹)  
  7. * [項目介紹](#項目介紹)  
  8. * [使用說明](#使用說明)  
  9.   * [獲取代碼](#獲取代碼)  
  10.   * [開發插件](#開發插件)  
  11.   * [使用ShurnimStorage接口](#使用ShurnimStorage接口)  
  12.        * [接口介紹](#接口介紹)  
  13.        * [使用樣例](#使用樣例)  
  14. * [其餘](#其餘)  
  15.   
  16. <a name="背景介紹"></a>  
  17. ## 背景介紹  
  18.   
  19. *Shurnim*,是我和我老婆曾經養過的一隻倉鼠的名字。<br/>  
  20. *shurnim-storage*,是一個插件式雲存儲/網盤同步管理工具。是在參加又拍雲開發大賽的過程當中設計並開發。  
  21.   
  22. <a name="項目介紹"></a>  
  23. ## 項目介紹  
  24.   
  25. *shurnim-storage* 的設計初衷是給你們提供一個可方便擴展的雲存儲/網盤同步工具。分後端接口和前端UI界面兩部分。<br>  
  26.   
  27. 因爲目前各類雲存儲和網盤系統層出不窮,單一工具每每支持支持某幾個特定存儲之間的同步,如**又拍雲**到**七牛雲存儲**的同步工具,此時如若想同步到其餘存則可能須要新的工具,給用戶帶來不便。*shurnim-storage*  正是爲了解決此問題而設計的。  
  28.   
  29. 在*shurnim-storage*中,用戶使用的固定的統一的後端接口。而全部雲存儲/網盤API的支持則是以插件的形式部署到系統中的。如此,若是用戶想要一個從**又拍雲**到**Dropbox**的同步工具,則只須要在原有基礎上,增長**Dropbox**的插件,便可實現互通,方便快捷。<br/>  
  30.   
  31. 同時,後端統一接口的設計也考慮到界面開發的需求,可直接經過後端提供的接口開發具備上述擴展功能的雲存儲UI工具。<br>  
  32.   
  33. 目前,後端總體框架的核心部分已經基本開發完成。只需逐步補充後端接口和插件開發接口的定義便可。但因爲我的時間和能力所限,UI部分沒有開發,有興趣的同窗能夠一試。  
  34.   
  35. <a name="使用說明"></a>  
  36. ## 使用說明  
  37.   
  38. <a name="獲取代碼"></a>  
  39. ### 獲取代碼  
  40.   
  41. * gitcafe項目主頁: <https://gitcafe.com/onecoder/shurnim-storage-for-UPYUN>  
  42. * OSChina項目主頁: <http://git.oschina.net/onecoder/shurnim-storage><br>  
  43. OSChina上的會持續更新。  
  44.   
  45. 另外你也能夠經過OSChina的Maven庫獲取依賴,或者本身編譯jar包。  
  46.   
  47. * maven  
  48.   
  49.      1. 加入OSC倉庫  
  50.      
  51.                     <repositories>  
  52.                       <repository>  
  53.                            <id>nexus</id>  
  54.                            <name>local private nexus</name>  
  55.                            <url>http://maven.oschina.net/content/groups/public/</url>  
  56.                            <releases>  
  57.                                 <enabled>true</enabled>  
  58.                            </releases>  
  59.                            <snapshots>  
  60.                                 <enabled>false</enabled>  
  61.                            </snapshots>  
  62.                       </repository>  
  63.                  </repositories>  
  64.   
  65.      2. 加入依賴  
  66.      
  67.                <dependency>  
  68.                  <groupId>com.coderli</groupId>  
  69.                  <artifactId>shurnim-storage</artifactId>  
  70.                   <version>0.1-alpha</version>  
  71.                </dependency>  
  72. * Gradle 編譯Jar  
  73.   
  74. 在項目目錄執行  
  75.      
  76.      gradle jar  
  77.      
  78. <a name="開發插件"></a>  
  79. ### 開發插件  
  80.   
  81. 在*shurnim-storage*中,插件就像一塊一塊的積木,不但支撐着框架的功能,也是框架可擴展性的基石。開發一個插件,僅需兩步:  
  82.   
  83. 1. 實現PluginAPI接口  
  84.   
  85. ```  
  86. package com.coderli.shurnim.storage.plugin;  
  87.   
  88. import java.io.File;  
  89. import java.util.List;  
  90.   
  91. import com.coderli.shurnim.storage.plugin.model.Resource;  
  92.   
  93. /**  
  94. * 各類雲存儲插件須要實現的通用接口  
  95. *  
  96. * @author OneCoder  
  97. * @date 2014年4月22日 下午9:43:41  
  98. * @website http://www.coderli.com  
  99. */  
  100. public interface PluginAPI {  
  101.   
  102.      /**  
  103.       * 初始化接口  
  104.       *  
  105.       * @author OneCoder  
  106.       * @date 2014年5月19日 下午10:47:40  
  107.       */  
  108.      void init();  
  109.   
  110.      /**  
  111.       * 獲取子資源列表  
  112.       *  
  113.       * @param parentPath  
  114.       * @return  
  115.       * @author OneCoder  
  116.       * @date 2014年4月24日 下午11:29:14  
  117.       */  
  118.      List<Resource> getChildResources(String parentPath);  
  119.   
  120.      /**  
  121.       * 下載特定的資源  
  122.       *  
  123.       * @param parentPath  
  124.       *            目錄路徑  
  125.       * @param name  
  126.       *            資源名稱  
  127.       * @param storePath  
  128.       *            下載資源保存路徑  
  129.       * @return  
  130.       * @author OneCoder  
  131.       * @date 2014年4月24日 下午11:30:19  
  132.       */  
  133.      Resource downloadResource(String parentPath, String name, String storePath);  
  134.   
  135.      /**  
  136.       * 建立文件夾  
  137.       *  
  138.       * @param path  
  139.       *            文件夾路徑  
  140.       * @param auto  
  141.       *            是否自動建立父目錄  
  142.       * @return  
  143.       * @author OneCoder  
  144.       * @date 2014年5月15日 下午10:10:04  
  145.       */  
  146.      boolean mkdir(String path, boolean auto);  
  147.   
  148.      /**  
  149.       * 上傳資源  
  150.       *  
  151.       * @param parentPath  
  152.       *            父目錄路徑  
  153.       * @param name  
  154.       *            資源名稱  
  155.       * @param uploadFile  
  156.       *            待上傳的本地文件  
  157.       * @return  
  158.       * @author OneCoder  
  159.       * @date 2014年5月15日 下午10:40:13  
  160.       */  
  161.      boolean uploadResource(String parentPath, String name, File uploadFile);  
  162. }  
  163. ```  
  164.   
  165. 目前插件的接口列表僅爲同步資源設計,若是想要支持更多操做(如刪除,查找等),可擴展該接口定義。<br/><br/>  
  166. 接口中,全部的參數和返回值均爲*shurnim-storage*框架中定義的通用模型。所以,您在開發插件過程當中須要將特定SDK中的模型轉換成接口中提供的模型。<br/><br/>  
  167. 插件實現類只要與*shurnim-storage*工程在同一個classpath便可使用。您既能夠直接在源碼工程中開發插件,就如工程裏提供的*upyun*和*qiniu*插件同樣,也能夠做爲獨立工程開發,打成jar,放置在同一個classpath下。<br/><br/>  
  168. *upyun*插件樣例(功能不完整):  
  169.   
  170. ```    
  171. package com.coderli.shurnim.storage.upyun.plugin;  
  172.   
  173. import java.io.File;  
  174. import java.util.List;  
  175.   
  176. import com.coderli.shurnim.storage.plugin.AbstractPluginAPI;  
  177. import com.coderli.shurnim.storage.plugin.model.Resource;  
  178. import com.coderli.shurnim.storage.plugin.model.Resource.Type;  
  179. import com.coderli.shurnim.storage.upyun.api.UpYun;  
  180.   
  181. public class UpYunPlugin extends AbstractPluginAPI {  
  182.   
  183.      private UpYun upyun;  
  184.      private String username;  
  185.      private String password;  
  186.      private String bucketName;  
  187.   
  188.      public UpYun getUpyun() {  
  189.           return upyun;  
  190.      }  
  191.   
  192.      public void setUpyun(UpYun upyun) {  
  193.           this.upyun = upyun;  
  194.      }  
  195.   
  196.      public String getUsername() {  
  197.           return username;  
  198.      }  
  199.   
  200.      public void setUsername(String username) {  
  201.           this.username = username;  
  202.      }  
  203.   
  204.      public String getPassword() {  
  205.           return password;  
  206.      }  
  207.   
  208.      public void setPassword(String password) {  
  209.           this.password = password;  
  210.      }  
  211.   
  212.      public String getBucketName() {  
  213.           return bucketName;  
  214.      }  
  215.   
  216.      public void setBucketName(String bucketName) {  
  217.           this.bucketName = bucketName;  
  218.      }  
  219.   
  220.      /*  
  221.       * (non-Javadoc)  
  222.       *  
  223.       * @see  
  224.       * com.coderli.shurnim.storage.plugin.PluginAPI#getChildResources(java.lang  
  225.       * .String)  
  226.       */  
  227.      @Override  
  228.      public List<Resource> getChildResources(String parentPath) {  
  229.           return null;  
  230.      }  
  231.   
  232.      /*  
  233.       * (non-Javadoc)  
  234.       *  
  235.       * @see  
  236.       * com.coderli.shurnim.storage.plugin.PluginAPI#downloadResource(java.lang  
  237.       * .String, java.lang.String, java.lang.String)  
  238.       */  
  239.      @Override  
  240.      public Resource downloadResource(String parentPath, String name,  
  241.                String storePath) {  
  242.           File storeFile = new File(storePath);  
  243. //          if (!storeFile.exists()) {  
  244. //               try {  
  245. //                    storeFile.createNewFile();  
  246. //               } catch (IOException e) {  
  247. //                    e.printStackTrace();  
  248. //               }  
  249. //          }  
  250.           String filePath = getFullPath(parentPath, name);  
  251.           upyun.readDir("/api");  
  252.           if (upyun.readFile(filePath, storeFile)) {  
  253.                Resource result = new Resource();  
  254.                result.setName(name);  
  255.                result.setPath(parentPath);  
  256.                result.setType(Type.FILE);  
  257.                result.setLocalFile(storeFile);  
  258.                return result;  
  259.           }  
  260.           return null;  
  261.      }  
  262.   
  263.      String getFullPath(String parentPath, String name) {  
  264.           if (!parentPath.endsWith(File.separator)) {  
  265.                parentPath = parentPath + File.separator;  
  266.           }  
  267.           return parentPath + name;  
  268.      }  
  269.   
  270.      /*  
  271.       * (non-Javadoc)  
  272.       *  
  273.       * @see com.coderli.shurnim.storage.plugin.PluginAPI#mkdir(java.lang.String,  
  274.       * boolean)  
  275.       */  
  276.      @Override  
  277.      public boolean mkdir(String path, boolean auto) {  
  278.           // TODO Auto-generated method stub  
  279.           return false;  
  280.      }  
  281.   
  282.      /*  
  283.       * (non-Javadoc)  
  284.       *  
  285.       * @see  
  286.       * com.coderli.shurnim.storage.plugin.PluginAPI#uploadResource(java.lang  
  287.       * .String, java.lang.String, java.io.File)  
  288.       */  
  289.      @Override  
  290.      public boolean uploadResource(String parentPath, String name,  
  291.                File uploadFile) {  
  292.           // TODO Auto-generated method stub  
  293.           return false;  
  294.      }  
  295.   
  296.      /*  
  297.       * (non-Javadoc)  
  298.       *  
  299.       * @see com.coderli.shurnim.storage.plugin.AbstractPluginAPI#init()  
  300.       */  
  301.      @Override  
  302.      public void init() {  
  303.           upyun = new UpYun(bucketName, username, password);  
  304.      }  
  305.   
  306. }  
  307. ```  
  308.   
  309.   
  310. 2. 編寫插件配置文件  
  311.   
  312. ```  
  313. <?xml version="1.0" encoding="UTF-8"?>  
  314. <plugin>  
  315.      <id>qiniu</id>  
  316.      <name>七牛雲存儲</name>  
  317.      <api>  
  318.           <className>com.coderli.shurnim.storage.qiniu.QiniuPlugin</className>  
  319.           <params>  
  320.                <param name="access_key" displayName="ACCESS_KEY">EjREKHI_GFXbQzyrKdVhhXrIRyj3fRC1s9UmZPZO  
  321.                </param>  
  322.                <param name="secret_key" displayName="SECRET_KEY">88NofFWUvkfJ6T6rGRxlDSZOQxWkIxY2IsFIXJLX  
  323.                </param>  
  324.                <param name="bucketName" displayName="空間名">onecoder  
  325.                </param>  
  326.           </params>  
  327.      </api>  
  328. </plugin>  
  329. ```  
  330.    * **id** 爲該插件在*shurnim-storage*框架下的惟一標識,不可重複,必填。  
  331.     * **name** 爲顯示值,爲UI開發提供可供顯示的有語義的值。  
  332.     * **className** 爲插件接口實現類的完整路徑。必填  
  333.     * **params/param** 爲插件須要用戶配置的參數列表。其中  
  334.          * *name* 表明參數名,須要與接口實現類中的參數名嚴格一致,且必須有相應的set方法的格式要求嚴格,即set+首字母大寫的參數名。例如:setAccess_key(String arg); 目前只支持*String*類型的參數。  
  335.          * *displayName* 爲參數顯示名,一樣是爲了UI開發的考慮,方便用戶開發出可根據參數列表動態顯示的UI界面。  
  336.          * 參數的值能夠直接配置在配置文件中,也能夠在運行期動態賦值。直接配置值,對於直接使用後端接口來講較爲方便。對於UI開發來講,運行期動態賦值更爲合理。<br/></br>  
  337.   
  338.      在使用源碼工程時,插件配置文件統一放置在工程的*plugins*目錄下。你也能夠統一放置在任何位置。此時,在構造後端接口實例時,須要告知接口該位置。  
  339.      
  340. <a name="使用ShurnimStorage接口"></a>  
  341. ### 使用*ShurnimStorage*接口  
  342.   
  343. <a name="接口介紹"></a>  
  344. #### 接口介紹  
  345.   
  346. **ShurnimStorage**接口是*shurinm-storage*框架全局的也是惟一的接口,目前定義如  
  347.   
  348. ```  
  349. package com.coderli.shurnim.storage;  
  350.   
  351. import java.util.List;  
  352. import java.util.Map;  
  353.   
  354. import com.coderli.shurnim.storage.plugin.model.Plugin;  
  355. import com.coderli.shurnim.storage.plugin.model.Resource;  
  356.   
  357. /**  
  358. * 後臺模塊的全局接口<br>  
  359. * 經過該接口使用後臺的所有功能。<br>  
  360. * 使用方式:<br>  
  361. <li>  
  362. * 1.先經過{@link #getSupportedPlugins()}方法獲取全部支持的平臺/插件列表。 <li>  
  363. * 2.將列表中返回的ID傳入對應的接口參數中,進行對應的平臺的相關操做。<br>  
  364. * 須要注意的是,不一樣平臺的插件須要給不一樣的參數賦值,該值能夠直接配置在配置文件中。<br>  
  365. * 也能夠在運行期動態賦值。(會覆蓋配置文件中的值。)<br>  
  366. *  
  367. * 參數列表的設計,方便UI開發人員動態的根據參數列表生成可填寫的控件。並給參數賦值。加強了可擴展性。  
  368. *  
  369. * @author OneCoder  
  370. * @date 2014年4月22日 下午9:21:58  
  371. * @website http://www.coderli.com  
  372. */  
  373. public interface ShurnimStorage {  
  374.   
  375.      /**  
  376.       * 獲取當前支持的插件列表<br>  
  377.       * 沒有支持的插件的時候可能返回null  
  378.       *  
  379.       * @return  
  380.       * @author OneCoder  
  381.       * @date 2014年5月7日 下午8:53:25  
  382.       */  
  383.      List<Plugin> getSupportedPlugins();  
  384.   
  385.      /**  
  386.       * 給指定的插件的對應參數賦值<br>  
  387.       * 此處賦值會覆蓋配置文件中的默認值  
  388.       *  
  389.       * @param pluginId  
  390.       *            插件ID  
  391.       * @param paramsKV  
  392.       *            參數鍵值對  
  393.       * @author OneCoder  
  394.       * @date 2014年5月9日 上午12:41:53  
  395.       */  
  396.      void setParamValues(String pluginId, Map<String, String> paramsKV);  
  397.   
  398.      /**  
  399.       * 獲取插件對應目錄下的資源列表  
  400.       *  
  401.       * @param pluginId  
  402.       *            插件ID  
  403.       * @param path  
  404.       *            指定路徑  
  405.       * @return  
  406.       * @author OneCoder  
  407.       * @date 2014年5月11日 上午8:52:00  
  408.       */  
  409.      List<Resource> getResources(String pluginId, String path);  
  410.   
  411.      /**  
  412.       * 同步資源  
  413.       *  
  414.       * @param fromPluginId  
  415.       *            待同步的插件Id  
  416.       * @param toPluginIds  
  417.       *            目標插件Id  
  418.       * @param resource  
  419.       *            待同步的資源  
  420.       * @return 同步結果  
  421.       * @author OneCoder  
  422.       * @date 2014年5月11日 上午11:41:24  
  423.       */  
  424.      boolean sycnResource(String fromPluginId, String toPluginId,  
  425.                     Resource resource) throws Exception;  
  426. }  
  427. ```      
  428.   
  429. 當前接口實際僅包含了獲取資源列表*getResources*和同步資源*sycnResource*功能,*getSupportedPlugins*和*setParamValues*實際爲輔助接口,在UI開發時較爲有用。<br/><br/>  
  430. 一樣,您也能夠擴展開發該接口增長更多的您喜歡的特性。例如,同時刪除給定存儲上的文件。固然,這須要插件接口的配合支持。<br/><br/>  
  431.   
  432. 這裏,*sycnResource*設計成插件間一對一的形式,是考慮到獲取同步是否成功的結果的需求。若是您想開發一次同步到多個存儲的功能,建議您從新開發您本身的接口實現類,由於默認實現會屢次下次資源(每次同步後刪除),形成網絡資源的浪費。  
  433.   
  434. 接口的默認實現類是: **DefaultShurnimStorageImpl**  
  435.   
  436. <a name="使用樣例"></a>  
  437. #### 使用樣例  
  438. ```        
  439. package com.coderli.shurnim.test.shurnimstorage;  
  440.   
  441. import org.junit.Assert;  
  442. import org.junit.BeforeClass;  
  443. import org.junit.Test;  
  444.   
  445. import com.coderli.shurnim.storage.DefaultShurnimStorageImpl;  
  446. import com.coderli.shurnim.storage.ShurnimStorage;  
  447. import com.coderli.shurnim.storage.plugin.model.Resource;  
  448. import com.coderli.shurnim.storage.plugin.model.Resource.Type;  
  449.   
  450. /**  
  451. * 全局接口測試類<br>  
  452. * 時間有限,目前僅做總體接口測試。細粒度的單元測試,隨開發補充。  
  453. *  
  454. * @author OneCoder  
  455. * @date 2014年5月19日 下午10:50:27  
  456. * @website http://www.coderli.com  
  457. */  
  458. public class ShurnimStorageTest {  
  459.   
  460.      private static ShurnimStorage shurnim;  
  461.   
  462.      @BeforeClass  
  463.      public static void init() {  
  464.           shurnim = new DefaultShurnimStorageImpl(  
  465.                     "/Users/apple/git/shurnim-storage-for-UPYUN/plugins");  
  466.      }  
  467.   
  468.      @Test  
  469.      public void testSycnResource() {  
  470.           Resource syncResource = new Resource();  
  471.           syncResource.setPath("/api");  
  472.           syncResource.setName("api.html");  
  473.           syncResource.setType(Type.FILE);  
  474.           try {  
  475.                Assert.assertTrue(shurnim.sycnResource("upyun", "qiniu",  
  476.                          syncResource));  
  477.           } catch (Exception e) {  
  478.                e.printStackTrace();  
  479.           }  
  480.      }  
  481. }  
  482. ```  
  483. <a name="其餘"></a>  
  484. ## 其餘  
  485.   
  486. 時間倉促,功能簡陋,望您包涵。OneCoder(Blog:[http://www.coderli.com](http://www.coderli.com))特別但願看到該項目對您哪怕一點點的幫助。任意的意見和建議,歡迎隨意與我溝通,聯繫方式:  
  487.   
  488. * Email: <wushikezuo@gmail.com>  
  489. * QQ:57959968  
  490. * Blog:[OneCoder](http://www.coderli.com)  
  491.   
  492. 項目的Bug和改進點,可在OSChina上以issue的方式直接提交給我。  
效果預覽:

原文:http://www.coderli.com/write-readme-for-your-project/web

相關文章
相關標籤/搜索