Юбер Алекс : другие произведения.

Заливалка v3.2

Самиздат: [Регистрация] [Найти] [Рейтинги] [Обсуждения] [Новинки] [Обзоры] [Помощь|Техвопросы]
Ссылки:


 Ваша оценка:
  • Аннотация:
    Прога для полуавтоматической верстки ХТМЛ. Исполняется 3.2 раза :)


Заливалка ХТМЛ: версия 3.2

LAV.UA#UNDEFINED


You will be the death of me
Yeah, you will be the death of me
Muse
' makehtml v3.2: Заливалка текста в ХТМЛ (с) 2004 Alex 'LabRat' Lobanov

' BEWARE! ACHTUNG! АЛАРМА! прога (далее SUBJ) не самая оптимальная и безопасная,
' но простая (делалась методами Copy-Paste & Mind Storm & Brute Force)
' в частности, исходя из принципов брутального программирования, похерены все
' проверки входных данных и действий пользователя -
' меня просто задрало в очередной раз ручками заполнять ХТМЛ-ную болванку
' и расставлять бесконечные <br>, <p>, etc

' ***************************** Раздел отмазок ***************************

' Это ПОЛНЫЙ "AS IS", НИКАКИЕ ПРЕТЕНЗИИ, В СЛУЧАЕ ИСПОЛЬЗОВАНИЯ SUBJ,
' (потеря данных, повреждения "железа" и нервные срывы при попытке
' самостоятельно пофиксить кривое рег. выражение) НЕ ПРИНИМАЮТСЯ!
' Со своей стороны автор не требует никаких лицензионных и иных отчислений,
' допускает "хранение в памяти ЭВМ-загрузку-исполнение-трассировку" SUBJ,
' и прочую шнягу, за которую честных хакеров и простых юзеров теперь
' преследуют, типа копирования, модификациий и расширений (последние можно
' только приветствовать). Пользовайтесь, почем зря... И не говорите потом,
' что LabRat вас не предупреждал: это кривая прога ;)

' *************************************************************************

' Известные (задуманные мной) фишки:

' - полуавтоматическая сборка опуса в публикабельный формат
' - автоматическое реферирование "больших опусов", если главы(части) в них
' соответствуют формату "##. <название главы>" (понятно, без кавычек,
' ## - двузначный номер главы. Те, кто может дописаться до трехзначных -
' см. раздел отмазок)

' Известные (мне) баги:

' - отсутствие проверок входных данных (на самом деле так и задумано,
' так что это не баг - это фишка... шутки прогр. юмора)

' Информация для добровольных камикадзе-испытателей:

' - инфу о багах можно оставлять в гостевой данного текста
' - багами считаются только сбои ДАННОЙ ВЕРСИИ скрипта, при соблюдении
' текущих правил заливки, т.е. отладка самостоятельных модификаций - проблемка
' самих... шибко самостоятельных: для меня это факультативный интерес, в части
' улучшений (улучшить можно любую прогу... только неплохо понимать, что делаешь)

' Текущие правила заливки:

' 1. Все абзацы и пустые строки должны содержать концевой символ табуляции
' 1.1 Началом абзаца считается лидирующий пробел в строке

' 2. Вызов скрипта: start makehtml31.vbs <outputname> <f_bignovel> <f_link>
' 2.1 outputname - имя выходного файла (результат заливки: outputname.html)
' 2.2 f_bignovel - признак деления на главы (для рассказов обычно равен 0)
' Если больше нуля - создается список глав и вставляется,
' как "Содержание" опуса.
' 2.3 f_link - признак настройки доп. гиперссылок (обычно всегда 1: просто,
' если в вашем файле нет гиперссылок, файл linkit.cf должен
' быть пуст)
' 2.4 f_rulez - признак подключения внешних правил (обычно 0)

