Как автоматически создавать файлы и сэкономить время с помощью волшебных лесов

kak avtomaticheski sozdavat fajly i sekonomit vremya s pomoshhyu volshebnyh?v=1656572414

Прежде чем начать: В этой статье используется пример кода JavaScript/Node.js, но вы можете перенести эти понятия на любой язык, используя соответствующие инструменты.

Увлекательное вступление

Случалось ли вам в своих проектах создавать одни и те же файлы снова и снова?

Я также.

У меня болят пальцы!

Я не удивлен. Вы забираете работу у роботов.

Создание одних и тех же файлов многократно скучное и ненужное.

TLDR? Я понял вас – вот демо

1*DVXreOfKQqtyY4CfLxiJ8w
Магическая автоматизация – как и обещали.

Покажи мне код

Я уважаю ваше чувство срочности – я перейду к погоне.

Код

Мы хотим автоматизировать создание файлов – поэтому вы все появились сегодня. Сначала нам нужно определить файлы, которые мы хотим создать.

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

Я разделил это на четыре шага. Просто говорю вам сейчас, чтобы вы могли управлять своими ожиданиями. Если вы не можете справиться с чем-то длиннее трех шагов, то мы в беде…

Шаг 1: Шаблоны

Установите их один раз и получите прибыль.

Нам нужны шаблоны. Я использовал шаблонные буквы, но поступайте так, как вам понятно — будьте креативными.

Вот файлы, которые я создаю каждый раз, когда создаю компонент React:

  1. index.jsx
  2. {Component}.test.js
  3. {Component}.sass

Примечание: {Component} предполагает интерполяцию строки.

Я тестирую с помощью Jest и использую шаблон create-react-app. Я знаю, что сегодня многие люди предпочитают CSS-in-JS, но привет. Дайте мне знать в комментариях, что вам интересно.

В любом случае – вот мы:

const templates = {
  
  index: name => `// @flow
import React from 'react';
import './${name}.css';
// TODO: write rest of ${name} component
const ${name} = () => (
  <div className="${name.toLowerCase()}">
    <span>rest of component</span>
  </div>
);
export default ${name};`,
  
  test: name => `// TODO: TDD
import { shallow, render } from 'enzyme';
import renderer from 'react-test-renderer';
import React from 'react';
import ${name} from '.';
const component = <${name} />;
describe('The ${name} component', () => {
  it('renders correctly', () => {
    const wrapper = render(component);
    expect(wrapper.hasClass('${name.toLowerCase()}')).toBeTruthy();
    const tree = renderer.create(component).toJSON();
    expect(tree).toMatchSnapshot();
  });
});`,
  
  sass: name => `.${name.toLowerCase()}
  background: initial`,
};

Это самый сложный фрагмент кода, который вы увидите здесь – pinky promise.

Итак, у нас есть объект с тремя свойствами: index, test и sass. Каждая из них содержит функцию, принимающую имя и возвращающую шаблон с интерполированным именем. Кажется законным.

Шаг 2: Давайте создадим несколько функций!

Мы используем модуль fs, упакованный из Node. Это восхитительно. Он делает многое.

Мы используем некоторые функции со стрелками и немного функционального программирования. Не бойтесь – просто уходите.

Синтаксис функции двойной стрелки называется карриированием. Ничего страшного, если это выглядит странно. Я был напуган, когда впервые увидел это, но это позволяет делать очень крутые вещи. На самом деле, вот краткая демонстрация:

const fs = require('fs');

const fileExists = path => file => fs.existsSync(`${path}/${file}`);

const fileExistsInSrc = fileExists('/src'); // file => fs.existsSync(`${path}/${file}`)

fileExistsInSrc('index.js') // true || false

Следовательно, это карри с частичным применением – это тоже закрытие.

Боковая панель: Надеюсь, что никто не призывает меня здесь из-за некоторых технических вопросов, но, пожалуйста, преследуйте меня в комментариях, если нуждаетесь.

Давайте продолжим:

const fs = require('fs');

const fileExists = path => file => fs.existsSync(`${path}/${file}`);

const writeToPath = path => (file, content) => {
  const filePath = `${path}/${file}`;

  fs.writeFile(filePath, content, err => {
    if (err) throw err;
    console.log("Created file: ", filePath);
    return true;
  });
};

Сначала требуем fs. Нам это нужно в нашей жизни.

Тогда объявляем файл существует как выражение функции.

Наконец-то у нас есть еще одно выражение функции, которое называется writeToPath. Это занимает путь и возвращает другую функцию, принимающую a файл строка и содержание этого файла. Затем он записывает файл или выдает ошибку (худший сценарий).

Вы правильно понимаете? Мы создаем некоторые файлы.

Шаг 3: Встречайте Чокидара

Интересный факт: это слово на хинди.

Челкидар – (Индия) сторож, смотритель, сторож; тот, кто живет в «челках», полицейском участке или часовом доме.

