TauCetiStation / TauCetiClassic

Франкенштейн жив
GNU Affero General Public License v3.0
142 stars 418 forks source link

[Task] [WiP] Рефакторинг пенкодов #10134

Open volas opened 2 years ago

volas commented 2 years ago

Там всё очень плохо, предлагаю подобный вариант для рефакторинга proc/parsebbcode()

  1. Десятки replacetext стоит заменить на один проход по тексту с findtext([*])
  2. Для этого все коды нужно вынести в ассоциативный список вида:
    #define OPEN_TAG 1
    #define CLOSE_TAG 2
    global/list/pencodes = list(
    "center" = list(OPEN_TAG = "<center>", CLOSE_TAG = "</center>")
    ...
    "bh" = list(OPEN_TAG = "<div style='border-width: 4px; border-style: solid; padding: 10px; text-align: center; font-weight: bold;'>", CLOSE_TAG = "</div>")
    )

    (есть идеи как сделать это без многоуровневых списков?)

  3. Нужен лимит на некоторые из тегов, включить сюда текущий fields и некоторые из последних добавленных пенкодов что могут убить клиент при абузе
    global/list/pencodes_limits = list(
    "field" = 30,
    "sfield" = 30,
    "bh" = "5",
    ...
    )

    (можно сделать лимиты частью общего списка пенкодов выше)

  4. Опциональные пенкоды, которые разбросаны по билду вне parsebbcode() (в основном на бумаге) нужно будет перенести в качестве TRUE/FALSE флагов в parsebbcode, типо (черновой вариант)
    proc/parsebbcode(text, colour = "black", crayon = FALSE, fields = FALSE, ntlogo = FALSE)
    ...
    list/use_pencodes = pencodes
    if (crayon)
      use_pencodes -= list("*", "hr", "small", "list") // или инвентировать флаг и добавлять их при !crayon
    if (ntlogo)
      use_pencodes += list("nt" = list(OPEN_TAG = "<img src='bluentlogo.png'>"))
    ... и т.п.

    todo: списки нужно сделать по другому, как-то без дополнительных инициализаций и создания временных списков при каждом запуске прока...

  5. (WiP) Сам проход будет выглядеть примерно как-то так, пишу уставший по памяти рефов и очень примерно, могут быть неточности
    proc/parsebbcode(text, ...)
    ...
    var/static/regex/bbcode_regex = regex(@"[.*]")
    var/last_find_pos = findtext(input, bbcode_regex)
    var/last_parsed_pos = 0
    var/new_text = ""
    while(last_find_pos)
      new_text += copytext(text, last_parsed_pos, last_find_pos)
      var/bbcode = //спарсить со строки текущий найденный bb-code
      last_parsed_pos += last_find_pos + char_length("\[bbcode\]")
      if(bbcode in use_pencodes)
         if(use_pencodes[CLOSE_TAG])
              // если есть закрывающий тэг - попробовать найти парный закрывающий bb-тэг дальше, иначе игнорируем
              ...
         if(pencodes_limits[bbcode] && ...) // проверить, если мы вне лимита... лимиты еще где-то временно сохранять
              ...
         new_text += use_pencodes[OPEN_TAG] // еще где-то закрывающие тэги должны быть...
      ...
      last_find_pos = findtext(input, bbcode_regex)

UPD: пофигу, я поплыл :weary: запощу как есть, потом вернусь со свежей головой. Проход нужно сделать не тяжелым, с наименьшим дерганьем строк. Возможно потом еще стоит на всякий замерить профайлером текущий parsebbcode с 20+ replacetext vs новый с кучей небольших конкатенаций.

Sakuya-Izayoi commented 2 years ago

Проход нужно сделать не тяжелым, с наименьшим дерганьем строк.

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

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

Mercurialaste commented 1 year ago
  1. (WiP) Сам проход будет выглядеть примерно как-то так, пишу уставший по памяти рефов

Можно на сами эти рефы посмотреть?

Mercurialaste commented 1 year ago

9. (WiP) Сам проход будет выглядеть примерно как-то так, пишу уставший по памяти рефов

Можно на сами эти рефы посмотреть?

@volas

volas commented 1 year ago

https://www.byond.com/docs/ref/info.html букварь у гусева проси, если нужен

Mercurialaste commented 1 year ago

Я посидел, подумал, оно разве будет проверять весь текст, а не только вводимый в данный момент? Тип, на сколько я понимаю, для того чтобы с самого начала просматривать, у нас есть last_parsed_pos установленная в 0, но если вводить теги не за один раз, а за несколько, то лимит в теории, не срабатывает тк то что уже введено, заменено на html код, а то, что вводится не превышает его лимит?

К этому же по сути, относится и создание временного списка с лимитами, в котором бы можно было бы производить инкремент ключей и при совпадении значения из временного списка и глобального, заменять на пустоту, но опять же, временный список опустошается к моменту ещё одного вызова, на сколько я понимаю, из-за чего абуз не исчезнет, но будет требовать вводить количество тегов, одобренное лимитом, после чего, снова вводить их через оставшийся [write].

Спрашивал Людука, он предложил просто хранить лимит в самой бумажке, в каждой отдельно.

LudwigVonChesterfield commented 1 year ago

Не уверен зачем это было писать сюда, если да, решение очевидно - сохранять количество пропаршенных тегов ("лимит") в бумажке... ну или короче в любом другом носителе текста (кажется только у педальных анонсов ещё такой механ?)

Mercurialaste commented 1 year ago

Мб я что-то упустил просто и описанный в таске пример не имеет этой проблемы, хз.