' 3. Входные данные:
' В текущем каталоге должны быть следующие файлы (подготавливаются ручками)
' head - файл шапки в ХТМЛе ("титул", сюда будет подставлено название
' и, возможно, инфа об авторе (на СИ не актуально, мной используется
' для ведения единого индекса опусов))
' body - файл с текстом опуса (без названия, готовится... автором опуса ;)
' rear - файл "подвала" в ХТМЛе (подставляется инфа о дате создания документа)
' spec - файл описания ("выходные данные" документа)
' epigraph - файл эпиграфа (не обязателен)
' linkit.cf - файл настройки гиперссылок по заданным меткам

' head и rear можно взять готовые или создать самостоятельно,
' "распилив" выходной файл любого html-редактора между тегами
' <body></body>. "Исторически сложилось", что я использую табличную
' разметку. Так что, в качестве болванки удобно использовать
' какую-нибудь ХТМЛ-таблицу (конвертер "Самиздата" сам подставит
' всякие <head>, <title> и <body> - пользовательские он, по-моему,
' просто удаляет).
' Самостоятельным придется подумать, где разместить
' маски выходных данных opus_title, opus_index и opus_date - они
' соответствуют строкам файла spec и автоматически заменяются скриптом
' в выходном файле.

' 4. Файл spec должен содержать три строки
' Название опуса
' Автор (или индексная номенклатура в любой удобной вам нотации)
' Дата создания документа
' В каждой строчке допустимо применение тегов для оформления текста

' 5. файл epigraph должен содержать
' Автора цитаты
' Текст цитаты, построчно

' Необязательность его объясняется просто: не найден - не файл ;)

' 6. Подключение внешних правил (режим f_ex_rulez=true)
' Укажите в 4-й строке файла spec полное имя текущего файла внешних правил.
' Скрипт следует вызвать с ключом f_rulez=1

script_ver = "3.2a" 'текущая версия скрипта

' Читаем ввод, открываем файлы... скрестив пальцы на удачу ;)

outstr=WScript.Arguments(0)
bignovel=WScript.Arguments(1)
f_link=WScript.Arguments(2)

f_rulez=WScript.Arguments(3)

set fso=createobject("scripting.filesystemobject")
set txtdate = fso.opentextfile("spec",1)
i_title=txtdate.readline
i_index=txtdate.readline
i_date=txtdate.readline
set txtFile2 = fso.opentextfile("body",1)
set txtFilehead = fso.opentextfile("head",1)
set txtfilerear = fso.opentextfile("rear",1)

'******** поддержка внешних правил (v3.2+) ****************
f_ex_rulez=false
if f_rulez>0 then
f_ex_rulez=true
end if
if f_ex_rulez = true then

cf_ruler=txtdate.readline

Dim oRuleReg
Set oRuleReg = New RegExp ' Create regular expression.
oRuleReg.Global = True ' All matches
oRuleReg.IgnoreCase = True ' Make case insensitive.

Dim oRuleReg1
Set oRuleReg1 = New RegExp ' Create regular expression.
oRuleReg1.Global = True ' All matches
oRuleReg1.IgnoreCase = True ' Make case insensitive.

Dim oPaReg
DIM oPaReg1
dim matches
dim cf_rule
dim cf_label

Set oPaReg = New RegExp ' Create regular expression.
oPaReg.Global = True ' All matches
oPaReg.IgnoreCase = True ' Make case insensitive.
end if

'********************** v.3.1- *****************************

if f_link = 1 then
set txtFile1 = fso.createtextfile("unl_" & outstr & ".html",1)
else
set txtFile1 = fso.createtextfile(outstr & ".html",1)
end if

''типа проба пера в большой форме ;)
'if bignovel=1 then
'txtfile1.writeline("<A NAME=""_op_begin_""></A>" & cr)
'end if

'Обозначаем место, где кончается заголовок блога (нужно для strip_sam)

txtfile1.writeline("<A NAME=""_op_blog_hend_""></A>" & cr)

'Если большой опус, реферируем части и/или главы
if bignovel = 1 then
Dim oReg1
Set oReg1 = New RegExp ' Create regular expression.
oReg1.Global = True ' All matches
oReg1.IgnoreCase = True ' Make case insensitive.

'Создаем промежуточный файл: можно посмотреть, как выглядит
' содержание опуса изнутри

set txtfilecont = fso.createtextfile("contents",8)

