Drupal7: автозамена кавычек на нормальные в тексте?

На хабрахабре, если я напишу такие кавычки:
"кавычки"

они в тексте автоматически заменяются на такие:

«кавычки»


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


По идее это как то можно реализовать добавив новый фильтр к данному формату отображения текста, который будет все кавычки менять на нормальные, но я не осилил сделать это сам. Подскажите как это лучше всего сделать. Заранее спасибо.
  • Вопрос задан
  • 4071 просмотр
Пригласить эксперта
Ответы на вопрос 3
demimurych
@demimurych
Не знаю как в 7 друпале,
а в пятом была такая штука как фильтры. Которыми можно было расширять как существующие так и писать свои собственные.
Почитайте документацию drupal.org/node/213156
Ответ написан
@m-haritonov
Если говорить безотносительно Drupal, то для обработки HTML в PHP стоит использовать встроенный класс DOMDocument. Стоит, как минимум, потому, что через него (через метод loadHTML) можно пропустить HTML код с целью исправления в нём ошибок HTML форматирования (незакрытые теги и т.п.). Касательно Вашей задачи, с помощью него можно получить доступ именно к текстовым узлам дерева HTML.

Пример парсинга (без корректного алгоритма по замене кавычек):
<?php
$html = '"текст в кавычках" текст "ещё текст в кавычках" <a href="http://ya.ru"><em>неправильный порядок вложенности элементов</a></em> текст <div>незакрытый элемент';

$domDocument = loadHtml($html);
$xpath = new DOMXpath($domDocument);

// Выбирает только текстовые узлы
foreach ($xpath->query('/html/body//text()') as $textNode)
{
	// Тут можно производить замены кавычек, учитывая текст из предыдущих $textNode
	$textNode->data = str_replace('"', '«', $textNode->data);
}

print htmlspecialchars(saveHtml($domDocument));

/*
Выведет:
«текст в кавычках« текст «ещё текст в кавычках« <a href="http://ya.ru"><em>неправильный порядок вложенности элементов</em></a> текст <div>незакрытый элемент</div>
*/


Функции, используемые в вышеприведённом коде (содержат различные исправления для соответствующих методов класса DOMDocument):
<?php
/**
 * @return DOMDocument
 */
function loadHtml($html, $charset = 'utf-8')
{
	$domDocument = new DOMDocument();

	// Т.к. функция DOMDocument::loadHTML конвертирует сущности "&nbsp;" в обычные пробелы, 
	// приходится экранировать эти сущности. Засипи вида "&amp;nbsp;" экранируем для того, 
	// чтобы при обратном преобразовании они по ошибке не превратились в "&nbsp;"
	$html = str_replace('&amp;nbsp;', '&amp;amp;nbsp;', $html);
	$html = str_replace('&nbsp;', '&amp;nbsp;', $html);

	// Удаляем символы "\r", т.к. DOMDocument::loadHTML() преобразует их в "&#13;"
	$html = str_replace("\r", '', $html);

	$html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
		<html>
			<head>
				<meta http-equiv="content-type" content="text/html;charset=' . $charset . '"/>
				<title></title>
			</head>
				<body>' . $html . '</body>
		</html>
	';
	
	// Функция DOMDocument::loadHTML может генерировать сообщения об ошибках, которые нам
	// не нужны (например, о незакрытом теге), т.к. мы используем данную функцию для 
	// коррекции HTML кода. Оператор @ ошибки у данной функции не подавляет.
	$useErrorsOld = libxml_use_internal_errors(true);
	$domDocument->loadHTML($html);
	libxml_use_internal_errors($useErrorsOld);

	return $domDocument;
}

/**
 * @return string
 */
function saveHtml(DOMDocument $domDocument)
{
	// Экспортируем в формате XHTML
	$html = $domDocument->saveXml();

	$html = str_replace('&amp;nbsp;', '&nbsp;', $html);
	$html = str_replace('&amp;amp;nbsp;', '&amp;nbsp;', $html);

	$html = preg_replace('/^\s*\<\?xml\s*[^\>]*\>\s*/is', '', $html);

	// Удаляем <![CDATA[]]>, которым оборачивается содержимое тега <script></script> при 
	// экспорте через DOMDocument::saveXml
	$html = preg_replace('/(\<script(\s*[^\>]*)?\>)\<\!\[CDATA\[/is', '$1', $html);
	$html = preg_replace('/\]\]\>(\<\/script\>)/is', '$1', $html);

	return preg_replace('/^.*?<body>(.*?)<\/body>\s*<\/html>$/is', '$1', $html);
}


P.S.: на хабре HTML сущности в теге <source>...</source> не экранируются для вывода кода в неизменном виде (жесть какая-то), я произвёл экранирование вручную, поэтому учтите, что код может стать некорректным, если программисты хабра исправят этот баг без должной замены в существующих сообщениях.
Ответ написан
Комментировать
movemind
@movemind
Аналитик из Кнопки
Вашу задачу полностью решает модуль Typogrify
Он так же умеет заменять дефис на тире и еще много чего, настоятельно рекомендую.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы