Still hoping for a response...

On May 29, 12:06 am, BBunny <[email protected]> wrote:
> Can anyone suggest a grep search/replace or other technique for changing
> root-relative links of a Web site to document-relative? The site is
> site-root is identified in BBEdit's preferences as a Web site. There's a
> utility written to do this for a very early version of Dreamweaver (it will
> also change all document-relative links to root-relative, if that's desired,
> which it isn't), and it works, but only on the open document. The sitewide
> feature doesn't work. My site has nearly 3,000 html files, so opening each
> document and running the script would be extremely time-consuming, and the
> author is not going to update the script. I do not know javascript and I'm
> not that savvy with regular expressions either, so I would appreciate any
> suggestions for running a script like this sitewide in BBEdit.
>
> Thanks.
>
> For reference, the Dreamweaver utility is supposed to use this regex to
> select the files sitewide:
>
> .+\.html?$
>
> And it uses this script (which works, but only in the open document):
>
> /*******************************************/
>
> /* Change links to document/root relative. */
>
> /* Version 1.5.1 (28 Dec 2005) */
>
> /* Jason Dalgarno <[email protected]> */
>
> /*******************************************/
>
> /*
>
> * Copyright (C) 2005 Jason Dalgarno <[email protected]>
>
> *
>
> * This library is free software; you can redistribute it and/or modify it
> under
>
> * the terms of the GNU Lesser General Public License as published by the
> Free
>
> * Software Foundation; either version 2.1 of the License, or (at your
> option)
>
> * any later version.
>
> *
>
> * This library is distributed in the hope that it will be useful, but
> WITHOUT
>
> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> FITNESS
>
> * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
> more
>
> * details.http://www.gnu.org/licenses/lgpl.txt
>
> */
>
> function canAcceptCommand()
>
> {
>
> var sr, doc;
>
> sr = dreamweaver.getSiteRoot();
>
> doc = dreamweaver.getDocumentDOM('document');
>
> /*
>
> * If a site is defined, the document has been saved, the document is saved
>
> * in a defined site and the document is HTML.
>
> */
>
> return (sr && doc && doc.URL && doc.URL.indexOf(sr) == 0 && fileIsHTML(doc)
> && !hasBaseHref(doc)) ? true : false;
>
> }
>
> function commandButtons()
>
> {
>
> return Array('Document relative', 'initRelativity("document", "document")',
>
> 'Root relative', 'initRelativity("document", "root")',
>
> 'Absolute (http://...)', 'initRelativity("document", "absolute")',
>
> 'Sitewide - Document relative', 'initRelativity("site", "document")',
>
> 'Sitewide - Root relative', 'initRelativity("site", "root")',
>
> 'Get latest version', 'fetchLatest()',
>
> 'Cancel', 'window.close()',
>
> 'Help', 'relativityHelp()');
>
> }
>
> function relativityHelp()
>
> {
>
> dreamweaver.browseDocument(dreamweaver.getConfigurationPath() +
> '/Shared/JSN/relativity/help.htm');
>
> }
>
> /**
>
> * Check if the current document/file is a HTML document
>
> *
>
> * @param object Document
>
> * @return boolean True is file is an html document, false if not.
>
> */
>
> function fileIsHTML(doc)
>
> {
>
> /*
>
> * .search(/<html/i) is to allow for <HTML> in uppercase.
>
> *
>
> * Relativity cannot work on a partial document that is included elsewhere
>
> * by SSI or PHP (for example) as it will not be able to resolve the base
>
> * URL correctly.
>
> */
>
> return doc.getParseMode() == 'html' &&
> doc.documentElement.outerHTML.search(/<html/i) != -1;
>
> }
>
> /**
>
> * If a file has a <base href="..." /> do not modify links
>
> *
>
> * @param object Document
>
> * @return boolean True if file has base href, false if we can safely modify
> it
>
> */
>
> function hasBaseHref(doc)
>
> {
>
> var base, i, ret = false;
>
> base = doc.getElementsByTagName('BASE');
>
> for (i = 0; i < base.length; ++i) {
>
> if (base[i].href) {
>
> ret = true;
>
> break;
>
> }
> }
>
> return ret;
>
> }
>
> /**
>
> * Read updater file from remote server and check version numbers
>
> */
>
> function fetchLatest()
>
> {
>
> /*
>
> * remote file goes like this:
>
> * version=1.2.3
>
> * url=http://www.example.com/dwextension.mxp
>
> * filename=filename_for_local_file.ext
>
> * title=Text for download dialog title
>
> * beforemessage=Some message to show before downloading.
>
> * donemessage=Message to show after file has been downloaded.
>
> */
>
> var currentVersion, updaterUrl, versionFile, latest, pairs, i, params,
> confirmMsg, gotUpdate;
>
> currentVersion = '1.5.1';
>
> updaterUrl = 'http://www.microwaved.plus.com/dw/relativityupdate.txt';
>
> versionFile = MMHttp.getText(updaterUrl);
>
> if (versionFile.statusCode == 200) {
>
> latest = new Array;
>
> pairs = versionFile.data.replace(/\r\n?/, '\n').split('\n');
>
> for (i = 0; i < pairs.length; ++i) {
>
> params = pairs[i].split('=');
>
> if (params.length == 2) {
>
> latest[params[0]] = params[1].replace(/\s+$/, '');
>
> }
> }
>
> if (latest.version && latest.url && latest.filename && latest.title
>
> && latest.beforemessage && latest.donemessage) {
>
> latest.beforemessage = latest.beforemessage.replace(/\\n/g, '\n');
>
> latest.donemessage = latest.donemessage.replace(/\\n/g, '\n');
>
> if (latest.version == currentVersion) {
>
> alert('No update available');
>
> } else {
>
> confirmMsg = 'Update available\n\n';
>
> confirmMsg += 'Latest version is ' + latest.version;
>
> confirmMsg += ' (currently using ' + currentVersion + ')\n\n';
>
> confirmMsg += latest.beforemessage + '\n\n';
>
> confirmMsg += 'Download the update?';
>
> if (confirm(confirmMsg)
>
> && (gotUpdate = MMHttp.getFile(latest.url, true, 'file:///C|/' +
> latest.filename,
>
> 'Download update - ' + latest.title)) && gotUpdate.statusCode) {
>
> if (gotUpdate.statusCode == 200) {
>
> alert('Download complete.\n\n' + latest.donemessage);
>
> } else {
>
> alert('Error retrieving file.')
>
> }
> }
> }
> } else {
>
> alert('Updater file does not follow expected format. Got this instead:\n\n'
> + pairs.join('\n'));
>
> }
> } else {
>
> // 404, host not found, not online etc
>
> alert('Updater file not found');
>
> }
> }
>
> /**
>
> * Change link relativity
>
> *
>
> * @param string Relativity direction, 'document' or 'root'
>
> */
>
> function Relativity(relativeTo)
>
> {
>
> var doc, ignore, ignore2, tagAttrs, siteRoot, siteUrl;
>
> /**
>
> * Read tag name and attributes file
>
> */
>
> function readTagAttributes()
>
> { // Read tag name and attributes file
>
> var fileContents, i, tagAttribs;
>
> fileContents = DWfile.read(dreamweaver.getConfigurationPath()
>
> + '/Shared/jsn/relativity/uris.txt').replace(/\r\n?/g, '\n').split(/\n/);
>
> for (i = 0; i < fileContents.length; ++i) {
>
> tagAttribs = fileContents[i].split(' ');
>
> tagAttrs[tagAttribs[0]] = tagAttribs.slice(1);
>
> }
> }
>
> /**
>
> * getElementsByTagName without translated elements
>
> *
>
> * There are two problems with the regular getElementsByTagName
>
> * implementation:
>
> * 1) Translated elements are included, but DW will choke if you try to
>
> * modify them.
>
> * 2) Elements with a name or id attribute beginning with a number are
>
> * inserted a second time in the array with its name as the key,
>
> * causing the array to be longer than it should be with empty elements
>
> * along the way. For example, if the only <a> tag in a document is
>
> * <a name="100"></a>, doc.getElementsByTagName('A').length is 101.
>
> *
>
> * @param object Partial document
>
> * @param string Tag name
>
> * @return array Non-translated elements
>
> */
>
> function getElements(docPart, tag)
>
> {
>
> var eles, cleaned, i, offsets, hasTranslatedContent;
>
> eles = docPart.getElementsByTagName(tag);
>
> hasTranslatedContent = docPart.getElementsByTagName('MM:BEGINLOCK').length ?
> true : false;
>
> cleaned = new Array;
>
> for (i = 0; i < eles.length && eles[i]; ++i) {
>
> if (hasTranslatedContent) {
>
> /*
>
> * translated element offsets refer to translated source,
>
> * offsetsToNode refers to actual source, if they don't match
>
> * the element is translated
>
> */
>
> offsets = doc.nodeToOffsets(eles[i]);
>
> if (doc.offsetsToNode(offsets[0], offsets[1]) == eles[i]) {
>
> cleaned.push(eles[i]);
>
> }
> } else {
>
> cleaned.push(eles[i]);
>
> }
> }
>
> return cleaned;
>
> }
>
> /**
>
> * Get root relative path
>
> *
>
> * @param string Document relative path
>
> * @return string Root relative path
>
> */
>
> function toRoot(path)
>
> {
>
> var trailSlash, dotSlash;
>
> if (path.substr(0, 2) == './') { // clean ./ paths
>
> if (path.length > 2) {
>
> path = path.substr(2);
>
> } else {
>
> path = 'PATHWASDOTSLASH'; // placeholder if path was just ./
>
> dotSlash = true;
>
> }
> }
>
> // remember if original path had trailing slash
>
> trailSlash = (RegExp('/$').test(path)) ? '/' : '';
>
> // dreamweaver.relativeToAbsoluteURL does not work as documented
>
> path = dreamweaver.relativeToAbsoluteURL(doc.URL, siteRoot, path);
>
> // remove everything before site root, -1 to retain leading slash
>
> path = path.substr(siteRoot.length - 1);
>
> path += trailSlash; // replace trailing slash if needed
>
> if (dotSlash) {
>
> // remove ./ placeholder
>
> path = path.replace(/PATHWASDOTSLASH$/, '');
>
> }
>
> return path;
>
> }
>
> /**
>
> * Get document relative path
>
> *
>
> * @param string Root relative path
>
> * @return string Document relative path
>
> */
>
> function toDoc(path)
>
> {
>
> var up, pathbits, filebits, s, i;
>
> // build arrays of path and document url folder structure
>
> pathbits = path.substr(1).split('/');
>
> // remove file:// path to site root
>
> filebits = doc.URL.substr(siteRoot.length).split('/');
>
> // number of levels to go up to get back to site root
>
> up = filebits.length - 1;
>
> s = 0; // path slice counter
>
> for (i = 0; i < filebits.length; ++i) {
>
> if (up == 0 && filebits[i] == pathbits[i]) {
>
> path = pathbits[0];
>
> } else if (filebits[i] == pathbits[i]) {
>
> /*
>
> * if filebit is the same as pathbit it can be discarded
>
> * increment s to remove bit from the path decrement up as it's
>
> * one less level to go back up the directory tree
>
> */
>
> ++s;
>
> --up;
>
> } else {
>
> /*
>
> * taking a different path, add the required number of up ../ to
>
> * the begining of the path then take the remaining bits of the
>
> * path that are different and join them back together.
>
> */
>
> path = '';
>
> for (i = 0; i < up; ++i) {
>
> path += '../';
>
> }
>
> path += pathbits.slice(s).join('/');
>
> break; // stop checking
>
> }
> }
>
> if (!path) {
>
> /*
>
> * original path was to the current directory, filebits and pathbits
>
> * all matched no bits remain, no levels to go up
>
> */
>
> path = './';
>
> }
>
> return path;
>
> }
>
> /**
>
> * Run command on document
>
> *
>
> * @param string Source document ('document' or file:// path)
>
> * @param boolean Save document (true if doing sitewide, false otherwise)
>
> * @return string ok - file was modified
>
> * savefailed - unable to save
>
> * nothtml - the file was not a HTML document.
>
> * basehref - file has base href, not modified
>
> */
>
> this.useDoc = function(sourceDoc, save)
>
> {
>
> var tag, attrs, eles, j, k, attr;
>
> doc = dreamweaver.getDocumentDOM(sourceDoc);
>
> if (!fileIsHTML(doc)) {
>
> ret = 'nothtml';
>
> } else if (hasBaseHref(doc)) {
>
> ret = 'basehref';
>
> } else {
>
> if (doc.getAttachedTemplate()) {
>
> editable = doc.getEditableRegionList();
>
> } else {
>
> editable = Array(doc.documentElement);
>
> }
>
> for (i = 0; i < editable.length; ++i) {
>
> for (tag in tagAttrs) {
>
> attrs = tagAttrs[tag];
>
> eles = getElements(editable[i], tag);
>
> for (j = 0; j < eles.length; ++j) {
>
> for (k = 0; k < attrs.length; ++k) {
>
> attr = attrs[k];
>
> path = eles[j].getAttribute(attr);
>
> if (path) {
>
> if (siteUrl && relativeTo != 'absolute'
>
> && path.substr(0, siteUrl.length) == siteUrl) {
>
> /*
>
> * If it is an absolute http:// URL to the
>
> * current site reduce it to a root relative
>
> * path.
>
> */
>
> path = path.substr(siteUrl.length);
>
> if (path == '') {
>
> path = '/';
>
> }
>
> if (relativeTo == 'root') {
>
> eles[j].setAttribute(attr, path);
>
> }
> } else if (path.substr(0, 7) == 'file://') {
>
> /*
>
> * If we have a file:/// URL pointing to
>
> * local files reduce it to a root relative
>
> * path.
>
> */
>
> if (path.substr(0, siteRoot.length) == siteRoot) {
>
> path = path.substr(siteRoot.length);
>
> } else if (path.substr(0, escapedSiteRoot.length) == escapedSiteRoot) {
>
> path = path.substr(escapedSiteRoot.length);
>
> }
>
> if (path == '') {
>
> path = '/';
>
> }
>
> eles[j].setAttribute(attr, path);
>
> }
>
> switch (relativeTo) {
>
> case 'document':
>
> if (path.charAt(0) == '/') {
>
> eles[j].setAttribute(attr, toDoc(path));
>
> }
>
> break;
>
> case 'root':
>
> if (!ignore.test(path)) {
>
> eles[j].setAttribute(attr, toRoot(path));
>
> }
>
> break;
>
> case 'absolute':
>
> if (!ignore2.test(path)) {
>
> if (path.charAt(0) != '/') {
>
> path = toRoot(path);
>
> }
>
> eles[j].setAttribute(attr, siteUrl + path);
>
> }
>
> break;
>
> }
> }
> }
> }
> }
> }
>
> if (!save) {
>
> ret = 'ok';
>
> window.close();
>
> } else if (DWfile.write(doc.URL, doc.documentElement.outerHTML)) {
>
> ret = 'ok';
>
> } else {
>
> ret = 'savefailed';
>
> }
> }
>
> if (save) {
>
> dreamweaver.releaseDocument(doc);
>
> }
>
> return ret;
>
> }
>
> /**
>
> * Pass all files matching regex to function
>
> *
>
> * @param object Regular expression
>
> */
>
> this.sitewide = function(filesRegex)
>
> {
>
> var logFile, dirs, dir, files, i, filename, rv, subDirs;
>
> // debug - uncomment the following line to log what happens
> file://localhost/Users/frances_cherman/Desktop
>
> // logFile = 'file:///~/Desktop/relativitylog.txt';
>
> logFile = 'file:///localhost/Users/frances_cherman/Desktop';
>
> dirs = Array(siteRoot);
>
> while (dirs.length) {
>
> dir = dirs.pop();
>
> if (logFile) {
>
> DWfile.write(logFile, 'Directory: ' + dir + '\n', 'append');
>
> }
>
> files = DWfile.listFolder(dir + '/*', 'files'); // list all files
>
> for (i = 0; i < files.length; ++i) {
>
> filename = dir + '/' + files[i];
>
> if (filesRegex.test(files[i])) {
>
> DWfile.write(logFile, 'Starting: ' + filename + '\n', 'append');
>
> rv = this.useDoc(filename, true);
>
> if (logFile) {
>
> if (rv == 'ok') {
>
> DWfile.write(logFile, 'Done: ' + filename + '\n', 'append');
>
> } else if (rv == 'nothtml') {
>
> DWfile.write(logFile, 'Not HTML: ' + filename + '\n', 'append');
>
> } else if (rv == 'basehref') {
>
> DWfile.write(logFile, 'Has base href: ' + filename + '\n', 'append');
>
> } else if (rv == 'savefailed') {
>
> DWfile.write(logFile, 'Save failed: ' + filename + '\n', 'append');
>
> }
> }
> } else if (logFile) {
>
> DWfile.write(logFile, 'No match: ' + filename + '\n', 'append');
>
> }
> }
>
> subDirs = DWfile.listFolder(dir, 'directories');
>
> for (i = 0; i < subDirs.length; ++i) {
>
> dirs.push(dir + '/' + subDirs[i]);
>
> }
> }
> }
>
> /**
>
> * @return string file:// path to site root
>
> */
>
> this.getSiteRoot = function()
>
> {
>
> return siteRoot;
>
> }
>
> // Regular expression of links to ignore
>
> ignore = /^(#|\/|[a-z][a-z\d\+\-\.]*:|<)/i;
>
> ignore2 = /^(#|[a-z][a-z\d\+\-\.]*:|<)/i;
>
> /*
>
> * Don't modify if link begins with either
>
> * # anchor
>
> * / root relative, ie doesn't need changing
>
> * [a-z][a-z\d\+\-\.]*: RFC 2396 scheme, external link
>
> * < server markup, only ignore if at begining of link, otherwise what goes
>
> * before is path, eg don't touch <?php echo $dir;?>file.html but do
>
> * change file.html?foo=<?php echo $foo; ?>
>
> *
>
> * ignore2 for absolute, as above but without /
>
> */
>
> tagAttrs = new Array(); // Tags and attributes to check
>
> siteRoot = dreamweaver.getSiteRoot(); // Site root directory
>
> escapedSiteRoot = escape(siteRoot);
>
> siteUrl = document.forms[0].siteurl.value;
>
> readTagAttributes();
>
> }
>
> /**
>
> * Start here
>
> *
>
> * @param string 'document' - Change current document only
>
> * 'site' - Change entire site
>
> * @param string Relativity direction, 'document', 'root' or 'absolute'
>
> */
>
> function initRelativity(mode, relativeTo)
>
> {
>
> var siteUrl, validUrl, cfgFile, rel;
>
> siteUrl = document.forms[0].siteurl.value;
>
> validUrl = /^https?:\/\/[a-zA-Z0-9.-]+(:\d{1,5})?$/;
>
> if (siteUrl != '' && !validUrl.test(siteUrl)) {
>
> document.forms[0].siteurl.value = '';
>
> alert('Ignoring invalid site URL ' + siteUrl);
>
> }
>
> // remember files regex and site url for next time
>
> cfgFile = MMNotes.open(dreamweaver.getConfigurationPath()
>
> + '/Shared/jsn/relativity/relativity.htm', true);
>
> MMNotes.set(cfgFile, 'siteurl', document.forms[0].siteurl.value);
>
> MMNotes.set(cfgFile, 'filesregex', document.forms[0].filesregex.value);
>
> MMNotes.close(cfgFile);
>
> rel = new Relativity(relativeTo);
>
> if (mode == 'document') {
>
> rel.useDoc('document', false);
>
> } else {
>
> var siteroot, filesRegex, confirmStr;
>
> // remove trailing slash
>
> siteroot = rel.getSiteRoot().replace(/\/$/, '');
>
> filesRegex = RegExp(document.forms[0].filesregex.value);
>
> confirmStr = 'Are you sure you want change links to ' + relativeTo + '
> relative in files in\n';
>
> confirmStr += siteroot + '\n';
>
> confirmStr += 'Matching the regular expression ' + filesRegex + '\n\n';
>
> confirmStr += 'All open files should be saved before continuing.\n';
>
> confirmStr += 'If you do not have a backup of your entire site hit
> cancel.\n\n';
>
> confirmStr += 'This may take some time.';
>
> if (siteroot && DWfile.exists(siteroot) && filesRegex &&
> confirm(confirmStr)) {
>
> MM.setBusyCursor();
>
> rel.sitewide(filesRegex);
>
> MM.clearBusyCursor();
>
> alert('Change link relativity finished');
>
> /*
>
> * You don't get a list of files on the alert anymore (as of 1.1.1),
>
> * it was beyond useless for all but the smallest of sites anyway
>
> * and as no one has ever complained I can only assume no one cares.
>
> * It is safe to assume the files were modified if all of the
>
> * following conditions are true:
>
> * - File is in the site
>
> * - File name matches the regex
>
> * - File is HTML
>
> * - There wasn't a problem saving (such as a readonly file)
>
> */
>
> window.close();
>
> } else {
>
> alert('Sitewide cancelled');
>
> }
> }
> }
>
> /**
>
> * Recall files regex and site url settings for form
>
> */
>
> function recallSettings()
>
> {
>
> var cfgFile, filesRegex;
>
> cfgFile = MMNotes.open(dreamweaver.getConfigurationPath()
>
> + '/Shared/jsn/relativity/relativity.htm', true);
>
> document.forms[0].siteurl.value = MMNotes.get(cfgFile, 'siteurl');
>
> filesRegex = MMNotes.get(cfgFile, 'filesregex');
>
> if (!filesRegex) {
>
> filesRegex = '.+\\.html?$';
>
> }
>
> document.forms[0].filesregex.value = filesRegex;
>
> MMNotes.close(cfgFile);
>
>
>
>
>
>
>
> }

-- 
You received this message because you are subscribed to the 
"BBEdit Talk" discussion group on Google Groups.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
<http://groups.google.com/group/bbedit?hl=en>
If you have a feature request or would like to report a problem, 
please email "[email protected]" rather than posting to the group.
Follow @bbedit on Twitter: <http://www.twitter.com/bbedit>

Reply via email to