Поскольку теперь доступно автоматическое переключение цветовой схемы, я задумался: неужели нет способа переключаться между светлым и тёмным режимами Discourse при встраивании в виде комментариев в блоге? В частности, в моём блоге Ghost есть переключатель, с помощью которого пользователи могут вручную менять режимы. Я знаю, что CSS моего блога не может влиять на CSS внутри iframe Discourse, но с этим новым дополнением, неужели нет другого способа, чтобы переключатель также менял цветовую схему Discourse? Пример поста с комментариями внизу можно увидеть здесь.
Это потенциально выполнимо, но немного сложно. На данный момент мы не добавили автоматическое переключение тёмного режима в конечную точку для встроенных комментариев. Мы можем это добавить, и это будет работать, если ваш сайт на Ghost автоматически переключается в тёмный режим при переключении браузера в тёмный режим. Но, судя по всему, ваш сайт на Ghost использует кнопку переключения тёмного режима, что не будет работать с реализацией Discourse.
В вашем конкретном случае вы можете переключать класс во встроенном iframe комментариев Discourse при нажатии на кнопку, а затем использовать этот класс для переключения цветов в вашем встроенном стиле.
Звучит отлично. Сейчас я собираю несколько тем для Ghost с поддержкой тёмного режима для своих коллег, все они будут использовать один экземпляр Discourse, но это всё ещё впереди.
К сожалению, я не совсем понимаю, что вы предлагаете. Сейчас все элементы, для которых я хочу использовать стили тёмного режима в моём блоге, имеют удвоенный CSS: перед такими элементами добавляется body.dark. Например:
p {
color: #000;
}
body.dark p {
color: #FFF;
}
Может быть, вы предлагаете использовать этот код body.dark для изменения чего-то во встроенном iframe Discourse? Я пытался вставить следующее в поле встроенного CSS в Discourse, но, к сожалению, это не дало эффекта:
.FF2F-discourse p {
color: #000;
}
body.dark .FF2F-discourse p {
color: #FFF;
}
В таком случае, вы предлагаете написать отдельный JS-скрипт, чтобы переключение влияло на изменения через точечное переключение класса внутри iframe? Как я уже писал в предыдущем комментарии, я не думал, что внешний код может влиять на CSS внутри iframe, отсюда и моя путаница. Но я всего лишь любитель в HTML/CSS, так что, возможно, вы знаете лучше, чем я, или я что-то неправильно понимаю.
Да, именно это я и предлагаю. Стили вашего блога не могут применяться к iframe, но вы можете использовать JS для переключения класса dark в элементе html или body внутри iframe, а затем соответствующим образом обновить встроенный стиль Discourse.
Я нашел две страницы, объясняющие, как можно реализовать переключение между светлой и темной темами для встроенного Discourse, но разработчик, пишущий мой JS, хочет уточнить: предполагает ли предлагаемый вами метод использование postMessage (как указано на найденных мной страницах) или что-то другое.
Вот страница, объясняющая реализацию межоконного обмена сообщениями через postMessage:
А эта страница — фактически учебник о том, как изменять CSS внутри iframe с помощью postMessage, конкретно для переключения между светлой и темной темами:
Извините, что поднимаю такую старую тему, но есть ли планы реализовать автоматическое переключение тёмного режима для конечной точки встроенных комментариев?
В настоящее время у нас нет планов по добавлению этой функции. Сайты могут добавить стили тёмного режима в свой встроенный стиль в качестве обходного решения (или использовать технику postMessage, обсуждавшуюся выше.)
Блок кода ① добавляет слушатель событий во встроенный iframe Discourse, который отправляет сообщение на мой сайт, содержащий встроенный iframe Discourse, сразу после его загрузки.
Когда мой сайт получает сообщение от встроенного Discourse, он выполняет проверку, как показано в блоке кода ②. Если проверка пройдена, вызывается функция setIframeStyle для настройки встроенного Discourse.
Функция setIframeStyle, показанная в блоке кода ③, передаёт режим цвета («dark» или «light») в iframe, вызывая postMessage. Кроме того, при переключении тёмного режима эту функцию можно вызывать, чтобы поддерживать в встроенном Discourse тот же режим цвета, что и на моём сайте.
Блок кода ④ позволяет встроенному Discourse обрабатывать сообщения о режиме цвета, отправляемые с моего сайта. Здесь я переключаю режим цвета, меняя имя класса у тега body.
Кроме того, блоки кода ① и ④ добавлены через страницу администратора Discourse, как показано ниже:
Спасибо за приведенный выше план, @mikeguo, всё прекрасно объяснено!
Также обратите внимание, что для этого вам нужна последняя версия Discourse, так как возможность встроенного заголовка была добавлена всего несколько дней назад.
Я могу подтвердить, что описанный выше метод всё ещё работает, но было бы приятнее не вводить код вручную со скриншота Вот он, с небольшими обновлениями:
Шаги
iframe комментариев завершает рендеринг и отправляет сообщение в главное окно браузера, уведомляя об этом.
Браузер запрашивает настройку тёмного/светлого режима и возвращает это значение в iframe.
iframe получает сообщение и устанавливает data-атрибут, класс или аналогичный элемент в зависимости от настройки тёмного/светлого режима.
Код
После загрузки iframe отправьте уведомление родительскому окну. Этот код нужно добавить на Discourse в разделе Admin -> Customize -> (выберите тему) -> Edit CSS/HTML -> Embedded Header.
Обработайте этот входящий триггер в главном окне. Этот код размещается на вашем сайте блога:
<script type="text/javascript">
const discourse_url = "https://your.discourse-instance.org";
// Здесь мы определяем тему и отправляем сообщение в iframe, чтобы сообщить ей о выбранной теме
// Ниже показано, как подключить notifyFrameStyle
const notifyIFrameOfTheme = () => {
const iframe = document.getElementById("discourse-embed-frame");
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(
{
// Измените строку ниже, чтобы получить настройку тёмного режима в зависимости от способа её хранения
theme: document.documentElement.getAttribute("data-theme")
},
discourse_url
);
}
};
// Вызываем setFrameStyle при получении сообщения "iframe loaded"
const handleMessageListener = (event) => {
var origin = event.origin;
if ((origin === discourse_url) && (event.data == "iframe loaded")) {
notifyIFrameOfTheme();
}
};
</script>
В блоке <script> из шага (1) добавьте слушатель для сообщения о теме, отправленного notifyFrameStyle:
window.addEventListener("message", (event) => {
const payload = event.data;
if (payload.theme) {
// Выполните действие с настройкой темы; я устанавливаю атрибут `data-theme` на теге <html> внутри iframe,
// но вы можете установить класс или аналогичный атрибут
document.documentElement.setAttribute("data-theme", payload.theme);
}
}, false);
Стилизация
В разделе Admin -> Customize -> (выберите тему) -> Edit CSS/HTML -> Embedded CSS вы теперь можете предоставить CSS для каждого режима. Например, можно переопределить переменные стилей Discourse:
Спасибо, что заметили это! Я больше не могу редактировать предыдущий пост, но window.addEventListener должен находиться в конце фрагмента кода под пунктом (2).