Gulp任务用文档相对URL替换所有根相对URL

时间:2018-04-04 11:58:29

标签: html .htaccess url-rewriting gulp

有4种不同的网址类型;

  1. 绝对 http://www.example.com/images/icons.png
  2. 文档相对 ../images/icons.png
  3. 根相对 /images/icons.png
  4. 协议相对 //www.example.com/images/icons.png
  5. 我有一个使用Jigsaw构建的大型静态文件站点(html,css,js)。该框架使用PHP模板并将它们编译为静态HTML。我也在使用Gulp任务来编译资产(sass,js..etc)。

    使用Jigsaw的构建过程我可以使用完整的绝对路径/网址(http://example.com/path-to/page)或根目录(/path-to/page)构建网站。

    这很好,但现在客户希望该网站使用Document-Relative,因为他们现在在一个子目录中托管该网站,其URL指向该子目录。

    E.g。 http://example.com会指向http://xx.server.com/hosted-files/directory

    我的问题是Jigsaw不允许使用文档相对URL。是否有一个gulp / node脚本我可以用来转换所有引用(图像源,链接,css路径......等)?或者是否有另一种解决方案(例如使用.htacccess)?

    TLDR;

    我需要使用 Document-Relative 路径和URL替换多个HTML文件和目录中的任何 Absolute Root-Relative 引用。或者是否有另一种解决方案(例如使用.htacccess)?

2 个答案:

答案 0 :(得分:0)

我设法解决了我自己的问题,我觉得这是一个“hacky”修复。

我基本上创建了一个自定义gulp插件,用Document-Relative路径替换URL / paths..etc。

所有其他任务完成后,

gulpfile.js - relative-urls任务就会运行。

const relative = require('./tasks/document-relative');
gulp.task('relative-urls', function() {
    return gulp.src('build/**/*.html')
        .pipe( relative({
            directory: 'build',
            url: 'http://localhost:8000',
        }) )
        .pipe( gulp.dest('build') );
});

./ tasks / document-relative.js - 插件

'use strict';

const fs            = require('fs');
const PluginError   = require('plugin-error');
const through       = require('through2');

const PLUGIN_NAME   = 'document-relative';

let count = 0;

module.exports = function(options) {

    // Remove slashes from beginning and end of string
    const strip_slashes = (string) => {
        return string ? string.replace(/^\/|\/$/g, '') : null;
    }

    // Users options object
    options = options || {};

    // Cleanup options
    const base_dir  = strip_slashes(options.directory);
    const url       = strip_slashes(options.url) + '/';

    return through({
        objectMode: true,
        writable: true,
        readable: true
    },
    function(file, enc, callback) {
        count++;

        // Check for null file
        if (file.isNull()) {
            return callback(null, file);
        }

        if (file.isStream()) {
            this.emit('error', new PluginError(PLUGIN_NAME, 'Stream not supported!'));
            return callback(null, file);
        }

        if (file.isBuffer()) {

            // Get contents of this file
            let html        = file.contents.toString(enc);

            // This files full path (/home/usr/project/build/page/example/index.html)
            const path      = file.path;

            // Path task was run from (/home/usr/project/)
            const cwd       = file.cwd+( base_dir ? '/'+base_dir : '' );

            // Project specific path (/page/example/index.html)
            const relative  = path.replace(cwd, '');

            // Get array of directories ['page', 'example', 'index.html']
            let paths       = strip_slashes(relative).split('/');

            // Remove last item ['page', 'example']
            paths.pop();

            // Add ../ for nth number of paths in array
            let rel_path    = paths.length === 0 ? '' : ('../'.repeat(paths.length));

            // Replace dom attributes (e.g. href="/page/example")
            html = html.replace( /(?:(?!="\/\/)="\/)/g, '="'+rel_path );

            // Replace inline background (e.g. background: url('/image/something.jpg'))
            html = html.replace( /url\(\'\//g, 'url(\''+rel_path );
            html = html.replace( /url\('\//g, 'url(''+rel_path );

            // If user defined URL, match and remove
            if (url && url.length) {
                html = html.replace( new RegExp(url, 'g'), rel_path );
            }

            // Overwrite file
            fs.writeFileSync(file.path, html, {
                encoding: enc,
                flag:'w'
            });

            return callback();
        }
    });
};

这基本上会打开我的构建文件夹中的所有.html个文件,计算每个文件的深度路径(/folder1/folder2/index.html)并替换url的任何实例({{3 }})../重复计算的路径数。

答案 1 :(得分:0)

节点有path.relative

  • 请阅读Levi Coles自己的answer,以了解urldirectory的来源。
const path = require("path");

// create a regular expression from your url property.
const domain_expression = new RegExp(url);

// Once you have an offending 'href' you can do this.
// - Here 'href' is Absolute, but this same code would work
//   with Root-Relative paths too.
const href = "http://localhost:8000/images/icons.png";
const file_index = href.lastIndexOf("/") + 1;
const file_component = href.substring(file_index);
const root_relative = href.replace(domain_expression, "");
const relative_href = path.relative(`${directory}/${root_relative}`, directory);
const _href = relative_href + file_component;
// _href = ../../icons.png