#lang racket
(require 2htdp/batch-io)
;; < と I の間に任意のスペースが入る場合も考慮して、
;; IMGタグ(大文字または小文字のIMG)を探す
(define *img* "< *[Ii][Mm][Gg]")
;; >に到達するまでに現れるALT属性を探す
(define *alt* (string-append *img* "[^>]*[Aa][Ll][Tt].*>"))
;; ファイルを開いてリストに読み込む
(define *filename* (begin (display "チェックするHTMLファイルの名前:")
(newline)
(format "~a" (read))))
(define *lines* (read-lines *filename*))
;; IMGタグがあって、タグ内にALTの見つからない行が見つかったら
;; コメントに入れた警告メッセージを追加する
(let loop ((lines *lines*) (acc '()))
(if (null? lines)
(write-file *filename* (apply string-append (reverse acc)))
(loop (cdr lines)
(let ((line (string-append (car lines) "\n")))
(if (and (regexp-match (regexp *img*) line)
(not (regexp-match (regexp *alt*) line)))
(cons (string-append "<!-- 画像にはALT属性を付けること! -->\n" line) acc)
(cons line acc))))))
I2xhbmcgcmFja2V0CgoocmVxdWlyZSAyaHRkcC9iYXRjaC1pbykKCjs7IDwg44GoIEkg44Gu6ZaT44Gr5Lu75oSP44Gu44K544Oa44O844K544GM5YWl44KL5aC05ZCI44KC6ICD5oWu44GX44Gm44CBCjs7IElNR+OCv+OCsCjlpKfmloflrZfjgb7jgZ/jga/lsI/mloflrZfjga5JTUcp44KS5o6i44GZCihkZWZpbmUgKmltZyogIjwgKltJaV1bTW1dW0dnXSIpCjs7ID7jgavliLDpgZTjgZnjgovjgb7jgafjgavnj77jgozjgotBTFTlsZ7mgKfjgpLmjqLjgZkKKGRlZmluZSAqYWx0KiAoc3RyaW5nLWFwcGVuZCAqaW1nKiAiW14+XSpbQWFdW0xsXVtUdF0uKj4iKSkKOzsg44OV44Kh44Kk44Or44KS6ZaL44GE44Gm44Oq44K544OI44Gr6Kqt44G/6L6844KACihkZWZpbmUgKmZpbGVuYW1lKiAoYmVnaW4gKGRpc3BsYXkgIuODgeOCp+ODg+OCr+OBmeOCi0hUTUzjg5XjgqHjgqTjg6vjga7lkI3liY06IikKICAgICAgICAgICAgICAgICAgICAgICAgIChuZXdsaW5lKQogICAgICAgICAgICAgICAgICAgICAgICAgKGZvcm1hdCAifmEiIChyZWFkKSkpKQooZGVmaW5lICpsaW5lcyogKHJlYWQtbGluZXMgKmZpbGVuYW1lKikpCgo7OyBJTUfjgr/jgrDjgYzjgYLjgaPjgabjgIHjgr/jgrDlhoXjgatBTFTjga7opovjgaTjgYvjgonjgarjgYTooYzjgYzopovjgaTjgYvjgaPjgZ/jgokKOzsg44Kz44Oh44Oz44OI44Gr5YWl44KM44Gf6K2m5ZGK44Oh44OD44K744O844K444KS6L+95Yqg44GZ44KLCihsZXQgbG9vcCAoKGxpbmVzICpsaW5lcyopIChhY2MgJygpKSkKICAoaWYgKG51bGw/IGxpbmVzKQogICAgICh3cml0ZS1maWxlICpmaWxlbmFtZSogKGFwcGx5IHN0cmluZy1hcHBlbmQgKHJldmVyc2UgYWNjKSkpCiAgICAgKGxvb3AgKGNkciBsaW5lcykKICAgICAgICAgIChsZXQgKChsaW5lIChzdHJpbmctYXBwZW5kIChjYXIgbGluZXMpICJcbiIpKSkKICAgICAgICAgICAgKGlmIChhbmQgKHJlZ2V4cC1tYXRjaCAocmVnZXhwICppbWcqKSBsaW5lKQogICAgICAgICAgICAgICAgICAgIChub3QgKHJlZ2V4cC1tYXRjaCAocmVnZXhwICphbHQqKSBsaW5lKSkpCiAgICAgICAgICAgICAgIChjb25zIChzdHJpbmctYXBwZW5kICI8IS0tIOeUu+WDj+OBq+OBr0FMVOWxnuaAp+OCkuS7mOOBkeOCi+OBk+OBqCEgLS0+XG4iIGxpbmUpIGFjYykKICAgICAgICAgICAgICAgKGNvbnMgbGluZSBhY2MpKSkpKSkK