Script-based Website Maintenance



Hyperlinking

You can use m4 to maintain hyperlinks.

Extracting URI path components

These macros extract different parts of a pathname:

define(`FILE_PARENT',`regexp($1,`\(\([^/]*/\)*\)',``\1'')')dnl
define(`FILE_LEAF',`regexp($1,`\([^/]*\)$',``\1'')')dnl
define(`FILE_BASE',`regexp($1,`\(.*\)\.\([^.]*\)$',``\1'')')dnl

…so this:

define(`afile',``a/long/list/of/path/elements.html'')dnl
FILE_PARENT(`afile')
FILE_LEAF(`afile')
FILE_BASE(`afile')

…expands to:

a/long/list/of/path/
elements.html
a/long/list/of/path/elements

The macro EXTSPLIT splits the dot-separated components of its argument into a comma-separated list:

define(`EXTSPLIT_2',
`regexp($1,`\(.*\)\.\([^.]*\)$',`EXTSPLIT_2(``\1''),``\2''')')dnl
define(`EXTSPLIT_1', `shift($@)')dnl
define(`EXTSPLIT', `EXTSPLIT_1(EXTSPLIT_2(``.'$1'))')dnl

The macro NOLANGS removes from its second argument extensions listed by its first:

define(`JOIN_3', `ifelse(regexp($2,switchexp($1)),`-1',``.'$2')')dnl
define(`JOIN_2',
`ifelse($2,,,`JOIN_3(`$1',`$2')`'JOIN_2(`$1',shift(shift($@)))')')dnl
define(`JOIN',`substr(JOIN_2($@),1,,1)')dnl

define(`NOLANGS',`JOIN(`$1',EXTSPLIT(shift($@)))')dnl

You can use it to remove language suffixes from file names, e.g.:

NOLANGS(```en'',``fr'',``de''',``this.is.my.de.long.fr.file.name'')

…yields:

this.is.my.long.file.name

Complementarily, ONLYLANGS extracts the suffixes:

define(`JOINX_3', `ifelse(regexp($2,switchexp($1)),`-1',,`,`$2'')')dnl
define(`JOINX_2',
`ifelse($2,,,`JOINX_3(`$1',`$2')`'JOINX_2(`$1',shift(shift($@)))')')dnl
define(`JOINX',`shift($@)')dnl

define(`ONLYLANGS',`JOINX(JOINX_2(`$1',EXTSPLIT(shift($@))))')dnl

For example:

ONLYLANGS(```en'',``fr'',``de''',``this.is.my.de.long.fr.file.name'')

…yields:

`de',`fr'

Relative URIs

This macro generates the correct number of ../ URI elements to get to the top of a directory structure, given a position within it:

define(`TOP_URI',`patsubst(FILE_PARENT(`$1'),`[^/]*/',`../')')

…so this:

TOP_URI(``a/long/list/of/path/elements.html'')

…expands to:

../../../../../

REL_URI yields the path to its second argument relative to its first:

define(`REL_URI',
`ifelse(regexp($1,`\([^/]*/\)'),-1,`$2',
regexp($1,`\([^/]*/\)',``\1''),regexp($2,`\([^/]*/\)',``\1''),
`REL_URI(`regexp($1,`[^/]*/\(.*\)',``\1'')',
`regexp($2,`[^/]*/\(.*\)',``\1'')')',
`TOP_URI(`$1')$2')')

Assuming that FILE is the path of the file currently being processed, and INDEXBASE is the basename of the directory index file, the macro RELURI will give a suitable relative URI to the file specified by the argument:

define(`DIR_URI',`ifelse($1,,``./'',`$1')')
define(`NOINDEX',
`ifelse(FILE_BASE(`FILE_LEAF(`$1')'),INDEXBASE,`FILE_PARENT(`$1')',`$1')')
define(`RELURI',`DIR_URI(`REL_URI(`FILE',`NOINDEX(`$1')')')')

Also, rather than returning an empty string (which some browsers don't like), it will yield ./.

Basic links

What do links have in common?

Here's a macro which takes those as arguments:

define(`LINK',`ifelse(CONTEXT,`CONTEXT',
``<a href="'$1`"'ifelse($3,,,``
title="'INCTXT(``PCDATA'',`$3')`"'')`'ifelse($4,,,``
class="'$4`"'')`>'INCTXT(``LINK'',`$2')`</a>'',
`$2')')

Further links within the current one are prevented by setting CONTEXT. Links and mark-up within the title are similarly prevented.

For external links to other websites, you may want the content to match the title:

define(`TLINK',`LINK(`$1',`$2',`ifelse($3,,`$2',`$3')',
shiftn(3,$@))')

Internal links

This macro can detect whether a local link is really necessary:

define(`LLINK',`ifelse($2,,
`ifelse($1,FILE,
`SPAN(`ifelse($6,,`$3',`$6')',`$7')',
`SPAN(`LINK(`RELURI(`$1')',`$3',`$4',`$5')',`$8')')',
`ifelse($1,FILE,
`ifelse($2,ifdef(`ANCHOR',`ANCHOR'),
`SPAN(`ifelse($6,,`$3',`$6')',`$7')',
`SPAN(`LINK(``#'$2',`$3',`$4',`$5')',`$8')')',
`SPAN(`LINK(`RELURI(`$1')`#'$2',`$3',`$4',`$5')',`$8')')')')

The first argument gives path of the document from the top of the website, and the second the anchor if needed.

Now, you can create links without specifying the suffix (in case you want to change it):

define(`LLINK_X',`LLINK(`$2`'$1',shift(shift($@)))')

define(`LLINK_HTML',`LLINK_X(`HTML_SUFFIX',$@)')
define(`LLINK_SVG',`LLINK_X(`SVG_SUFFIX',$@)')

The next macro allows you to mark an area as being addressable by an anchor, which LLINK can detect:

define(`INANCHOR',`pushdef(`ANCHOR',`$1')`'$2`'popdef(`ANCHOR')')dnl

Use it in combination with macros that generate anchor points:

INANCHOR(``help'',

`H1(``Help'', `ANCHOR')`

<p>Hello!</p>'')

You can create navigation menus that don't list/link the item for the current page. First, define how each menu item should be marked up:

define(`NAVLINK',`SPAN(`LLINK_HTML(`$1',,`$2',`ifelse($3,,`$2',`$3')',
``NAV'',,``UNNAV'')',``ITEM'')')dnl

Now define how to build a navigation menu:

define(`NAVLIST_',`NAVLINK($1)`'ifelse($#,1,,
`SPAN(``&nbsp;|&nbsp;'',``SEP'')`'NAVLIST_(shift($@))')')dnl

define(`NAVLIST',``<div class=NAVBAR><p>'NAVLIST_($@)`</p></div>'')dnl

If you want to use a menu more than once per page, put the data into a macro:

define(`NAVBAR',`NAVLIST(
```index'', `LANG(``eo'', ``Prezento'', ``Intro'')', `LANG(``eo'',
``Prezento'', ``Introduction'')'',

```contact'', `LANG(``eo'', ``Kontakto'', ``Contact'')', `LANG(``eo'',
``Kontakta informo'', ``Contact information'')'',

```nails'', `LANG(``eo'', ``Ungoj'', ``Nails'')', `LANG(``eo'',
``Ungoj'', ``Finger Nails'')'',

```webpages'', `LANG(``eo'', ``Retpag'x`oj'', ``Webpages'')'',

```software'', `LANG(``eo'', ``Komputaj'x`oj'', ``Software'')'')')dnl

…and use it wherever needed.

Document relationships

In HTML, you can specify the document's relationship with another document using the LINK element type. Here's a macro to generate such an element:

define(`REL',
``<link rel="'$1`"'ifelse($2,,,
`` type="'$2`"'')` href="'$3`"'ifelse($4,,,
`` title="'INCTXT(``PCDATA'', `$4')`"'')`'ifelse($5,,,
`` media="'$5`"'')`>'')dnl

Now a macro for such links to local documents:

define(`LREL',`ifelse(FILE,$3,,
`REL(`$1',`$2',`RELURI(`$3')`'ifelse($4,,,``#'$4')',shiftn(4,$@))')')dnl

Now to specialise for each media type:

define(`LREL_X',`LREL(`$3',`$2',`$4`'$1',shiftn(4,$@))')dnl
define(`LREL_HTML',`LREL_X(`HTML_SUFFIX',``text/html'',$@)')dnl
define(`LREL_CSS',`LREL_X(`CSS_SUFFIX',``text/css'',$@)')dnl

Examples:

LREL_HTML(``BOOKMARK'', ``admin/search'', ``help'', ``Search help'')
LREL_CSS(``STYLESHEET'', ``styles/screen'',,, ``SCREEN'')

Here's a summary of the arguments:

  1. the link type,

  2. the location, relative to the top of the website, and without the suffix,

  3. the optional anchor,

  4. the optional title,

  5. the optional media.



Updated: 2007-May-11 16:56 GMT
Contact Steven Simpson

Ĉi tiu paĝo disponeblas ĉi-lingve, laŭ via krozila agordo.