Получить объекты из файлов js, прочитанных как строки, и обработать их в одном файле с помощью gulp - PullRequest
0 голосов
/ 01 июля 2018

Я пытаюсь прочитать файлы TypographyJS с помощью Gulp, чтобы создать список шрифтов, используемых для облегчения загрузки соответствующих шрифтов Google.

Пока моя задача выглядит так:

gulp.task('buildFontListFile', function (event) {
  return gulp.src(`node_modules/+(typography-theme*)/dist/index.js`)
    .pipe(debug({title: 'typography-theme:'}))
    .pipe(gulp.dest('gulpTest/fonts'));
});

Итак, я правильно нацеливаюсь на нужные мне файлы, но сейчас просто копирую копии в новый каталог. Файлы, которые я читаю, выглядят так:

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});


var theme = {
  title: 'Noriega',
  baseFontSize: '18px',
  baseLineHeight: 1.61,
  headerFontFamily: ['Lato', 'sans-serif'],
  bodyFontFamily: ['Lato', 'sans-serif'],
  bodyWeight: 400,
  headerWeight: 700,
  boldWeight: 700,
  googleFonts: [{
    name: 'Lato',
    styles: ['400', '700']
  }],
  scaleRatio: 1.618
};
exports.default = theme;

Что мне нужно сделать, так это извлечь ключ googleFonts из этого экспорта по умолчанию и обработать каждую запись в строке, которая выглядит следующим образом:

Lato:400,700&subset=latin

Вывод содержимого ключей в этом формате должен быть достаточно легким, но чтение содержимого файла - это то, что я не могу понять в настоящее время.

Каков наилучший способ прочитать содержимое этих файлов и выполнить некоторую обработку, прежде чем, наконец, вывести файл, который выглядит примерно так?

Lato:400,700&subset=latin
Source+Sans+Pro:200,400,700&subset=latin,latin-ext

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

[ Второй ответ ]

Вот еще одна версия, в которой используется концепция, о которой я думал в первом ответе, но которая не сработала позже. Если бы объекты theme (которые возвращаются как строки fs.readFileSync) могли быть преобразованы обратно в обычные объекты JavaScript, мы могли бы использовать точечную нотацию для доступа ко всем ее свойствам.

Но мы не хотим использовать eval, метод Function(string) работает хорошо, пока мы добавляем return object к строке. См. MDN: как заменить eval на Function ()

И код будет немного более надежным, если получить всю строку темы вместо различных строк в файле. Бонус заключается в том, что вызовы object.properties возвращают более приятный формат, чем в другой версии ответа. Нет кавычек и запятых, которые необходимо удалить.

const gulp = require("gulp");
const glob = require('glob');
const fs = require('fs');

gulp.task('default', function () {

  // like gulp.src but makes it easy to work on individual files one at a time
  glob("./+(folder*)/index.js", function (er, files) {

    // used later to avoid an extra newline after the last entry added
    const numFiles = files.length;
    let thisFileNum = 1;

    files.forEach(file => {

      const contents = fs.readFileSync(file, "utf8");

      // get the entire theme object, using the dotall flag to include newlines
      let themeVarString = contents.match(/(var theme.*)exports/s)[1];

      // Since the theme object is now a string, we need to convert it to a javascript object again
      //   so we can access its values easily.
      //   But don't use eval, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
      //   Use Function() instead, but it should return the object so append "return theme;"
      //     And call it immediately () so it reurns the theme object (as an javascript object!)

      let themeObject = Function(`${themeVarString}return theme;`)();

      // now themeObject is a regular javascript object, we can access its properties with dot notation
      // nice, name is returned as Lato or Source Sans Pro : no quotes
      // make Source Sans Pro into Source+Sans+Pro
      let fontName = themeObject.googleFonts[0].name.replace(/\s+/g, "+");

      // and the styles are returned as 200,400,700 : no quotes or spaces!

        // now build the next line to append to the file 
      let line = `${fontName}:${themeObject.googleFonts[0].styles}&subset=latin`;
        // I don't know where you got the 'latin-ext' on one of your fonts

        // if the last file, omit the newline
      if (thisFileNum === numFiles) {
        fs.appendFileSync('modified.txt', line);
      }
      else {
        fs.appendFileSync('modified.txt', line + '\n');

      }

      thisFileNum++;
    });
  });
});
0 голосов
/ 01 июля 2018

Попробуйте это:

const gulp = require("gulp");
const glob = require('glob');
const fs = require('fs');

gulp.task('default', function () {

  // like gulp.src but makes it easy to work on individual files one at a time
  glob("node_modules/+(typography-theme*)/dist/index.js", function (er, files) {

    // used later to avoid an extra newline after the last entry added
    const numFiles = files.length;
    let thisFileNum = 1;

    files.forEach(file => {

      const contents = fs.readFileSync(file, "utf8");

      // look for "name: 'Lato',"
      let fontName = contents.match(/name:\s*'(.*)'/);

      // look for "styles: ['400', '700']"
      let fontStyle = contents.match(/styles:\s*\['(.*)'\]/);

      // get rid of the ' and , in fontStyle [the regexp returns ""'400', '700']""
      fontStyle = fontStyle[1].replace(/,|'/g, "");

      // in fontNames like "Souce Sans Pro", replace the spaces with +'s
      fontName = fontName[1].replace(/\s+/g, "+");

      // in fontStyles like "200 400 700", replace the spaces with ,'s
      fontStyle = fontStyle.replace(/\s+/g, ",");

      // now build the next line to append to the file 
      let line = `${fontName}:${fontStyle}&subset=latin`;
      // I don't know where you got the 'latin-ext' on one of your fonts

      // if the last file, omit the newline
      if (thisFileNum === numFiles) {
        fs.appendFileSync('modified.txt', line);
      }
      else {
        fs.appendFileSync('modified.txt', line + '\n');
      }

      thisFileNum++;
    });
  });
});

Я не знаю, порядок новых записей в файле гарантирован.

...