Code Monkey home page Code Monkey logo

control-replacer's Introduction

Скрипт для автозамены

Скрипт предназначен для замены всех вхождений контролов, когда они переносятся из одного модуля в другой, либо переименовывается. Также скрипт позволяет переносить утилиты, переименовать опцию у контрола, переименовать/удалить css переменную или класс, а также позволяет передать свою настройку для замены.

Также есть возможность исправить проблему, когда был запущен скрипт массовой обработки git-репозиториев , но по какой-то причине ему не удалось запушить изменения. И при повторном запуске скрипта, ничего не происходило. Чтобы исправить эту проблему, нужно запустить скрипт с флагом fixCommit

Готовый скрипт можно скачать из репозитория, либо собрать самому. Для этого нужно скачать проект, выполнить npm i и npm run build

Как работает

Необходимо запустить файл dist/replacer.js, а также подготовить json файл с настройкой.

Запуск скрипта

Переименовывания контролов:

node replacer.js config.json

Переименовывания опций контрола:

node replacer.js replaceOpt config.json

Переименовывания css переменных или классов:

node replacer.js cssReplace config.json

Свое переименование:

node replacer.js customReplace config.json

Сброс правок, на случай если скрипт запущен ошибочно, либо с некорректным config.json:

node replacer.js resetGit config.json

Сброс коммита, на случай когда нужно перезапустить скрипт для создания mr:

node replacer.js fixCommit config.json

JSON файл настроек

Описание

Описание файла конфигурации для переименовывания контролов:

Если модуль полностью переносится, то можно использовать сокращенную запись для module и controls[i].newModuleName, указав /* в конце. Например Name переносится в Controls-Name, тогда module: "Name/*", а controls[i].newModuleName: "Controls-Name/*"

{
  "path": "Путь к репозиториям, где нужно выполнить замену",
  "replaces": [
    {
      "module": "Текущее имя модуля",
      "newModule": "Новое имя модуля. Стоит указывать когда весь модуль со всеми контролами переносится",
      "controls": [
        {
          "name": "Текущее имя контрола",
          "newName": "Новое имя контрола. Если контрол не переименовывается, то свойство указывать не нужно",
          "newModuleName": "Новое имя модуля. Стоит указывать если из модуля выносится 1 определенный контрол"
        }
      ]
    }
  ],
  "maxFileSize": "Максимальный размер файла. По умолчанию 50"
}

Описание файла конфигурации для переименовывания опций:

{
  "path": "Путь к репозиториям, где нужно выполнить замену",
  "replaces": [
    {
      "thisOpt": "Текущее имя опции",
      "newOpt": "Новое имя опции",
      "module": "Имя модуля, для которого нужно осуществить переименовывание",
      "control": "Имя контрола, в котором нужно переименовать опцию"
    }
  ],
  "maxFileSize": "Максимальный размер файла. По умолчанию 50"
}

Описание файла конфигурации для переименовывания css переменных или классов:

{
  "path": "Путь к репозиториям, где нужно выполнить замену",
  "replaces": [
    {
      "varName": "Текущее имя переменной или класса. Важно указывать имя css переменной полностью(--css-var), а класс указывать с '.'",
      "newVarName": "Новое имя переменной или класса",
      "isRemove": "Класс или переменная полностью удаляется"
    }
  ],
  "maxFileSize": "Максимальный размер файла. По умолчанию 50"
}

Описание файла конфигурации для пользовательского переименовывания:

{
  "path": "Путь к репозиториям, где нужно выполнить замену",
  "replaces": [
    {
      "reg": "Регулярное выражение",
      "flag": "Флаг для регулярного выражения. По умолчанию g",
      "replace": "То как производится замена",
      "scriptPath": "Путь до пользовательского скрипта"
    }
  ],
  "maxFileSize": "Максимальный размер файла. По умолчанию 50"
}

При кастомной замене стоит правильно указывать значение в replace. Замена осуществляется следующим образом:

str.replace(new RegExp(congig.reg, config.flag || "g"), config.replace);

Если нужно выполнить какое-то свое преобразование, то можно в scriptPath передать путь до своего скрипта. Скрипт должен быть следующего вида:

interface ICustomScriptParam {
  path: string; // Полный путь до файла
  file: string; // Имя файла с расширением
    fileContent: string; // Содержимое файла
}

interface ICustomScriptResult {
    status: boolean; // Статус выполнения скрипта. Если вернется true, то значение файла перезапишется на значение в result
    result?: string; // Новое содержимое файла
    error?: string; // Ошибки найденные при обработке файла
}

export function run(param: ICustomScriptParam): ICustomScriptResult {
    return {
        status: true,
        result: 'Результат работы скрипта'
    };
}

Для режимов resetGit и fixCommit, можно указать любой их указанных выше файлов конфигурации, либо создать отдельный. Важно чтобы в файле было указано поле path.

Примеры файлов конфигурации

Замена утилиты Controls/utils:oldUtil на Controls/newUtils:newUtil

{
  "path": "",
  "replaces": [
    {
      "module": "Controls/utils",
      "controls": [
        {
          "name": "oldUtils",
          "newName": "newUtil",
          "newModuleName": "Controls/newUtils"
        }
      ]
    }
  ]
}

Перенос всего модуля из одного места в другое. Например: Name/* в Controls-Name/*

{
  "path": "",
  "replaces": [
    {
      "module": "Name/*",
      "controls": [
        {
          "name": "",
          "newModuleName": "Controls-Name/*"
        }
      ]
    }
  ]
}

Перенос отдельных частей модуля из одного места в другое. Например: Name/Input в Controls-Name/Input

{
  "path": "",
  "replaces": [
    {
      "module": "Name/Input",
      "controls": [
        {
          "name": "*",
          "newModuleName": "Controls-Name/Input"
        }
      ]
    }
  ]
}

Замена Controls/buttons:ArrowButton на Controls/extButtons:ArrowButton

{
  "path": "",
  "replaces": [
    {
      "module": "Controls/buttons",
      "controls": [
        {
          "name": "ArrowButton",
          "newModuleName": "Controls/extButtons"
        }
      ]
    }
  ]
}

Замена Controls/toggle:Tumbler на Controls/toggle:NewTumbler

{
  "path": "",
  "replaces": [
    {
      "module": "Controls/toggle",
      "controls": [
        {
          "name": "Tumbler",
          "newName": "NewTumbler"
        }
      ]
    }
  ]
}

Замена Controls/list:Button на Controls-button/list:Button

{
  "path": "",
  "replaces": [
    {
      "module": "Controls/list",
      "controls": [
        {
          "name": "Button",
          "newModuleName": "Controls-button/list"
        }
      ]
    }
  ]
}

Замена Controls/toggle:Tumbler на Controls-toggle/Tumbler. Обратите внимание на newName, если свойство не указывать, то произойдет переименование модуля(Controls-toggle/Tumbler:Tumbler), но при указании пустой строки, контрол подключается как модуль.

{
  "path": "",
  "replaces": [
    {
      "module": "Controls/toggle",
      "controls": [
        {
          "name": "Tumbler",
          "newName": "",
          "newModuleName": "Controls-toggle/Tumbler"
        }
      ]
    }
  ]
}

Замена опции myClassName на className у контрола Controls/toggle:Toggle

{
  "path": "",
  "replaces": [
    {
      "thisOpt": "myClassName",
      "newOpt": "className",
      "module": "Controls/toggle",
      "control": "Toggle"
    }
  ]
}

Замена css переменной --oldName на --newName

{
  "path": "",
  "replaces": [
    {
      "varName": "--oldName",
      "newVarName": "--newName"
    }
  ]
}

Замена css класса oldClassName на newClassName

{
  "path": "",
  "replaces": [
    {
      "varName": ".oldClassName",
      "newVarName": ".newClassName"
    }
  ]
}

Дополнительно

Важно чтобы в module и newModuleName разделение было сделано через / иначе возможна некорректная работа. Также в controls можно не указывать newName и newModuleName, в таком случае значения поставятся из name и module. При этом, одно из значений должно быть заполнено, иначе скрипт посчитает что правки не нужны и завершит работу.

Подобное сделано для удобства, когда переименовывается только модуль или контролл.

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

Что корректно работает

Скрипт автоматически вносит правки в wml файлы. А также может вносить правки в ts, tsx и другие файлы.

Корректно обрабатываются следующие сценарии:

import { Tumbler } from "Controls/toggle";

<Tumbler />;
import { Tumbler as View } from "Controls/toggle";

<View />;
import { default as toggle } from "Controls/toggle";

<toggle.Tumbler />;
import {Tumbler, Switch} from 'Controls/toggle';

<Tumbler/>
<Switch/>

Если из исходной библиотеки выносится 1 контрол, то скрипт сам создаст или найдет нужный импорт, и поместит туда новый контрол

При переименовывании css переменных или классов корректно отрабатываются все случаи связанные с переменными. Также если указан isRemove=true, то определение переменной удалится.

Что нестабильно работает с заменой контролов

Сейчас есть проблемы с импортом следующего вида:

import * as toggle from "Controls/toggle";

Скрипт самостоятельно не сможет обработать подобные сценарии, на что кинет ошибку. Но при этом скрипт сможет внести правки по использованию контрола, и заменит

<toggle.Name>

на

<toggle.NewName>

Скрипт не тронет сам импорт, так как не знает как нужно его заменить. Если вы полностью переносите весь модуль, то можно указать это название в replaces.newModule, в таком случае скрипт заменит импорт для модуля. Свойство стоит использовать тогда, когда полностью переименовывается модуль, в противном случае скрипт отработает некорректно.

Также если контрол использовался так Controls.LoadingIndicator, а нужно превратить его в Controls.loading:Indicator, то скрипт самостоятельно не сможет подобное обработать, а любая попытка провернуть подобное может обернуться ошибками. Возможно, когда-то подобный функционал появится, но на данный момент в нем нет необходимости.

При переносе модуля, когда используется конструкции с указанием в имени модуля "/*", и указанием нового имени контрола, произойдет переименовывание самого модуля, старое имя контрола при этом не заменится.

Что не корректно работает с переименовыванием опций

Скрипт не сможет обработать случаи, когда контрол вставляется в другой контрол в качестве шаблона с передачей опций.

<Async templateName="Controls.toggle:Tumblet" templateOptions="{optionName: ...}" />

и

<Async templateName="Controls.toggle:Tumblet">
    <ws:templateOptions optionName="..."/>
</Async>

Также не отработают случай с использованием spread оператора

<Tumbler {...{ optionName: "..." }} />

Что не корректно работает с переименовыванием классов

Скрипт корректно отрабатывает все случаи с заменой классов. Но могут возникнуть сложности, когда isRemove=true. Скрипт не сможет корректно отработать в следующих конструкциях:

.myClass .removeClass {
. . .
}

и

.removeClass {
  /* ... */

  .template {
    /* ... */
  }
}

Данные конструкции скрипт пропустит, но выкинет ошибку, чтобы можно было вручную внести правку. Все остальные конструкции отрабатывают корректно.

Дополнительно

Через скрипт можно переименовывать различные утилиты, но есть вероятность что будет проблемы в редких случаях(см "Что работает нестабильно").

Скрипт проходится по всем файлам в директории, но не смотрит файлы больше 50mb, но можно настроить другое ограничение используя maxFileSize(не рекомендуется устанавливать большие значения)

О найденных проблемах или идеях по улучшению можно писать мне

control-replacer's People

Contributors

max36895 avatar

Watchers

 avatar

control-replacer's Issues

баги и фичи

Сейчас добавлен экстренный костыль чтобы решить следующую проблему
Name/Input.ts
export default ...

В подобном случае утилита не корректно отрабатывала, из-за чего был добавлен быстрый костыль, который вроде как работает, но нужно внимательно посмотреть и протестить(см последний mr)

Также вылезло 2 проблемы:

  1. когда полностью переносится модуль. Файл конфига становится больше, и есть вероятность что-то потерять. Правильнее будет в конфиге указать короткую запись(Name/*), что скажет что все файлы из директории перенесутся в новую.
  2. проблема с s3mod и s3srv, нужно добавить их поддержку. Скорей всего это будет новый режим работы, так как там есть id и path. При этом путь нужно правильно определить и подставить.

Переименовывание значений для опции

Подумать над возможность добавления возможности по переименовыванию значений для опции.
В принципе подобное сделать не сложно, сложность заключается в следующих моментах
opt={value ? 1:2} opt={value}

В теории это может заменить добавление кастомного replacer

Рефакторинг

Отрефакторить код.
Поправить сложные для понимания места, произвести оптимизацию кода, добавить больше примеров, покрывающих все сценарии.
На данный момент, есть места, которая можно оптимизировать и получить выигрыш по производительности, но это нужно проверить.
Подготовить новость на свой страничке online, и предложить переезд на git.sbis.ru

Ошибочные сообщения об ошибке в лог файле

Сейчас скрипт корректно отрабатывает все кейсы, когда переименовывается или переименовывается контрол. Но когда из всей либо выносится не все контролы, то в лог файл кидается ошибка, которая по факту ошибочка.
Возможно стоит убрать эту проверку совсем, либо найти способ как-то доработать момент, чтобы избежать ошибочных срабатываний. Отключать полностью скорей всего не стоит, так как есть вероятность (< 1%) что скрипт не сможет что-то заменить. А проверять каждый файл не самая хорошая идея.

  • такой проверки при прочих заменах нет

Косяк в импортах

Сейчас есть косяк с заменой импортом.
Проблема возникает когда контрол превращается в модуль.
Ошибка связана с некорректной заменой и возникает когда имя заменяемое на default есть где-то выше в файле

переименовывание опций

есть косяк с переименовыванием опций.
повторяется в случаях, когда компонент вставляют внутри async, в таком случае мы не сможет отработать сценарии вида
<Async name={...} nameOptions={{replacedOpt:...}}
Стоит найти решение, либо забить, так вроде не очень важно, главное чтобы сработало переименовывание компонента, что отрабатывает корректно.

Удаление css переменных

Есть небольшая недоработка с удалением css переменных.
Связана она с тем, что переменная удаляется, а строка остается. Стоит также удалять и строку.

Пример
Исходные данные:
--first: 12px;
--remove: 0;
--second: 13px;
Итоговый результат:
--first: 12px;

--second: 13px;
Ожидаемый результат:
--first: 12px;
--second: 13px;

import type { IDataConfig } from '...';

Скрипт лажает при следующем сценарии
import type { IDataConfig } from '...';
преобразует в
import { type IDataConfig } from '...';

Это связано с автопостановкой пробелов.

Также есть проблема для импорта вида:
import {
IDataConfig,
Test2
} from '...';
Скрипт тупо приведет все в 1 строку

Откат

Добавить команду, которая будет делать git reset --hard
На всякий случай если скрипт сделает херню

Убрать проверку модуля

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

  • стоит либо чистить файл с логами, либо создавать новый по дате

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.