Внесение пользовательских изменений в необработанный шаблон

В настоящее время на страницах со списком тем аватары основных участников каждой темы отображаются вместе со ссылкой на страницу профиля пользователя. Это можно увидеть здесь:


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

Проблема заключается в том, что наш консультант по SEO определил, что это создает для нас трудности, и хочет, чтобы ссылка на страницу профиля вообще не была видна Google.

Существуют аналогичные проблемы с постами в темах, но все они находились в виджетах, и их было относительно легко решить с помощью api.reopenWidget() и подобных методов.

С страницами списка тем дело обстоит иначе: нам нужно изменить содержимое raw-templates/list/posters-column.hbr!

Теперь я опишу то, что я уже пробовал. Если хотите, можете пропустить это и сразу перейти к концу, если уже знаете ответ.

Сначала я попытался подключить виджет согласно инструкциям из Руководства для начинающих.

<script type="text/x-handlebars" data-template-name="list/posters-column">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
              {{mount-widget widget="custom-list-avatar"}}
            {{/if}}
        {{/each}}
    </td>
</script>

Ничего из этого, казалось, не дало никакого результата. В конце концов, я нашел тему, где кто-то использовал расширение .raw в значении data-template-name, поэтому я предполагаю, что руководство просто устарело. В нем ничего не говорилось о raw-шаблонах! Использование .raw позволяет отобразить вышеуказанные изменения, но мой пользовательский виджет отказывался загружаться.

Это странно, потому что list/posters-column упоминается только в topic-list-item.hbr, который также является raw-шаблоном и конкретно указан в том руководстве как один из используемых шаблонов. Но… снова, я полагаю, руководство просто устарело? В конце концов я где-то прочитал, что нельзя подключать виджеты в raw-шаблонах, поэтому, похоже, этот метод никогда не сработает.

Затем я обнаружил частичные шаблоны (partials) и попытался использовать их. Я подумал, что у меня больше шансов, поскольку эти части больше не являются raw-шаблонами.

<script type="text/x-handlebars" data-template-name="components/custom-avatar">
    <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
</script>

<script type="text/x-handlebars" data-template-name="list/posters-column.raw">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
                {{partial 'components/custom-avatar'}}
            {{/if}}
        {{/each}}
    </td>
</script>

К сожалению, похоже, что использовать частичные шаблоны в raw-шаблонах тоже нельзя, поэтому этот подход не сработал.

Затем я нашел эту тему, которая, казалось, могла содержать то, что мне нужно. Основываясь на этом подходе и зная, что list/topic-list-item (который вызывает list/posters-column) используется компонентом topic-list-item, я придумал следующее:

<script type="text/x-handlebars" data-template-name="list/posters-column.raw">
    <td class='posters topic-list-data'>
        {{#each posters as |poster|}}
            {{#if poster.moreCount}}
                <a class="posters-more-count">{{poster.moreCount}}</a>
            {{else}}
                {{#if hideFromAnonUser}}
                    <div data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</div>
                {{else}}
                    <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
                {{/if}}
            {{/if}}
        {{/each}}
    </td>
</script>

<script type="text/discourse-plugin" version="1.1.0">
    const settings = Discourse.SiteSettings;
    const user = api.getCurrentUser();
    const hideFromAnonUser = settings.hide_user_profiles_from_public && !user;
    const topicListItemComponent = require('discourse/components/topic-list-item').default;
    topicListItemComponent.reopen({
        hideFromAnonUser: function() {
            return hideFromAnonUser
        }.property()
    });
</script>

К сожалению, hideFromAnonUser никогда, похоже, не становится видимым для raw-шаблона. Возможно, hideFromAnonUser нужно вычислять внутри функции, назначенной ключу hideFromAnonUser? Кажется, это не имеет значения. Даже если я закомментирую первые три присваивания const и просто установлю возвращаемое значение в False, или добавлю вызов console.log() внутри функции перед оператором return, я вижу, что функция никогда не выполняется ничем.

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

Как можно заменить теги <a></a> на теги <div></div> для аватаров на страницах со списком тем? Спасибо.

Привет @boltronics :wave:

Это переопределит шаблон list/posters-column. Вероятно, это лучше, чем переопределять шаблон topic-list-item.

<script type="text/x-handlebars" data-template-name="list/posters-column.hbr">
  <td class='posters topic-list-data'>
  {{#if currentUser}}
    {{#each posters as |poster|}}
      {{#if poster.moreCount}}
        <a class="posters-more-count">{{poster.moreCount}}</a>
      {{else}}
        <a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</a>
      {{/if}}
    {{/each}}
  {{else}}
    {{#each posters as |poster|}}
      <div data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" namePath="user.name" imageSize="small"}}</div>
    {{/each}}
  {{/if}}
  </td>
</script>

Также нужно добавить немного CSS, так как он нацелен на a, а нам нужен div для анонимных пользователей.

Desktop / CSS

html.anon {
  .topic-list {
    .posters {
      width: 146px;
      > div {
        float: left;
        margin-right: 4px;
        &:last-of-type {
          margin-right: 0;
        }
      }
      div:first-child .avatar.latest:not(.single) {
        box-shadow: 0 0 3px 1px rgba(var(--tertiary-rgb), 0.35);
        border: 1px solid rgba(var(--tertiary-rgb), 0.5);
        position: relative;
        left: -2px;
      }
    }
  }
}

Стоит отметить, что система «сырых» шаблонов (и виджетов!) скоро будет упразднена, но, разумеется, это не решит вашу текущую проблему.

Просто будьте готовы к рефакторингу, возможно, с дополнительными инструментами в вашем распоряжении, так как Glimmer-компоненты, скорее всего, придут им на смену:

@Don, ты просто супер. Я протестировал это, и решение идеально решает мою проблему.

Чуть-чуть жульничество, так как проблема решается другим способом (я не знал, что переменная currentUser доступна оттуда), но с результатами не поспоришь. :smile:

Спасибо также @merefield за указание на предстоящий рефакторинг. Я настрою тест для мониторинга нашей среды на предмет возможных регрессий.

Спасибо, ребята.

Я рад, что у вас всё работает, однако я внес некоторые исправления в пост выше. :slightly_smiling_face:
Параметр posters-more-count отображается в списке тем личных сообщений, поэтому он не нужен анонимным пользователям. Я также удалил его из шаблона и CSS.

Спасибо, Дон. Я изначально подозревал, что это может быть так, исходя из моих первоначальных попыток, но не стал проверять, чтобы подтвердить. Хорошо знать.