Но мы говорим о пакете npm. Он основан на нашем новом друге fs, и вы можете использовать его для многих замечательных вещей.

Он следит за нашими файлами, как ястреб.

Ну не совсем как ястреб.

Это не птица.

Как и вообще.

Во всяком случае, вот код…

const chokidar = require("chokidar");

const watcher = chokidar
  .watch("src/components/**", { ignored: /node_modules/ })
  .on("addDir", (path, event) => {
    const name = path.replace(/.*\/components\//, "");
    const goodToGo = /^[^\/_]*$/.test(name);
    if (goodToGo) createFiles(path, name);
  });

Поначалу мы его требуем.

Дальше мы определяем, что мы хотим смотреть. Я наблюдаю за src/компоненты каталог, но вы можете просмотреть любой набор путей. Вы можете даже передать массив путей. Если вы не узнаете ** участвовать в src/components/** – это называется узором глобуса.

После этого мы определяем какие события мы хотим прослушать. Я слушаю только добавление каталога из .on(«addDir») но вы можете слушать другие события.

Далее давайте вытащим название компонента, заменив что-либо перед именем компонента:

src/components/Header/components/Title

становится

Title

Наконец-то мы проверим, передает ли имя компонента это регулярное выражение:

/^[^\/_]*$/

Так что если на нем нет косой черты или подчеркивания — можно идти. Это позволяет избежать ошибочного загрязнения папок __tests__ или вложенных/каталогов.

Шаг 4: Пора создать несколько файлов!

Вы добились последнего шага. Поздравляю! Это было очень здорово.

Эта следующая функция имеет точное название createFiles.

Это немного грязно – его можно переделать.

Заранее прошу прощения, если код ниже вас оскорбил.

Давайте копаемся:

function createFiles(path, name) {
  const files = {
    index: "index.jsx",
    test: `${name}.test.js`,
    sass: `${name}.sass`
  };

  if (name !== "components") {
    const writeFile = writeToPath(path);
    const toFileMissingBool = file => !fileExists(path)(file);
    const checkAllMissing = (acc, cur) => acc && cur;

    const noneExist = Object.values(files)
      .map(toFileMissingBool)
      .reduce(checkAllMissing);

    if (noneExist) {
      console.log(`Detected new component: ${name}, ${path}`);
      Object.entries(files).forEach(([type, fileName]) => {
        writeFile(fileName, templates[type](name));
      });
    }
  }
}

Поэтому наверху мы объявляем файлы объект – это список строк имен файлов, которые мы вводим имя параметр и. Вы могли заметить, что он имеет те же ключи, что и шаблоны объект. Это важно.

The если утверждение очень специфично для моей настройки. Я не хочу создавать свои файлы если новая папка называется компонентами. Я создаю только компоненты внутри вложена папка компонентов.

  • writeFile это наша функция writeToPath частично применен. Это функция, которая создает файл по заданному пути при вызове с именем файла и содержимым.
  • toFileMissingBool принимает имя файла и возвращает true, если файл не существует в заданном пути. Я знаю, что названия функций удивительны, но я обещаю, что это имеет больше смысла в нескольких строках.
  • checkAllMissing это функция, к которой мы собираемся перейти уменьшить. Он принимает два логических значения и возвращает true, если оба истинны. Это булевая алгебра. Мы также используем уменьшить методом Массив. Не бойтесь сокращения. Это очень круто и очень полезно в такой ситуации.

Поговорим о переменной noneExist. Если это правда, то ни один из файлов, которые мы хотим создать, не существует в новой папке. Идея заключается в том, что вы не возитесь с папкой только потому, что в ней нет тестового файла или sass. Возможно, эта папка не требуется.

const noneExist = Object.values(files)
  .map(toFileMissingBool)      
  .reduce(checkAllMissing);

Вот почему я создал эти удивительно названные функции выше.

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

Итак, если они все правда, потом noneExist есть также правда. Но если хотя бы один ошибочный, потом noneExist будет ошибочный.

Надеюсь, ты всё это получил. Это немного во рту.

Последний бит кода:

Object.entries(files).forEach(([type, fileName]) => {
  writeFile(fileName, templates[type](name)); 
});

Берем ключ (тип) и значение (имя файла) и напишите файл по заданному пути с содержимым соответствующего шаблона.

фин.

0*rv8KkV_Kvdfj941i
«Большая морская черепаха, плывущий по океану на пляже Капутас», Рендал Руис на Unsplash

Эта картина морской черепахи показывает, насколько свободны вы, видимо, чувствуете себя, теперь вы все автоматизировали.

Если вам нужен весь код для автоматического создания компонентов реакции, то он здесь.

Дайте мне знать, что вы думаете – оставайтесь на связи.

Скажите мне, если вы найдете какие-нибудь ошибки.

Следите за мной в Twitter, Medium или Github.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *