はじめに
今回は法務らしく、契約書関係で。
契約書を触ったことがある人は誰しも経験がある「条ずれ」。
そう。Cloudsignの契約書あるあるで投稿したところ入賞するレベル(契約書あるある2019」結果発表)のあの忌まわしき「条ずれ」問題。
実は契約書の類はフォーマットがしっかり決まっていて、Markdownとも相性がいいので、MarkdownをHTMLに変換して、jsで条文番号なんかをコントロールすれば条ずれしない契約書が作れるのではないかと思って、作ってみました。
ソースコード
Githubで公開してます。
ちなみに「Markdownって表書きにくいやん」問題は放置してしまっています。ごめんなさい。
使い方
Markdownで契約書を書きます。
とはいえ、実質Webと相性がいい契約書類といえば利用規約か社内規定といったところかとは思います。
この時、Markdown条では一切条文番号を振る必要はなく、
- h1: 契約書名・利用規約名
- h2: 章
- h3: 条
- h3の下のp: 項 (第1項は項数をふらないようにしています。)
- li: 号
というルールに基づいて書いていけばいいだけです。
このMarkdownをHTMLに変換し、jQueryとScriptを読ませると、自動で各番号を振る仕組みです。
Markdown側では一切番号を付与していないので、条を追加しようが削除しようが、Web側では正しく番号が振られることになります。
実際の動き
# ○○サービス利用規約 (Sample)
## 総則
### 規約の制定目的
\当社は契約者に○○サービス(以下「本サービス」といいます。)を提供するための条件として、○○サービス利用規約(重要事項説明書、別紙、〇〇を含みます。以下「本規約」といいます。)を定めます。
### 本規約の変更
当社は本規約を変更することがあります。当該変更を行うときは、当該変更後の本規約の内容及びその効力発生時期を、当社のWebサイト上への掲載その他の適切な方法により周知します。
本規約の変更の効力が発生した後、契約者が、特段の申し出なく、本サービスを利用したとき、利用料金を支払ったとき、その他当該変更に特段の異議無く承諾したものと当社が判断したときは、かかる変更に同意したものとみなし、特に断りの無い限り料金その他の提供条件は変更後の規約によります。
### 定義
本規約において用いる用語の意味は次のとおりです。
- 用語1
- 用語2
- 用語3
これを変換すると
○○サービス利用規約 (Sample)
第1章 総則
第1条 規約の制定目的
当社は契約者に○○サービス(以下「本サービス」といいます。)を提供するための条件として、○○サービス利用規約(重要事項説明書、別紙、〇〇を含みます。以下「本規約」といいます。)を定めます。
第2条 本規約の変更
当社は本規約を変更することがあります。当該変更を行うときは、当該変更後の本規約の内容及びその効力発生時期を、当社のWebサイト上への掲載その他の適切な方法により周知します。
2 本規約の変更の効力が発生した後、契約者が、特段の申し出なく、本サービスを利用したとき、利用料金を支払ったとき、その他当該変更に特段の異議無く承諾したものと当社が判断したときは、かかる変更に同意したものとみなし、特に断りの無い限り料金その他の提供条件は変更後の規約によります。
第3条 定義
本規約において用いる用語の意味は次のとおりです。
(1)用語1
(2)用語2
(3)用語3
// Body以下をWrap
$("body").wrapInner('<section class="tos">')
//Head addClass
$("h1").addClass("tos__title");
$("h2").addClass("section__title");
$("h3").addClass("article__title");
//$("p").addClass("regular-font");
// Head note
$("h1 + p").addClass("tos__headNote");
//Section Number automatic numbering
$("h2").each(function(i){
i = i+1;
$(this).attr("id","section_" + i);
$("#section_"+i).prepend("<span class='section__num'>第"+i+"章</span>");
});
//Article Number automatic numbering
$("h3").each(function(i){
i = i+1;
$(this).attr("id","article_" + i);
$("#article_"+i).prepend("<span class='article__num'>第"+i+"条</span>");
//pにclassを振るため
var $p = "#article_"+i+" ~ p";
$($p).each(function(i){
i = i+1;
$(this).attr("class", "regular-font p_" + i);
});
//liにclassを振るため
var $item = "#article_"+i+" ~ ul > li";
$($item).each(function(i){
i = i+1;
$(this).attr("class", "regular-font item_" + i);
});
});
//Sub-Article Number automatic numbering
$("p").each(function(i){
i = i+1;
$(".p_"+i).prepend("<span class='subArticle__num'>"+i+"</span>");
});
//Sub-Paragraph Number automatic numbering
$("li").each(function(i){
i = i+1;
$(".item_"+i).prepend("<span class='subParagraph__num'>("+i+")</span>");
});
なお、内部の参照リンクも自動で取得するようになっています。
Markdown側で**[条文の表題]()**としておくと「リンクが空欄になっているaタグは条文の表題と一致する条項のIDを拾って、挿入する形になっています。
// Internal link
$("a").each(function(i){
i = i+1;
$(this).attr("id", "internalAnchor_"+i);
var query = $(this).text();
console.log(query);
// h3の中で一致する条文を検索して、条文番号を取得
var articleNum = $("h3:contains('"+query+"')").children("span").text();
console.log(articleNum);
// ページ内リンクを動的に作成するためにarticleのidを取得
var articleId = $("h3:contains('"+query+"')").attr("id");
console.log(articleId);
// 参照条項名に括弧を付与(括弧がないと読みにくいため)
// ただし、自動で内部リンクとして付与しないもの(外部リンクなど)に括弧がついてしまうと邪魔なので、ifで条件分岐。hrefが設定されていないリンクだけに括弧を付与するとしている。
// ページ内リンク用のIDや参照条文の番号も動的に付与しているので、こちらもhrefが空になっているものだけに付与されるようにif内に設定。
var $href = $(this).attr("href");
if($href == ""){
$(this).text("("+query+")"); // 参照条文のものには括弧を付与
$(this).attr("href", "#"+articleId); // 動的にページ内リンクを作成
$(this).prepend("<span class='internalAnchor'>"+articleNum+"</span>"); // 参照条文の番号を動的にページ内リンクに挿入
} else {
$(this).attr("target", "_blank"); // target属性を付与
}
});
おわりに
少しでも「条ずれ」という悪夢を和らげようと作ったものです。参考までに。
もっといいやりかたがあるよという方はぜひ。