3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyのslim風の表記をHTMLに変換するPHPスクリプトを作った

Last updated at Posted at 2016-10-13

#考えたきっかけ
HTMLを書いたり読んだりするときに<や>がふと邪魔に感じた。

slimという書式があったなと思い出したので、似た書式で書ける変換プログラムを作ってみた。

書式は自分の好みで決めたので、結果的にはslimには少ししか似ていないものになった。

簡単な処理の割に便利なのでJavaScriptに書き換えてnode.jsで動くようにしてみようと思う。

#使い方
この投稿の最後にあるPHPスクリプト(swim.php)をサーバーに置いてから、次のようなファイルを書くとHTMLに変換されて表示される。

index.php
<?php require "swim.php"; ?>
!DOCTYPE html
html lang="ja"
  head
    meta charset="UTF-8"
    title|テストページ
  body
    h1|テストページ
    div
      p|このページはテストページです。
結果
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>テストページ</title>
  </head>
  <body>
    <h1>テストページ</h1>
    <div>
      <p>このページはテストページです。</p>
    </div>
  </body>
</html>

#書式

HTMLから<と>と閉じタグを取り除き、テキストの前に|を書く。

タグの階層はインデントで表現する。インデントはスペースでもタブでもいい。ただし、インデントにスペースとタブが混在してはいけない。

いくつか短縮形がある。短縮形を活用すると結構短く書けるようになる。

通常形
div class="abc def"|テキスト

classは.で表現できる。

短縮形
div.abc.def|テキスト

divは省略できる。

さらに短縮形
.abc.def|タイトル

テキストを含まない階層はまとめて書ける。

通常形
li
  a href="..."
    span|ここをクリック
短縮形
li>a href="...">span|ここをクリック

テキストは|に続けて書く。

一行のテキスト
p|テキスト
複数行のテキスト
p
  |これがテキスト。
  |続けて書く。
  |そのままHTMLに出力されるので、
  |小なり記号は&lt;のように書く。

/で始まる行はHTMLには出力されない。

コメント
/ コメント

/?で始まる行はPHPのコードとして実行される。

PHPコード
/? print("OK");

#変換スクリプト

swim.php
<?php

function makeHtml() {
	$stack = array();
	$in = fopen($_SERVER["SCRIPT_FILENAME"], "r");
	fgets($in, 4096);
	while (($line = fgets($in, 4096)) !== false) {
		$line = rtrim($line);
		$name = ltrim($line);
		$indent = strlen($line) - strlen($name);
		if (substr($name, 0, 1) == "/") {
			if (substr($name, 1, 1) == "?") {
				eval(substr($name, 2));
			}
			continue;
		}
		$text = "";
		if (strpos($name, "|") !== false) {
			list($name, $text) = explode("|", $name, 2);
		}
		if ($name == "") {
			print($text);
		}
		elseif (count($stack) == 0) {
			$stack[0] = array($indent, $name);
			printNodeOpen($stack, $text);
		}
		elseif ($indent == $stack[0][0]) {
			printNodeClose($stack);
			$stack[0] = array($indent, $name);
			printNodeOpen($stack, $text);
		}
		elseif ($indent > $stack[0][0]) {
			array_unshift($stack, array($indent, $name));
			printNodeOpen($stack, $text);
		}
		else {
			while (count($stack) > 0 && $indent <= $stack[0][0]) {
				printNodeClose($stack);
				array_shift($stack);
			}
			array_unshift($stack, array($indent, $name));
			printNodeOpen($stack, $text);
		}
	}
	while (count($stack) > 0) {
		printNodeClose($stack);
		array_shift($stack);
	}
	fclose($in);
}

function printNodeOpen($stack, $text) {
	$indentLevel = $stack[0][0];
	$tags = explode(">", $stack[0][1]);
	$tag = array_pop($tags);
	for ($i = 0; $i < count($tags); $i++) {
		printNode($indentLevel + $i, $tags[$i], true, "");
	}
	printNode($indentLevel + count($tags), $tag, true, $text);
	if (count($tags) >= 1) {
		printNode($indentLevel + count($tags), $tag, false);
		for ($i = count($tags) - 1; $i >= 1 ; $i--) {
			printNode($indentLevel + $i, $tags[$i], false);
		}
	}
}

function printNodeClose($stack) {
	$indentLevel = $stack[0][0];
	list($tag) = explode(">", $stack[0][1], 2);
	printNode($indentLevel, $tag, false);
}

function printNode($indentLevel, $tag, $isOpen, $value = "") {
	$indent = str_repeat("  ", $indentLevel);
	$attr = "";
	if (strpos($tag, " ") !== false) {
		list($tag, $attr) = explode(" ", $tag, 2);
		if ($attr != "") {
			$attr = " ".$attr;
		}
	}
	$class = "";
	if (strpos($tag, ".") !== false) {
		$classList = explode(".", $tag);
		$tag = array_shift($classList);
		if ($tag == "") {
			$tag = "div";
		}
		if (count($classList) >= 1) {
			$class = " class=\"".implode(" ", $classList)."\"";
		}
	}
	$type = "";
	if (strpos($tag, "-") !== false) {
		list($tag, $type) = explode("-", $tag, 2);
		if ($type != "") {
			$type = " type=\"".$type."\"";
		}
	}
	if (
		$tag == "!DOCTYPE" || $tag == "meta" || $tag == "link" ||
		$tag == "img" || $tag == "input"
	) {
		if ($isOpen) {
			print($indent."<".$tag.$type.$class.$attr.">\n");
		}
	}
	elseif ($isOpen) {
		print($indent."<".$tag.$type.$class.$attr.">\n");
		if ($value != "") {
			print($value."\n");
		}
	}
	else {
		print($indent."</".$tag.">\n");
	}
}

makeHtml();
exit();
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?