commit 8694c58409ea3a0b33f5a5647456a699c483e53f
Author: Kyle Milz <milz@0x30.net>
Date: Wed, 17 Mar 2021 00:04:28 +0000
html.mk: website creation framework
Diffstat:
A | Makefile | | | 29 | +++++++++++++++++++++++++++++ |
A | mk/html.mk | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | mk/obj.mk | | | 35 | +++++++++++++++++++++++++++++++++++ |
A | mk/site.mk | | | 24 | ++++++++++++++++++++++++ |
A | mk/subdir.mk | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
A | t/cp_happy.t | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
A | t/cp_nodest.t | | | 30 | ++++++++++++++++++++++++++++++ |
A | t/cp_unhappy.t | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | t/dep_simple.t | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | t/srcs_missing.t | | | 21 | +++++++++++++++++++++ |
A | t/srcs_suffix.t | | | 65 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | t/xliterate.t | | | 62 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
12 files changed, 654 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,29 @@
+#
+# Sample Makefile, edit for your needs.
+# As is it will create `index.html' from source file `index.in'.
+#
+
+# For out of tree builds, which files need copying into the object
+# directory.
+#
+#CP_OBJ += file_a.pdf
+#CP_OBJ += file_b.log
+
+# Files to transform into HTML documents. If omitted the default `index.in'
+# will be used.
+# These MUST HAVE `.in' suffix!
+#
+#SRCS += doc_a.in
+#SRCS += doc_b.in
+
+# What directories to enter after building the current one completes.
+#
+#SUBDIR += dir_a
+#SUBDIR += dir_b
+#SUBDIR += dir_c
+
+# Relative path to the top level directory. Must always be set.
+#
+TOP = .
+
+.include "${TOP}/mk/html.mk"
diff --git a/mk/html.mk b/mk/html.mk
@@ -0,0 +1,171 @@
+#
+# html.mk
+# This file must be included by all Makefiles.
+#
+
+#
+# These variables shoud not be modified here but set in Makefiles instead.
+# - TOP: Directory containing the `mk' directory
+# - SRCS: List of source files to transform into HTML documents
+#
+TOP ?= .
+SRCS ?= index.in
+INCLUDE = ${.CURDIR}/${TOP}/include
+
+
+# Clear existing suffixes.
+.SUFFIXES:
+
+
+# Check SRCS array for nonexisting files.
+.for src in ${SRCS}
+. if !exists(${.CURDIR}/${src})
+all:
+ @>&2 echo "html.mk: file '${src}' in SRCS array does not exist."
+.else
+all: ${src:.in=.html}
+. endif
+.endfor
+
+
+all: _SUBDIRUSE
+
+#
+# Use the C preprocessor to turn input source files into HTML.
+#
+# -I: global files and targets generated in object directory can be included
+# -P: the files being preprocessed are not C
+# -o: the final HTML files are written in the object directory
+#
+.SUFFIXES: .in .html
+.in.html:
+ cpp -I${INCLUDE} -I${.OBJDIR} -P -o ${.OBJDIR}/$@ $<
+
+
+#
+# Use the C preprocessor to generate dependency files from input source
+# files.
+#
+# -I: XXX
+# -M: generate Makefile dependency target instead of preprocessing
+# -MG: assume missing files are generated files
+# -MF: write dependency list to .depend file where make will look for it
+# -MT: override target name
+#
+.SUFFIXES: .depend
+.in.depend:
+ cpp -I${INCLUDE} -M -MG -MF $@ -MT ${@:.depend=.html} $<
+
+# Create the final `.depend' file from all of the individual dependency files.
+.if !empty(SRCS)
+depend: ${SRCS:.in=.depend} _SUBDIRUSE
+ cat ${.ALLSRC} > .depend
+.endif
+
+
+#
+# Generate `*_html' HTML fragments that use <img> tag to link to images.
+#
+.SUFFIXES: .jpg .jpg_html
+.SUFFIXES: .png .png_html
+.jpg.jpg_html .png.png_html:
+ @# Copy original image to object dir with `_cp' appended to file name.
+ @# Make gets confused when two files have the same names
+ @# in different directories.
+ cp $? ${.OBJDIR}/${<F:R}_cp.${<F:E}
+
+ @# Generate thumbnail of image with `_thumb' appended to file name.
+ convert -resize 710x $? ${<F:R}_thumb.${<F:E}
+
+ @# Create HTML fragment that uses the thumbnail as a base image
+ @# that is a link to the full size (copied) image, like this:
+ @#
+ @# <a href="pic_cp.jpg"><img src="pic_thumb.jpg"
+ @#
+ @# NOTE: The <img> tag is not closed! You must close it, hopefully with:
+ @# alt="description of image for blind people" /></a>
+ echo "\t<a href='${<F:R}_cp.${<F:E}'><img src='${<F:R}_thumb.${<F:E}' " > $@
+
+#
+# Generate `*_html' html fragments that link to videos using <video> tag.
+#
+.SUFFIXES: .mp4 .mp4_html
+.SUFFIXES: .mov .mov_html
+.mp4.mp4_html .mov.mov_html:
+ @# Copy video from source to object directory.
+ cp $? ${.OBJDIR}/
+
+ @# Generate html code snippet using HTML5 video tag to show video.
+ echo "\t<video controls>" > $@
+ echo "\t\t<source src='${<F}' type='video/mp4'>" >> $@
+ echo "\t\tYour browser does not support the video tag." >> $@
+ echo "\t</video>" >> $@
+
+
+#
+# Transliterate the contents of various file types when they coincidentally
+# (not purposefully) contain HTML markup or C preprocessor directives.
+#
+# - turn '<' and '>' into HTML named character references so they are
+# displayed and not parsed
+# - turn '\' line continuation into HTML named character reference so they
+# do not get removed by the HTML parser
+# - turn '#' into HTML named character reference so the preprocessor doesn't
+# try and operate on it.
+#
+# Note dependency file names must be unique for this inference because all
+# target files will have .xliterate suffix.
+#
+.SUFFIXES: .c .html .in .txt
+.SUFFIXES: .xliterate
+.c.xliterate .html.xliterate .in.xliterate .txt.xliterate:
+ sed \
+ -e "s/</\</g" \
+ -e "s/>/\>/g" \
+ -e "s/\\\/\\/" \
+ -e "s/#/\#/g" \
+ $< > $@
+
+
+#
+# Make an HTML time attribute for direct inclusion in HTML. Populate the
+# "datetime" property with an appropriatly formatted date.
+# Use full names for day of week and month instead of default abbreviated ones.
+#
+FMT="+%A %B %e %H:%M:%S %Z %Y"
+_timestamp.gen: index.in
+ echo "<time datetime='`date +%Y-%m-%d`'>`date ${FMT}`</time>" > $@
+
+#
+# Generate a banner of the current directory for inclusion in HTML.
+#
+_dirbanner_html:
+ @echo " <pre class='small'>" > ${.OBJDIR}/$@
+ here=`cd ${.CURDIR}; basename $$PWD`; \
+ banner $$here >> ${.OBJDIR}/$@;
+ @echo "</pre>" >> ${.OBJDIR}/$@
+
+#
+# Plain file copy.
+#
+.for file in ${CP_OBJ}
+.if !exists(${.CURDIR}/${file})
+all:
+ @>&2 echo "html.mk: file '${file}' in CP_OBJ array does not exist."
+.else
+
+#
+# We can get away with using the same file name here and make still being
+# able to distinguish the files because we use absolute paths.
+#
+${.OBJDIR}/${file}: ${.CURDIR}/${file}
+ cp ${.CURDIR}/${file} $@
+
+all: ${.OBJDIR}/${file}
+
+.endif
+.endfor
+
+.include "obj.mk"
+.include "site.mk"
+.include "subdir.mk"
diff --git a/mk/obj.mk b/mk/obj.mk
@@ -0,0 +1,35 @@
+#
+# Originally taken from OpenBSD /usr/share/mk/bsd.obj.mk.
+#
+
+_SUBDIRUSE:
+
+obj! _SUBDIRUSE
+ @cd ${.CURDIR}; \
+ here=`/bin/pwd`/; bsdsrcdir=`cd ${TOP}; /bin/pwd`; \
+ subdir=$${here#$${bsdsrcdir}/}; \
+ if [[ $$here != $$subdir ]]; then \
+ dest=${DESTDIR}/$$subdir ; \
+ echo "$$here/obj -> $$dest"; \
+ if [[ ! -L obj || `readlink obj` != $$dest ]]; \
+ then \
+ [[ -e obj ]] && rm -rf obj; \
+ ln -sf $$dest obj; \
+ fi; \
+ if [[ -d ${DESTDIR} ]]; then \
+ [[ -d $$dest ]] || mkdir -p $$dest; \
+ else \
+ if [[ -e ${DESTDIR} ]]; then \
+ echo "${DESTDIR} is not a directory"; \
+ else \
+ echo "${DESTDIR} does not exist"; \
+ fi; \
+ fi; \
+ else \
+ dest=$$here/obj ; \
+ if [[ ! -d obj ]]; then \
+ echo "making $$dest" ; \
+ mkdir -p $$dest; \
+ $$SETOWNER $$dest; \
+ fi ; \
+ fi;
diff --git a/mk/site.mk b/mk/site.mk
@@ -0,0 +1,24 @@
+#
+# Site specific configuration.
+#
+# The directory to place out of tree builds.
+DESTDIR ?= /tmp/html.mk
+
+#
+# Helper targets for misc tasks.
+#
+
+#
+# Check files for trailing white space using `egrep`.
+# -H: show matched filename
+# -n: shows matched line in file
+# '[[:space:]]+$': matches at least one space or tab until end of line
+#
+trailingspace: _SUBDIRUSE
+ ! egrep -Hn '[[:space:]]+$$' ${.CURDIR}/${SRCS}
+
+#
+# Check spelling of all pages using `spell_ok' file for exceptions.
+#
+spell: _SUBDIRUSE
+ spell +${.CURDIR}/${TOP}/spell_ok ${.CURDIR}/${SRCS}
diff --git a/mk/subdir.mk b/mk/subdir.mk
@@ -0,0 +1,48 @@
+#
+# Originally taken from OpenBSD /usr/share/mk/bsd.subdir.mk.
+#
+
+# Make sure this is defined
+SKIPDIR?=
+
+_SUBDIRUSE: .USE
+.if defined(SUBDIR)
+ @for entry in ${SUBDIR}; do \
+ _newdir_="$${entry}"; \
+ if test X"${_THISDIR_}" = X""; then \
+ _nextdir_="$${_newdir_}"; \
+ else \
+ _nextdir_="$${_THISDIR_}/$${_newdir_}"; \
+ fi; \
+ _makefile_spec_=""; \
+ subskipdir=''; \
+ for skipdir in ${SKIPDIR}; do \
+ subentry=$${skipdir#$${entry}}; \
+ if [ X$${subentry} != X$${skipdir} ]; then \
+ if [ X$${subentry} = X ]; then \
+ echo "($${_nextdir_} skipped)"; \
+ break; \
+ fi; \
+ subskipdir="$${subskipdir} $${subentry#/}"; \
+ fi; \
+ done; \
+ if [ X$${skipdir} = X -o X$${subentry} != X ]; then \
+ echo "===> $${_nextdir_}"; \
+ ${MAKE} -C ${.CURDIR}/$${_newdir_} \
+ SKIPDIR="$${subskipdir}" \
+ $${_makefile_spec_} _THISDIR_="$${_nextdir_}" \
+ ${MAKE_FLAGS} \
+ ${.TARGET:S/^real//}; \
+ fi; \
+ done
+.endif
+
+
+.for t in all depend obj spellcheck trailingspace
+. if !target($t)
+$t: _SUBDIRUSE
+. endif
+.endfor
+.if !target(clean) && empty(.TARGETS:Mcleandir)
+clean: _SUBDIRUSE
+.endif
diff --git a/t/cp_happy.t b/t/cp_happy.t
@@ -0,0 +1,45 @@
+#
+# Happy path for CP, obj/ and file exists.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::File;
+use Test::More tests => 9;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . '/mk/html.mk';
+
+$cmd->write( 'copy.txt', 'some stuff here' );
+$cmd->subdir( 'destdir' );
+$cmd->write( 'Makefile', <<EOF );
+CP_OBJ = copy.txt
+DESTDIR = destdir
+SRCS =
+
+.include "$html_mk"
+EOF
+
+#
+# Create obj/ directory.
+#
+my $o = ".*//obj -> destdir/";
+
+$cmd->run( args => 'obj', chdir => $cmd->curdir );
+like( $cmd->stdout, qr{$o}, 'make obj stdout' );
+is( $cmd->stderr, '', 'make obj stderr' );
+is( $? >> 8, 0, 'make obj exit status' );
+
+#
+# Default make target should copy the file.
+#
+$o = "cp .*/copy.txt .*/obj/copy.txt";
+
+$cmd->run( chdir => $cmd->curdir );
+like( $cmd->stdout, qr{$o}, 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+file_exists_ok( $cmd->workdir . "/copy.txt" );
+file_exists_ok( $cmd->workdir . "/obj/copy.txt" );
+file_contains_like( $cmd->workdir . '/obj/copy.txt', qr/some stuff here/ );
diff --git a/t/cp_nodest.t b/t/cp_nodest.t
@@ -0,0 +1,30 @@
+#
+# CP file when not building into obj/.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::File;
+use Test::More tests => 5;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+$cmd->write( 'cp_file.txt', 'some file contents' );
+$cmd->write( 'Makefile', <<EOF );
+CP_OBJ = cp_file.txt
+SRCS =
+
+.include "$html_mk"
+EOF
+
+#
+# Silence is OK here I think.
+#
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+file_exists_ok( $cmd->workdir . '/cp_file.txt' );
+file_contains_like( $cmd->workdir . '/cp_file.txt', qr/some file contents/ );
diff --git a/t/cp_unhappy.t b/t/cp_unhappy.t
@@ -0,0 +1,54 @@
+#
+# CP_OBJ nonexistent file and file that is a directory.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::More tests => 9;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+#
+# 1) CP_OBJ nonexistent file.
+#
+
+my $e = "html.mk: file 'does_not_exist' in CP_OBJ array does not exist.";
+
+$cmd->write( 'Makefile', <<EOF );
+CP_OBJ = does_not_exist
+SRCS =
+
+.include "$html_mk"
+EOF
+
+$cmd->run( chdir => $cmd->curdir );
+
+is( $cmd->stdout, '', 'make stdout' );
+like( $cmd->stderr, qr{$e}, 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 2) CP_OBJ directory, obj exists
+#
+my $o = "cp .*/cp_dir .*/obj/cp_dir";
+$e = 'cp: .*/cp_dir is a directory \(not copied\)';
+
+$cmd->subdir( 'destdir', 'cp_dir' );
+$cmd->write( 'Makefile', <<EOF );
+CP_OBJ = cp_dir
+DESTDIR = destdir
+SRCS =
+
+.include "$html_mk"
+EOF
+
+$cmd->run( args => 'obj', chdir => $cmd->curdir );
+like( $cmd->stdout, qr{obj -> destdir}, 'make obj stdout' );
+is( $cmd->stderr, '', 'make obj stderr' );
+is( $? >> 8, 0, 'make obj exit status' );
+
+$cmd->run( chdir => $cmd->curdir );
+like( $cmd->stdout, qr{$o}, 'make stdout' );
+like( $cmd->stderr, qr{$e}, 'make stderr' );
+is( $? >> 8, 2, 'make exit status' );
diff --git a/t/dep_simple.t b/t/dep_simple.t
@@ -0,0 +1,70 @@
+#
+# make depend works on single file.
+#
+use Modern::Perl;
+use Test::File;
+use Test::Cmd;
+use Test::More tests => 19;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+$cmd->write( 'index.in', '' );
+$cmd->write( 'Makefile', <<EOF );
+.include "$html_mk"
+EOF
+
+#
+# 1) `make depend'
+#
+$cmd->run( args => 'depend', chdir => $cmd->curdir );
+
+my $o = "cpp .* -MF index.depend -MT index.html index.in";
+like( $cmd->stdout, qr{$o}, 'make depend stdout' );
+is( $cmd->stderr, '', 'make depend stderr' );
+is( $? >> 8, 0, 'make depend exit status' );
+
+# XXX: index.depend and .depend should have identical contents.
+file_exists_ok( $cmd->workpath . '/index.depend' );
+file_exists_ok( $cmd->workpath . '/.depend' );
+
+#
+# 2) `make'
+#
+$cmd->run( chdir => $cmd->curdir );
+
+$o = "cpp .* -P -o .*index.html .*index.in";
+like( $cmd->stdout, qr{$o}, 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+file_exists_ok( $cmd->workpath . '/index.html' );
+
+#
+# 3) Another `make' does nothing.
+#
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 4) Touch the source file and re-run `make'.
+#
+$cmd->write( 'index.in', '' );
+$cmd->run( chdir => $cmd->curdir );
+
+like( $cmd->stdout, qr{$o}, 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 5) Remove index.html and re-run `make'.
+#
+my $f = $cmd->workdir . "/index.html";
+is (unlink( $f ), 1, 'unlink success' );
+
+$cmd->run( chdir => $cmd->curdir );
+like( $cmd->stdout, qr{$o}, 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
diff --git a/t/srcs_missing.t b/t/srcs_missing.t
@@ -0,0 +1,21 @@
+#
+# The default SRCS file is missing.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::More tests => 3;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+$cmd->write( 'Makefile', <<EOF );
+.include "$html_mk"
+EOF
+
+my $e = "html.mk: file 'index.in' in SRCS array does not exist.";
+
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+like( $cmd->stderr, qr{$e}, 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
diff --git a/t/srcs_suffix.t b/t/srcs_suffix.t
@@ -0,0 +1,65 @@
+#
+# No and strange file suffixes in SRCS array.
+# These are different cases because make behaviour is dependant on suffixes.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::More tests => 12;
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+#
+# 1) File with no suffix in SRCS array and does not exist
+#
+$cmd->write( 'Makefile', <<EOF );
+SRCS = no_file_suffix
+
+.include "$html_mk"
+EOF
+
+# This is an ok error message.
+my $e = "html.mk: file 'no_file_suffix' in SRCS array does not exist.";
+
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+like( $cmd->stderr, qr{$e}, 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 1a) File with no suffix in SRCS array but file exists.
+# XXX Strange behaviour... this should be an error with a message.
+#
+$cmd->write( 'no_file_suffix', '' );
+
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 2) File with bad suffix in SRCS array that does not exist.
+#
+$cmd->write( 'Makefile', <<EOF );
+SRCS = bad.sfx
+
+.include "$html_mk"
+EOF
+
+$e = "html.mk: file 'bad.sfx' in SRCS array does not exist.";
+
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+like( $cmd->stderr, qr{$e}, 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# 2b) File with bad suffix in SRCS array but file exists.
+# XXX Strange behaviour... this should be an error with a message.
+#
+$cmd->write( 'bad.sfx', '' );
+
+$cmd->run( chdir => $cmd->curdir );
+is( $cmd->stdout, '', 'make stdout' );
+is( $cmd->stderr, '', 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
diff --git a/t/xliterate.t b/t/xliterate.t
@@ -0,0 +1,62 @@
+#
+# #include "foo.xliterate" works.
+#
+use Modern::Perl;
+use Test::Cmd;
+use Test::File::Contents;
+use Test::More tests => 7;
+
+
+my $cmd = Test::Cmd->new( prog => '/usr/bin/make', workdir => '' );
+my $html_mk = $cmd->here . "/mk/html.mk";
+
+$cmd->write( 'c_frag.c', '#include <stdio.h>' );
+$cmd->write( 'html_frag.html', '<head><body> <img /> </body>' );
+$cmd->write( 'in_frag.xliterate', 'line one \n
+line two' );
+$cmd->write( 'txt_frag.xliterate', 'whatever' );
+
+$cmd->write( 'index.in', <<EOF );
+#include "c_frag.xliterate"
+--
+#include "html_frag.xliterate"
+--
+#include "in_frag.xliterate"
+--
+#include "txt_frag.xliterate"
+EOF
+
+$cmd->write( 'Makefile', <<EOF );
+.include "$html_mk"
+EOF
+
+# make depend
+$cmd->run( args => 'depend', chdir => $cmd->curdir );
+like( $cmd->stdout, qr/.*/, 'make stdout' );
+is( $cmd->stderr, "", 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+# make
+$cmd->run( chdir => $cmd->curdir );
+like( $cmd->stdout, qr/sed .*/, 'make stdout' );
+is( $cmd->stderr, "", 'make stderr' );
+is( $? >> 8, 0, 'make exit status' );
+
+#
+# Compare index.html with known good output.
+#
+my $good = <<'EOF';
+
+
+#include <stdio.h>
+--
+<head><body> <img /> </body>
+--
+line one \n
+line two
+--
+whatever
+EOF
+
+file_contents_eq_or_diff( $cmd->workdir . "/index.html", $good,
+ 'index.html contents transliterated' );