txtfilecont.writeline("<A NAME =""_op_cont_""></A>" & cr)
txtfilecont.writeline("<div align=""justify"">Содержание</div>" & cr)
txtfilecont.writeline("<ul>" & cr)
'txtfilecont.writeline("<ol>" & cr) 'Для тех, кому лень ставить номера
line_id=0

' просматриваем тело на предмет заголовков глав

do while txtfile2.atendofstream <> true

i_line=txtfile2.readline 'читаем строку "тела"
oReg1.Pattern = "^ [1-90-9].*" & chr(9) 'Set pattern. (маска поиска)
oReg1.Global = True ' All matches (поиск... по всему телу ;)

if oreg1.test(i_line) then 'нашли заголовок главы
line_id=Line_id+1
i_line = oReg1.Replace(i_line, "<li><a href=""#spec" & line_id & """>" & i_line & "</a></li>")
txtfilecont.writeline(i_line & cr) 'пишем в contents строчку в ХТМЛе
end if
loop
' txtfilecont.writeline("</ol>") 'Для тех, кому лень ставить номера
txtfilecont.writeline("</ul>") '
txtfilecont.close
set txtFilecont = fso.opentextfile("contents",1)
txtfile2.close
set txtFile2 = fso.opentextfile("body",1)
end if

'пишем "титул"

Set oReg1 = New RegExp ' Create regular expression.
oReg1.Global = True ' All matches
oReg1.IgnoreCase = True ' Make case insensitive.
oreg1.Pattern="<html>" ' до конца ХТМЛа скромничаем ;)

do while txtfilehead.atendofstream <> true
i_line=txtfilehead.readline
MakeHtmlCode i_line,i_title,i_index,i_date,0
txtfile1.writeline(i_line)
if oreg1.test(i_line) then

if bignovel = 1 then
'типа проба пера в большой форме ;)
txtfile1.writeline("<A NAME=""_op_begin_""></A>" & cr)
end if
end if
loop
txtfilehead.close

'вставляем эпиграф, если есть
If FSO.FileExists("epigraph") Then

txtfile1.writeline("<table cellpadding=""2"" cellspacing=""2"" border=""0"" width=""100%"">")
txtfile1.writeline("<tbody>")
txtfile1.writeline("<tr valign=""right"" width =""100%"">")
txtfile1.writeline("<td>")
txtfile1.writeline("</td>")
txtfile1.writeline("<td width=""50%"">")
txtfile1.writeline("<div align=""left"">")

' Set objFolder = objFSO.GetFile("C:\FSO\ScriptLog.txt")
set epigraph = fso.opentextfile("epigraph",1)
epic_author = epigraph.readline
do while epigraph.atendofstream <> true
i_line = epigraph.readline
txtfile1.writeline("<DD>" & i_line)
loop
epigraph.close

txtfile1.writeline("</div>")
txtfile1.writeline("<table cellpadding=""2"" cellspacing=""2"" border=""0"" width=""100%"">")
txtfile1.writeline("<tbody>")
txtfile1.writeline("<td>")
txtfile1.writeline("</td>")
txtfile1.writeline("<td width=""50%"">")
txtfile1.writeline("<div align=""left"">")

'автор эпиграфа

txtfile1.writeline(epic_author)

txtfile1.writeline("</div>")
txtfile1.writeline("</td>")
txtfile1.writeline("</tbody>")
txtfile1.writeline("</table>")
txtfile1.writeline("</td>")
txtfile1.writeline("</tr>")
txtfile1.writeline("</tbody>")
txtfile1.writeline("</table>")
End If


'вставляем оглавление

if bignovel > 0 then
txtfile1.writeline("<hr size=""2"" noshade>")
do while txtfilecont.atendofstream <> true
i_line = txtfilecont.readline
txtfile1.writeline(i_line)
loop
txtfilecont.close
txtfile1.writeline("<hr size=""2"" noshade>")
end if

'пишем тело документа

chaps_num=Line_id
line_id =0
' WScript.Echo Line_id & " " & chaps_num

do while txtfile2.atendofstream <> true
i_line=txtfile2.readline

if f_ex_rulez = false then
MakeHtmlCode i_line,i_title,i_index,i_date,1
else
' ********************* Внешние правила (v3.2+) *******************
MakeHtmlCode i_line,i_title,i_index,i_date,2
' *****************************************************************
end if

if bignovel > 0 then
if chaps_num >= Line_id then
oReg1.Pattern = "^<DD>[1-90-9].*" & chr(9) ' Set pattern.
oReg1.Global = True ' All matches
if oreg1.test(i_line) then
txtfile1.writeline("<br>" & cr)
txtfile1.writeline("<br>" & cr)
txtfile1.writeline("<br>" & cr)
Line_id=Line_id+1
' if line_id=1 then
' i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A>" & "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id+1 & """>[ Вперед ]</a> </a>")
' elseif line_id=chaps_num then
' i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A>" & "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id-1 & """>[ Назад ]</a>")
' else
' i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A>" & "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id+1 & """>[ Вперед ]</a> <a href=""#spec" & Line_id-1 & """>[ Назад ]</a>")
' end if
if line_id=1 then
i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A><div align=""right""><a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id+1 & """>[ Вперед ]</a> </div>")
elseif line_id=chaps_num then
i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A><div align=""right""><a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id-1 & """>[ Назад ]</a> </div>")
else
i_line = oReg1.Replace(i_line, i_line & "<A NAME=""spec" & Line_id &"""></A><div align=""right""><a href=""#_op_cont_"">[ Содержание ]</a> <a href=""#spec" & Line_id+1 & """>[ Вперед ]</a> <a href=""#spec" & Line_id-1 & """>[ Назад ]</a> </div>")
end if
' WScript.Echo Line_id ' если охота соглашаться с обработкой каждой главы
end if
end if
end if
txtfile1.writeline(i_line)

loop
txtfile2.close

' пишем "подвал"
Set oReg1 = New RegExp ' Create regular expression.
oReg1.Global = True ' All matches
oReg1.IgnoreCase = True ' Make case insensitive.
oreg1.Pattern="</body>" ' до конца ХТМЛа скромничаем ;)

do while txtfilerear.atendofstream <> true
i_line=txtfilerear.readline
MakeHtmlCode i_line,i_title,i_index,i_date,0

if oreg1.test(i_line) then
' txtfile1.writeline("<div align=""right""><a href=""#_op_begin_"">[В начало]</a></div>")
if bignovel = 1 then
txtfile1.writeline("<div align=""left""><a href=""#_op_begin_"">[В начало]</a></div>")
end if
txtfile1.writeline("<hr size=""2"" noshade>")
' txtfile1.writeline("<div align=""right""><i>Залито в ХТМЛ с помощью makehtml v3.1</i></div>")
txtfile1.writeline("<div align=""right""><i>Залито в ХТМЛ с помощью makehtml v" & script_ver & "</i></div>")
end if

txtfile1.writeline(i_line)

' if oreg1.test(i_line) then
' oreg1.pattern="</html>"
' end if

' if oreg1.test(i_line) then
''Обозначаем место, где начинается подвал блога (нужно для strip_sam)
' txtfile1.writeline("<A NAME=""_op_blog_rbeg_""></A>" & cr)
' end if
loop

'Обозначаем место, где начинается подвал блога (нужно для strip_sam)
txtfile1.writeline("<A NAME=""_op_blog_rbeg_""></A>" & cr)
txtfilerear.close
txtfile1.close

' Настраиваем гиперссылки

if f_link = 1 then
set sh=createobject("WScript.Shell")
sh.Run "linkit.vbs unl_" & outstr & ".html " & outstr & ".html"
end if

Sub MakeHTMLCode(txt, op_title, op_index, op_date, flag)

' Самая важная рутинка: проставляет теги в тексте опуса

' За основу взят пример из справки по использованию рег. выражений VBS
' с помощью Windows Scripting Host (плюс страничка юнихово хелпа regex(7))

Dim oReg
Set oReg = New RegExp ' Create regular expression.
oReg.Global = True ' All matches
oReg.IgnoreCase = True ' Make case insensitive.

if flag = 1 then
' Replace all < with &lt;.
oReg.Pattern = "<" ' Set pattern.
txt = oReg.Replace(txt, "&lt;")

' Replace all > with "&gt;"
oReg.Pattern = ">" ' Set pattern.
txt = oReg.Replace(txt, "&gt;")
' end if

' Replace all > with "&gt;"
oReg.Pattern = ".*\.jpg" ' Set pattern.
txt = oReg.Replace(txt, "<p>" & cr & "<div align=""center""><img src=""" & txt & """ alt=""" & txt & """></div>" & cr & "<p>" & cr)
' end if

oReg.Pattern = "\?" & chr(9)
oReg.Global = true
txt = oReg.Replace(txt, "?<br>")

oReg.Pattern = "!" & chr(9) ' Exl+Tab
oReg.Global = True ' All matches
txt = oReg.Replace(txt, "!<br>")

oReg.Pattern = "\." & chr(9) ' Dot+Tab (special symbol)
oReg.Global = True ' All matches
txt = oReg.Replace(txt, ".<br>")

' oReg.Pattern = "/" ' NOW OMITED, UNUSED (BEWARE)
' oReg.Global = True ' All matches
' txt = oReg.Replace(txt, "<br>")

oReg.Pattern = "^" & chr(9) ' EmptyLn+TAB Set pattern.
oReg.Global = True ' All matches
txt = oReg.Replace(txt, "<p>" & vblf)

oReg.Pattern = "^ " ' Paragraph FEED Set pattern.
oReg.Global = True ' All matches
txt = oReg.Replace(txt, "<DD>")

end if

' Проставляем "выходные данные"

if flag = 0 then
oReg.Pattern = "opus_title" ' Set pattern.
oReg.Global = True ' All matches
txt = oReg.Replace(txt, op_title)

oReg.Pattern = "opus_index" ' Set pattern.
oReg.Global = True ' All matches
txt = oReg.Replace(txt, op_index)

oReg.Pattern = "opus_date" ' Set pattern.
oReg.Global = True ' All matches
txt = oReg.Replace(txt, op_date)
End If

if flag = 2 then
' здесь могли быть и ваши расширения ;)
' а пока будут мои: вызов внешнего файла для настройки
' шаблонов по типу процедуры настройки гиперссылок в linkit.vbs
' Этот режим предполагается использовать для подключения внешних
' правил оформления (например, с заливкой в ХТМЛ стихов и текстов
' программ встроенный набор правил не справляется)
' Фишка планируется к версии v3.2
' Кстати, эта штука может и ссылки вставлять
' Extern_rules txt, "rulez.cf"
' Тестовый модуль: ex_rulez.vbs
Extern_Rulez txt,cf_ruler
end if

End Sub

Sub Extern_Rulez(i_str,ruler)
'sub Linkit(strtolink)
set cf_txtfile = fso.opentextfile(ruler,1) ' файл внешних правил
do while cf_txtfile.atendofstream <> true
cf_line=cf_txtfile.readline
oRuleReg.Pattern="_rem_" ' игнорируем комментарии
if oRuleReg.test(cf_line) then
else
cf_rule=cf_line
cf_label=cf_line
oRuleReg.Pattern="\{.*\}"
oRuleReg.Global = false ' All matches
oRuleReg.IgnoreCase = True ' Make case insensitive.
cf_rule=oRuleReg.Replace(cf_rule,"")

oRuleReg.Global = true ' All matches
oRuleReg.IgnoreCase = True ' Make case insensitive.
ruleparser i_str, cf_rule,0
oRuleReg.Pattern="\{"
oRuleReg.Global = true ' All matches
oRuleReg.IgnoreCase = True ' Make case insensitive.
cf_label=oRuleReg.Replace(cf_label,"")
oRuleReg.Pattern="\}.*"
cf_label=oRuleReg.Replace(cf_label,"")

' ruleparser cf_label,cf_rule

oRuleReg.Pattern=cf_rule
if oRuleReg.Test(i_str) then
' if cf_rule=".*\.jpg" then
' wsh.echo i_str
' end if
ruleparser cf_rule,cf_label,0
' ruleparser cf_rule,cf_label,1
' if cf_rule=".*\.jpg" then
' wsh.echo i_str
' end if

' oPaReg1.Pattern=cf_rule
' set matches = oPaReg1.Execute(i_str)
' WSH.Echo "i_str = " & i_str
' WSH.echo "P = " & oRuleReg.Pattern
set matches = oRuleReg.Execute(i_str)
' for each match in matches
' WSH.Echo "i_str = " & i_str

' end if
ruleparser i_str,cf_label,1
' ruleparser cf_rule,cf_label,1

ruleparser i_str, cf_label,2
i_str=oRuleReg.Replace(i_str,cf_label)
end if
end if
loop
cf_txtfile.close
'end sub
end sub

' Эта процедура проверяет наше правило на управляющие последовательности
'sub ruleparser(i_line1, x_line)
sub ruleparser(i_line1, x_line,mode)
if mode=2 then
' Режим обработки изображений
oPaReg.Pattern="_i_str_" 'исходная строка
' if oPaReg.Test(x_line) then
' wsh.echo "x_line= " & x_line
' wsh.echo "i_str= " & i_line1

x_line=oPaReg.Replace(x_line,i_line1)
' end if
end if
if mode=0 then
' Режим обработки спецсимволов и гиперссылок
' (пока что изображения и гиперссылки исключают друг друга в одном режиме
' в дальнейшем надо избавиться от параметар mode)
oPaReg.Pattern="#13" ' Enter
' x_line=oPaReg.Replace(x_line,cr)
x_line=oPaReg.Replace(x_line,chr(13))
' oPaReg.Pattern="#30" ' space
oPaReg.Pattern="#32" 'SPACE CODE IS 32, NOT 30
x_line=oPaReg.Replace(x_line," ")
' x_line=oPaReg.Replace(x_line,chr(30))
oPaReg.Pattern="#9" ' Enter
' x_line=oPaReg.Replace(x_line," ")
x_line=oPaReg.Replace(x_line,chr(9))
oPaReg.Pattern="_smpl_" ' поисковый шаблон (не маска!)
x_line=oPaReg.Replace(x_line,i_line1)

' Обработка гиперссылок
' end if
' if mode=1
oPaReg.Pattern="^http.*"
x_line=oPaReg.Replace(x_line,"<a href=""" & x_line & """>" & i_line1 & "</a>")
' Гиперссылки гадят... попробуем здесь
' oPaReg.Pattern="' oPaReg.Pattern="_i_str_" ' исходная строка" ' исходная строка
' x_line=oPaReg.Replace(x_line,i_line)
end if
if mode = 1 then
oPaReg.Pattern="_match_" ' совпадение с маской
if oPaReg.test(x_line) then
' oPaReg1.Pattern=i_line1
'' set matches = oPaReg1.Execute(i_line1)
' set matches = oPaReg1.Execute(i_str)
' WSH.Echo "i_str = " & i_str
' WSH.echo oRuleReg.Pattern
' set matches = oRuleReg.Execute(i_line1)
' WSH.echo "i_line1=" & i_line1
for each match in matches
' WSH.Echo "match = " & MAtch.Value
'' i_line1 = oPaReg1.Replace(i_line1, "<font color=""green"">" & match.Value & "</font>")
str1=Match.VAlue
' str1=oRuleReg.Replace(str1,"<font color=""green"">" & match.Value & "</font>")
str1=oRuleReg.Replace(str1,match.Value)
' str1=oPaReg.Replace(str1,"<font color=""green"">" & match.Value & "</font>")
x_line=oPaReg.Replace(x_line,str1)
next
end if
end if
end sub

Aug 6/ Y2K+4

Залито в ХТМЛ с помощью makehtml v3.2a

 Ваша оценка:

Связаться с программистом сайта.

Новые книги авторов СИ, вышедшие из печати:
О.Болдырева "Крадуш. Чужие души" М.Николаев "Вторжение на Землю"

Как попасть в этoт список
Сайт - "Художники" .. || .. Доска об'явлений "Книги"