Журнал LinuxFormat - перейти на главную

LXF170:Ре­дак­ти­ро­вание тек­ста: Markdown

Материал из Linuxformat
Версия от 04:37, 17 ноября 2018; Olkol (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Кон­вер­ти­руй­те свои фай­лы в Word с ко­манд­ной стро­ки

Ко­эн Верв­лое­сем не лю­бит во­зить­ся со шриф­та­ми и цве­том, ко­гда пи­шет тек­сты, и кон­вер­ти­ру­ет свои тек­сто­вые фай­лы в Word в ко­манд­ной стро­ке.

(thumbnail)
Наш эксперт Ко­эн Верв­лое­сем пи­шет об от­кры­том ПО с 2000 го­да, и с тех пор не за­кры­вал свой Vim. По­вто­ри­те, по­жа­луй­ста: ка­кой ко­ман­дой его за­крыть?

Как пи­са­тель, пред­по­чи­таю­щий тер­ми­нал и обыч­ные тек­сто­вые фай­лы, я всегда недо­люб­ли­вал гра­фи­че­­ские тек­сто­вые про­цес­со­ры, вклю­чая OpenOffice.org/LibreOffice Writer и AbiWord. Не то что они пло­хи – они про­сто не впи­сы­ва­ют­ся в мой ра­бо­чий про­цесс. Я мно­го ра­бо­таю в тер­ми­на­ле и пред­по­чи­таю тек­сто­вый ре­дак­тор Vim и поч­то­вый кли­ент Mutt. Когда я пи­шу пись­ма в Mutt, то мо­гу да­же ре­дак­ти­ро­вать их в Vim. Этот под­ход ка­жет­ся мне вполне ес­те­ст­вен­ным: Vim пред­на­зна­чен для ре­дак­ти­ро­вания тек­ста, и лю­бая про­грам­ма, в про­цес­се ра­бо­ты в ко­то­рой мож­но ре­дак­ти­ро­вать текст (на­при­мер, поч­то­вый кли­ент), долж­на пе­ре­да­вать эту за­да­чу Vim (или дру­го­му ре­дак­то­ру). Вот я и пи­шу в Vim пись­ма и ста­тьи, а так­же ис­ход­ный код – на­при­мер, скрип­ты обо­лоч­ки, скрип­ты Ruby и про­грам­мы на Java.

К со­жа­лению, из-за Vim я в мень­шин­ст­ве по от­но­шению ко всем поль­зо­ва­те­лям, да и тек­сто­вые фай­лы без раз­мет­ки се­го­дня не в мо­де. Так что неко­то­рые жур­на­лы из тех, в ко­то­рые я пи­шу, про­сят ме­ня при­сы­лать ста­тьи в фай­лах Word, в спе­ци­аль­ном шаб­лоне Word. Конеч­но, я уп­ря­мо про­дол­жаю пи­сать свои тек­сты в Vim, а по­том соз­даю но­вый до­ку­мент в LibreOffice Writer и на­чи­наю при­ме­нять шаб­лон фор­ма­ти­ро­вания, ко­то­рым я дол­жен поль­зо­вать­ся.

Я так по­сту­паю мно­го лет, но из­вел слиш­ком мно­го вре­мени на руч­ное фор­ма­ти­ро­вание, и несколь­ко ме­ся­цев на­зад, на­конец, ре­шил ав­то­ма­ти­зи­ро­вать про­цесс. Я по­ду­мал, что это не долж­но быть слиш­ком слож­но, по­то­му что в жур­на­лах ме­ня про­сят поль­зо­вать­ся спе­ци­аль­ным шаб­ло­ном, а у него есть струк­ту­ра. Мне про­сто нуж­но соз­дать некую струк­ту­ру в ис­ход­ном тек­сто­вом фай­ле и при­ду­мать спо­соб пре­об­ра­зо­вать эту ис­ход­ную струк­ту­ру в же­лае­мую.

Markdown: струк­ту­ри­ро­ван­ный текст

По­это­му наш пер­вый шаг – струк­ту­ри­ро­вать ис­ход­ный тек­сто­вый файл. Все эти го­ды я поль­зо­вал­ся неки­ми обо­зна­чения­ми для за­го­лов­ков, под­за­го­лов­ков и т. д.; но, немно­го по­ко­пав, об­на­ру­жил, что неко­то­рые фор­ма­ты струк­ту­ри­ро­ван­но­го тек­ста уже су­ще­ст­ву­ют. По­пу­ляр­ный при­мер – Markdown (http://daringfireball.net/projects/markdown/).

На­при­мер, мож­но струк­ту­ри­ро­вать текст так:

# За­го­ло­вок
## Подза­го­ло­вок

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut,

imperdiet a, venenatis vitae, justo.

### За­го­ло­вок третье­го уров­ня
  • эле­мент мар­ки­ро­ван­но­го спи­ска
  • эле­мент с _вы­де­ле­ни­ем_;
  • эле­мент с **силь­ным вы­де­ле­ни­ем**;

Син­так­сис го­во­рит сам за се­бя – при­вык­нуть к нему мож­но бы­ст­ро. И этим фор­ма­том мож­но поль­зо­вать­ся в сво­ем лю­би­мом ре­дак­то­ре, а при пе­ре­хо­де к дру­го­му син­так­си­су ме­нять ре­дак­тор не при­дет­ся. У фай­лов Markdown нет об­ще­при­ня­то­го рас­ши­рения, но мно­гие ис­поль­зу­ют .md или .markdown.

Итак, спо­соб струк­ту­ри­ро­вания тек­стов у нас есть, и ну­жен спо­соб пре­об­ра­зо­вы­вать их в до­ку­мен­ты Word. По­пу­ляр­ная ути­ли­та для этой це­ли – Pandoc (http://johnmacfarlane.net/pandoc), опи­сы­вае­мая как «универ­саль­ный кон­вер­тор до­ку­мен­тов». Она под­дер­жи­ва­ет несколь­ко вход­ных фор­ма­тов, в том чис­ле Markdown, и мно­же­ст­во вы­ход­ных фор­ма­тов, в том чис­ле DOCX для Microsoft Word и ODT (Open Document Text – текст от­кры­то­го до­ку­мен­та) для OpenOffice.org/LibreOffice. Так как с фай­ла­ми ODT го­раз­до про­ще ра­бо­тать, их мы и при­мем за вы­ход­ной фор­мат. Тогда мы смо­жем из­менить фор­мат поз­же, а вы уз­нае­те кое-что по­лез­ное об Open Document Format (фор­мат от­кры­то­го до­ку­мен­та), спо­соб­ное нам при­го­дить­ся. Pandoc есть в ре­по­зи­то­ри­ях мно­гих ди­ст­ри­бу­ти­вов Linux, вклю­чая Debian, Ubuntu, Slackware, Arch, Fedora, NixOS и Gentoo, по­это­му уста­но­вить ее очень лег­ко. Прав­да, уч­ти­те, что Pandoc на­пи­са­на на Haskell, и при­дет­ся уста­на­вливать всю ра­бо­чую сре­ду Haskell, а это до­воль­но-таки дол­го.

Ес­ли нуж­но из­менить ре­зуль­тат пре­об­ра­зо­вания Pandoc, это де­ла­ет­ся скрип­та­ми Haskell. Не­знание Haskell бы­ло еще од­ной при­чи­ной вы­бо­ра ODT: так как ODT по су­ти пред­став­ля­ет со­бой упа­ко­ван­ный в ZIP-ар­хив XML-файл, я смо­гу ра­бо­тать с ним с по­мо­щью XSLT.

Ес­ли вас уст­раи­ва­ет раз­мет­ка по умол­чанию, мо­же­те лег­ко пре­вра­тить файл Markdown в ODT:

$ pandoc -o document.odt document.md

Взгляните на ре­зуль­тат в LibreOffice. Ес­ли вы хо­ти­те пре­вра­тить его в файл Word, мо­же­те восполь­зо­вать­ся ути­ли­та­ми Unoconv (http://dag.wieers.com/home-made/unoconv), и это будет сде­ла­но с по­мо­щью OpenOffice.org/LibreOffice:

$ unoconv -f doc document.odt

Ре­зуль­ти­рую­щий файл document.doc – вер­сия ва­ше­го тек­ста для Word. Уч­ти­те, что пе­ред кон­вер­та­ци­ей фай­ла с unoconv нуж­но за­крыть OpenOffice.org или LibreOffice, что не всегда удоб­но.

Ана­то­мия фай­ла ODT

Ес­ли вам не по душе раз­мет­ка Pandoc по умол­чанию, из­мените ее – и здесь нам при­дет­ся немно­го глуб­же вник­нуть в ана­то­мию фай­ла ODT. Од­на из при­чин, по ко­то­рым я пред­по­чи­таю ODT в ка­че­­ст­ве про­ме­жу­точ­но­го фор­ма­та в этом пре­об­ра­зо­вании – в том, что его струк­ту­ру лег­ко по­нять, и ею лег­ко управ­лять. Ка­ж­дый файл ODT по су­ти пред­став­ля­ет со­бой ZIP-ар­хив. Смот­ри­те са­ми:

$ unzip -l document.odt

Archive: document.odt

Length Date Time Name


------------ ------ -------

770 01-14-2013 14:34 META-INF/manifest.xml

6860 01-14-2013 14:34 content.xml

0 07-18-2011 08:17 META-INF/

0 07-18-2011 08:01 Thumbnails/

742 03-11-2011 06:28 Thumbnails/thumbnail.png

342 07-18-2011 08:15 meta.xml

39 03-11-2011 06:28 mimetype

306 07-18-2011 08:15 settings.xml

53538 07-18-2011 08:15 styles.xml


-------

62597 9 files

Нам здесь важнее все­го фай­лы content.xml и styles.xml. В од­ном хранит­ся со­дер­жи­мое до­ку­мен­та в фор­ма­те XML, а в дру­гом – струк­ту­ра до­ку­мен­та в том же фор­ма­те. Что­бы по­зна­ко­мить­ся с фор­ма­том ODT, рас­па­куй­те файл и про­смот­ри­те эти XML-фай­лы в сво­ем лю­би­мом тек­сто­вом ре­дак­то­ре. styles.xml, на­вер­ное, по­хож на ки­тай­скую гра­мо­ту, зато син­так­сис content.xml очень прост: на­при­мер, эле­мен­ты <text:p> ис­поль­зу­ют­ся для аб­за­цев, а <text:h> – для за­го­лов­ков. Сравните ис­ход­ный текст Markdown с со­дер­жи­мым content.xml фай­ла ODT, что­бы по­нять, ка­кие пре­об­ра­зо­вания бы­ли вы­полнены Pandoc.

Мож­но из­менить фай­лы content.xml и styles.xml, пе­ре­упа­ко­вать фай­лы в ар­хив, и вы уви­ди­те эти из­менения в ре­зуль­ти­рую­щем фай­ле. Конеч­но, это до­воль­но труд­ный и под­вер­жен­ный ошиб­кам спо­соб ре­дак­ти­ро­вания фай­лов ODT (но от­лич­ный спо­соб на­брать бал­лов умника!). Глав­ный же наш ин­те­рес – в ав­то­ма­ти­за­ции дан­но­го ме­ханиз­ма.

На­при­мер, пусть вам не нра­вит­ся раз­мет­ка ODT по умол­чанию, генери­руе­мая Pandoc. Во мно­гих слу­ча­ях про­бле­ма ре­ша­ет­ся до­воль­но про­сто. Вы­бе­ри­те файл ODT с нуж­ной раз­мет­кой, рас­па­куй­те его и ско­пи­руй­те его файл styles.xml. За­тем рас­па­куй­те файл ODT, соз­дан­ный Pandoc, и за­мените его styles.xml на ско­пи­ро­ван­ный styles.xml. Пе­ре­упа­куй­те файл ODT и от­крой­те его в LibreOffice. Та-дам! Те­перь в ва­шем фай­ле ODT дру­гая раз­мет­ка.

Транс­фор­ме­ры

Конеч­но, это не всегда так про­сто. На­при­мер, ес­ли текст нуж­но пре­достав­лять в фор­ма­те Word с име­на­ми сти­лей, от­ли­чаю­щих­ся от имен сти­лей по умол­чанию, при­дет­ся кон­вер­ти­ро­вать все име­на сти­лей по умол­чанию (на­при­мер, «За­го­ло­вок 1», «За­го­ло­вок 2», «Текст» и т. д.) в content.xml в име­на сти­лей шаб­ло­на, ко­то­ро­му вы долж­ны сле­до­вать. В прин­ци­пе, для это­го мож­но бы­ло бы из­менить код пре­об­ра­зо­вания в Pandoc, но я не вла­дею Haskell и восполь­зо­вал­ся дру­гим ре­шением: об­ра­бо­тал content.xml с XSLT (extensible stylesheet language transformations – пре­об­ра­зо­вания рас­ши­ряе­мо­го язы­ка сти­лей).

В XSLT мож­но восполь­зо­вать­ся таб­ли­цей сти­лей XSLT, ко­то­рая оп­ре­де­ля­ет, как я со­би­ра­юсь пре­об­ра­зо­вать вход­ной файл в фор­ма­те XML в вы­ход­ной файл в фор­ма­те XML. Но я не хо­чу пол­но­стью ме­нять content.xml, а хо­чу толь­ко из­менить име­на неко­то­рых сти­лей. По­это­му нач­ну с так на­зы­вае­мо­го то­ж­де­ст­вен­но­го пре­об­ра­зо­вания [identity transform]:

<?xml version=”1.0” ?>

<xsl:stylesheet version=”1.0”

xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”

xmlns:text=”urn:oasis:names:tc:opendocument:xmlns:text:1.0”>


<xsl:template match=”/ | @* | node()”>

<xsl:copy>

<xsl:apply-templates select=”@* | node()” />

</xsl:copy>

</xsl:template>

При то­ж­де­ст­вен­ном пре­об­ра­зо­вании все уз­лы XML с их ат­ри­бу­та­ми про­сто ко­пи­ру­ют­ся, и ниче­го не ме­ня­ет­ся. Ес­ли же нуж­но из­менить име­на неко­то­рых сти­лей, до­ба­вим дру­гой шаб­лон:

<xsl:template match=”@text:style-name”>

<xsl:attribute name=”text:style-name”>

<xsl:choose>

<xsl:when test=”.=’Heading_20_1’”>Article_20_title</xsl:when>

<xsl:when test=”.=’Heading_20_2’”>Article_20_subtitle</xsl:when>

<xsl:when test=”.=’Text_20_body’”>Article_20_text</xsl:when>

<xsl:otherwise><xsl:value-of select=”.”/></xsl:otherwise>

</xsl:choose>

</xsl:attribute>

</xsl:template>

</xsl:stylesheet>

С до­бав­лением это­го шаб­ло­на таб­ли­ца сти­лей ко­пи­ру­ет все уз­лы XML с их атри­бу­та­ми, но когда ей по­па­да­ет­ся ат­ри­бут с именем text:style-name, зна­чение ат­ри­бу­та ме­ня­ет­ся, ес­ли оно рав­но од­но­му из пе­ре­чис­лен­ных вы­ше. _20_ в име­нах сти­лей оз­на­ча­ет про­бел (20 – его ше­ст­на­дца­те­рич­ный код ASCII), по­то­му что, со­глас­но фор­ма­ту фай­ла ODT, во внут­ренних име­нах сти­лей не мо­жет быть про­бе­лов.

Что­бы при­менить таб­ли­цу сти­лей к на­ше­му content.xml, нам по­на­до­бит­ся про­цес­сор XSLT, на­при­мер, па­кет xsltproc. Восполь­зо­вать­ся им про­сто:

$ xsltproc -o newcontent.xml stylesheet.xsl content.xml

Здесь код XSLT из фай­ла stylesheet.xsl при­ме­ня­ет­ся к фай­лу content.xml, а ре­зуль­тат пре­об­ра­зо­вания со­хра­ня­ет­ся в файл newcontent.xml.

Так мож­но из­менить в до­ку­мен­те мно­гое. На­при­мер, один из жур­на­лов, в ко­то­рые я пи­шу, про­сит ме­ня пе­ре­сы­лать свои тек­сто­вые до­ку­мен­ты в осо­бом шаб­лоне Word, когда на­ча­ло тек­ста (пер­вый аб­зац по­сле за­го­лов­ка и под­за­го­лов­ка) оформ­ле­но в спе­ци­аль­ном сти­ле «лид [lead, ввод­ка]». А в Markdown нет та­ко­го сти­ля. Как же ав­то­ма­ти­че­­ски из­менить стиль пер­во­го аб­за­ца? Бла­го­да­ря XSLT это про­сто. Я про­сто до­ба­вил сле­дую­щий шаб­лон XSLT:

<xsl:template match=”text:p[1]”>

<xsl:copy>

<xsl:attribute name=”text:style-name”>Lead</xsl:attribute>

<xsl:apply-templates select=”node()” />

</xsl:copy>

</xsl:template>

Когда моя таб­ли­ца сти­лей XSLT встре­ча­ет пер­вый аб­зац в content.xml (так как он со­от­вет­ст­ву­ет XPath-вы­ра­жению “text:p[1]”), она ко­пи­ру­ет весь аб­зац, пе­ред этим за­менив имя сти­ля на Lead. А так как в мо­ем styles.xml стиль Lead за­дан кор­рект­но, ре­зуль­ти­рую­щий файл ODT вы­гля­дит имен­но так, как дол­жен, при этом его ввод­ка име­ет соб­ст­вен­ный стиль.

Ав­то­ма­ти­зи­ру­ем все

Мы при­бли­жа­ем­ся к за­вер­шению этой ста­тьи и уже по­лу­чи­ли до­воль­но слож­ную по­сле­до­ва­тель­ность ша­гов для пре­об­ра­зо­вания фай­ла Markdown в файл Word с за­дан­ной раз­мет­кой. Конеч­но, вы­пол­нять эти ша­ги вруч­ную неин­те­рес­но и мо­жет при­вес­ти к ошиб­кам, по­это­му их сто­ит ав­то­ма­ти­зи­ро­вать.

Для это­го я восполь­зо­вал­ся под­хо­дом Makefile в раз­ра­бот­ке про­грамм. Makefile ис­поль­зу­ет­ся для ком­пи­ля­ции ис­ход­ных фай­лов и фор­ми­ро­вания из них ис­пол­няе­мой про­грам­мы в про­ек­тах с от­кры­тым ис­ход­ным ко­дом, но тот же ме­ханизм мож­но ис­поль­зо­вать для соз­дания фай­ла Word из фай­ла Markdown. Ре­зуль­ти­рую­щий файл Makefile вы­гля­дит так (внимание: от­сту­пы сле­ду­ет вы­пол­нять та­бу­ля­ци­ей, а не про­бе­ла­ми):

XSL = ../../article.xsl

STYLESHEET = ../../styles.xml

TEMP_DIR = output

SOURCE_DOCS = $(wildcard *.md)

INTERMEDIATE_DOCS = $(patsubst%.md, %.odt,$(SOURCE_DOCS))

OUTPUT_DOCS = $(patsubst %.md,%.doc, $(SOURCE_DOCS))

test: $(INTERMEDIATE_DOCS)

all: $(OUTPUT_DOCS)

%.odt: %.md

pandoc -o $@ $<;\

rm -rf $(TEMP_DIR);\

mkdir $(TEMP_DIR);\

unzip $@ -d $(TEMP_DIR);\

xsltproc -o $(TEMP_DIR)/content.xml $(XSL) $(TEMP_DIR)/content.xml;\

cp $(STYLESHEET) $(TEMP_DIR)/styles.xml;\

cd $(TEMP_DIR);\

zip -r $@ .;\

mv $@ ..;

%.doc: %.odt

unoconv -f doc $<

Ес­ли вы чи­та­ли эту ста­тью внима­тель­но, то долж­ны по­нять ло­ги­ку в этом фай­ле Makefile. Сна­ча­ла мы оп­ре­де­ля­ем несколь­ко пе­ре­мен­ных, на­при­мер, с рас­по­ло­жением таб­ли­цы сти­лей XSL и фай­ла styles.xml на­ше­го фай­ла шаб­ло­на ODT, ко­то­рым мы долж­ны поль­зо­вать­ся. Мы оп­ре­де­ля­ем две це­ли: test, ко­то­рая соз­да­ет фай­лы ODT для всех фай­лов Markdown в этом ка­та­ло­ге, и all, ко­то­рая соз­да­ет все фай­лы DOC. Файл ODT соз­да­ет­ся по фай­лу Markdown, сле­дуя про­це­ду­ре, опи­сан­ной в этой ста­тье: Pandoc соз­да­ет файл ODT, соз­да­ет­ся вре­мен­ный ка­та­лог, со­дер­жи­мое фай­ла ODT рас­па­ко­вы­ва­ет­ся в этот ка­та­лог, к фай­лу content.xml при­ме­ня­ет­ся таб­ли­ца сти­лей XSLT и ре­зуль­тат со­хра­ня­ет­ся в фай­ле content.xml. Файл styles.xml, соз­дан­ный Pandoc, за­ме­ня­ет­ся на наш styles.xml, и со­дер­жи­мое вре­мен­но­го ка­та­ло­га упа­ко­вы­ва­ет­ся. Пре­об­ра­зо­вание из ODT в DOC про­ще: про­сто за­пусти­те unoconv. По­мес­тив этот файл Makefile в ка­та­лог с фай­ла­ми Markdown, мож­но на­брать make all, и тек­сто­вые фай­лы бу­дут пре­об­ра­зо­ва­ны в фай­лы Word с за­дан­ной раз­мет­кой.

Pandoc рас­ши­ря­ет син­так­сис Markdown мас­сой до­полнитель­ных воз­мож­но­стей – таб­ли­цами, кар­тин­ка­ми с под­пи­ся­ми, спи­ска­ми оп­ре­де­лений, ну­ме­ро­ван­ны­ми спи­ска­ми при­ме­ров, верхними и ниж­ними ин­дек­са­ми, сно­ска­ми и т. д. За­гляните в файл README Pandoc, что­бы уз­нать под­роб­но­сти о син­так­си­се, а так­же неко­то­рые ин­те­рес­ные па­ра­мет­ры ко­ман­ды pandoc.

Луч­шее из двух ми­ров

С опи­сан­ным под­хо­дом для соз­дания тек­сто­вых до­ку­мен­тов вы по­лу­чи­те луч­шее из двух ми­ров. Вы мо­же­те пи­сать тек­сты в лю­би­мом тек­сто­вом ре­дак­то­ре, но ва­ши кор­рес­пон­ден­ты и не по­ду­ма­ют, что вы поль­зуе­тесь эти­ми стран­ны­ми тек­сто­вы­ми фай­ла­ми без раз­мет­ки. И вы смо­же­те про­дол­жать по­та­кать сво­им на­вы­кам эф­фек­тив­ной ра­бо­ты в Linux, на­при­мер, ис­кать сло­ва с по­мо­щью grep или поль­зо­вать­ся сис­те­ма­ми управ­ления вер­сия­ми. А ва­ши кор­рес­пон­ден­ты бу­дут ду­мать, что вы поль­зуе­тесь Microsoft Word, и все бу­дут сча­ст­ли­вы... |

Персональные инструменты
купить
подписаться
Яндекс.Метрика