It started with a question from here
Download: upload.ee, yandex (the files are always newer)
ini file (must have the same name as the exe file):
source = path to source file
destination = path to the resulting file being created
flag = 6 - css formatting flags (see below)
open = 1 - open the resulting file for viewing in the associated program
msg = 1 - messages
Flags of the ini file (can be a combination-sum of flags):
1 - CSS compression. Flags 2, 4, 8 do not work in this mode.
2 - opening curly brace "{" on a new line
4 - after the comma "," in the class listing, there will be a line break instead of a space. This makes the classes a vertical list and is easier to read.
8 - (the option is disabled for now) there is no space inside the curly braces {...} after the colon ":" (separation of parameter and value)
16 - Convert rgb(x,x,x) to #hex
128 - disables deleting comments. Works with flag 1.
Command line: The "flag source_path destination_path" is passed on the command line. If the file is not transferred, a file selection window opens. If a file is selected, a save dialog is created in the same folder as a file with index "_1". The command line takes precedence over the ini file.
css_tidy
Code: Select all
;- TOP
; AZJIO 2024.09.02 - 2024.09.24
EnableExplicit
;- ● Global
Global NewList TextList.s()
Global Dim Tab.s(1)
Tab(1) = #TAB$
Global g_Format, flag, Error, open, msg, StartTime
Global source$, destination$, current$, ext$, Message$
;- ● Define
Define Len, *Point
Define Result.string
Define CountPP
Define tmp$
; https://www.purebasic.fr/english/viewtopic.php?p=478874
XIncludeFile "AutoDetectTextEncoding_Trim.pbi"
Procedure.s RTrimChar(String$, TrimChar$ = " " + #TAB$ + #CRLF$ + #FF$ + #VT$)
Protected Len2, Blen, i
Protected *jc0, *c.Character, *jc.Character
Len2 = Len(String$)
Blen = StringByteLength(String$)
If Not Asc(String$)
ProcedureReturn ""
EndIf
*c = @String$ + Blen - SizeOf(Character)
*jc0 = @TrimChar$
For i = Len2 To 1 Step - 1
*jc = *jc0
While *jc\c
If *c\c = *jc\c
*c\c = 0
Break
EndIf
*jc + SizeOf(Character)
Wend
If *c\c
Break
EndIf
*c - SizeOf(Character)
Next
ProcedureReturn String$
EndProcedure
Procedure ForceDirectories(Dir.s)
Static tmpDir.s, Init
Protected result
If Asc(Dir) ; если что-то есть
If Not Init
tmpDir = Dir
Init = 1
EndIf
Dir = RTrim(Dir, #PS$) ; убираем последний слеш, не делая лишние проверки
; если папка существует или дошли до корневой, то
If FileSize(Dir) = -2 Or (Len(Dir) < 3) Or GetPathPart(Dir) = Dir
If FileSize(tmpDir) = -2
result = -1 ; попробуем использовать -1 в качестве "путь уже создан"
EndIf
tmpDir = ""
Init = 0
ProcedureReturn result ; если это папка, то возврат будет 1
EndIf
ForceDirectories(GetPathPart(Dir))
ProcedureReturn CreateDirectory(Dir)
Else
ProcedureReturn 0
EndIf
EndProcedure
; Чтение файла в гаджет
Procedure.s OpenFileToGadget(FilePath$)
Protected length, oFile, bytes, *mem, Text$
oFile = ReadFile(#PB_Any, FilePath$)
If oFile
g_Format = ReadStringFormat(oFile)
length = Lof(oFile)
*mem = AllocateMemory(length)
If *mem
bytes = ReadData(oFile, *mem, length)
If bytes
If g_Format = #PB_Ascii
g_Format = dte::detectTextEncodingInBuffer(*mem, bytes, 0)
If g_Format = #PB_Ascii
Text$ = PeekS(*mem, bytes, #PB_Ascii)
Else
Text$ = PeekS(*mem, bytes, #PB_UTF8) ; если UTF8 без BOM
EndIf
Else
; тут не уверен, PeekS() поддерживает #PB_Unicode,
; а ReadStringFormat() может дать #PB_UTF16BE, #PB_UTF32, #PB_UTF32BE
; хотя эти форматы не популярны скорее не встретятся, и надо сделать на них игнор
Text$ = PeekS(*mem, bytes, g_Format)
EndIf
EndIf
FreeMemory(*mem)
EndIf
CloseFile(oFile)
EndIf
ProcedureReturn Text$
EndProcedure
Procedure cssCompression(*c.Character)
Protected sz = SizeOf(Character)
Protected OpenBrace, OpenSquareBracket
Protected *tmp, *start
If *c = 0 Or *c\c = 0
MessageRequester("Ошибка", "Данные пусты")
ProcedureReturn
; ElseIf *c\c = '{' ; защита уже сделана
; MessageRequester("Ошибка", "{ - фигурная скобка не может быть первым символом соответсвенно невозможно осуществить просмотр назад")
; ProcedureReturn
EndIf
*start = *c
; Удаление стартовых пробелов
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
While *c\c
Select *c\c
;- /
Case '/' ; проверка комментариев, если найдено то затираем псевдо-пусто-символом
If flag & 128 ; если флаг 128, то не удаляем комментарии
*c + sz
If *c\c = '*'
*c + sz
While *c\c
If *c\c = '*'
*c + sz
If *c\c = '/'
Break
EndIf
*c - sz
EndIf
*c + sz
Wend
If *c\c = 0 ; проверка если комент не закрыт в конце файла
Break
EndIf
Else
Continue
EndIf
Else
*c + sz
If *c\c = '*'
*c - sz
*c\c = 1
*c + sz
*c\c = 1
*c + sz
While *c\c
If *c\c = '*'
*c + sz
If *c\c = '/'
*c - sz
*c\c = 1
*c + sz
*c\c = 1
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
*c - sz
Break
EndIf
*c - sz
EndIf
*c\c = 1
*c + sz
Wend
Else
*c - sz
EndIf
EndIf
;- '
Case 39 ; проверка апострофа, идём до закрывающего апострофа
; *tmp = *c
*c + sz
While *c\c
If *c\c = 39
; Debug PeekS(*tmp, (*c - *tmp) / 2 + 1, #PB_Unicode)
Break
EndIf
If *c\c > 8 And *c\c < 14
; Debug PeekS(*tmp, (*c - *tmp) / 2, #PB_Unicode)
*c\c = 32
Error + 1
Break
EndIf
*c + sz
Wend
;- "
Case 34 ; проверка кавычки, идём до закрывающей кавычки
; *tmp = *c
*c + sz
While *c\c
If *c\c = 34
; Debug PeekS(*tmp, (*c - *tmp) / 2 + 1, #PB_Unicode)
Break
ElseIf *c\c > 8 And *c\c < 14
; Debug PeekS(*tmp, (*c - *tmp) / 2, #PB_Unicode)
*c\c = 32
Error + 1
Break
Else
*c + sz
EndIf
Wend
;- [ ]
Case '['
OpenSquareBracket = 1
Case ']'
OpenSquareBracket = 0
;- !
Case '!'
If OpenBrace And CompareMemoryString(*c , @"!important", #PB_String_NoCaseAscii, 10) = #PB_String_Equal
; проверка пробелов назад
*tmp = *c
*c - sz
While *c>=*start And (*c\c = 32 Or (*c\c > 8 And *c\c < 14))
*c\c = 1
*c - sz
Wend
*c = *tmp + (10 * sz)
Continue
EndIf
;- ,:
Case ',', ':';, ')'
If OpenSquareBracket = 0; And OpenBrace = 0
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
*c - sz
EndIf
;- {
Case '{'
OpenBrace = 1
; проверка пробелов назад
*tmp = *c
*c - sz
While *c>=*start And (*c\c = 32 Or *c\c = 1 Or (*c\c > 8 And *c\c < 14))
*c\c = 1
*c - sz
Wend
*c = *tmp
; проверка пробелов вперёд
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
*c - sz
;- }
Case '}'
OpenBrace = 0
; проверка пробелов назад
*tmp = *c
*c - sz
While *c>=*start And (*c\c = 32 Or *c\c = ';' Or *c\c = 1 Or (*c\c > 8 And *c\c < 14))
*c\c = 1
*c - sz
Wend
*c = *tmp
; проверка пробелов вперёд
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
*c - sz
;- ;
Case ';' ; разделитель параметров в css
If OpenBrace ; внутри фигурных скобок
*c + sz
While *c\c = 32 Or *c\c = ';' Or (*c\c > 8 And *c\c < 14)
*c\c = 1
*c + sz
Wend
*c - sz
EndIf
;- Space, Tab, CR
Case 32, 9 To 13 ; пробел и табуляция и переносы строк
If *c\c <> 32
OpenSquareBracket = 0
EndIf
*c\c = 32 ; заменяем любой перенос пробелом
; If OpenBrace
; *c\c = 1
; Else
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14) ; удаляем повтор пробельных символов
*c\c = 1
*c + sz
Wend
*c - sz
; EndIf
EndSelect
*c + sz
Wend
EndProcedure
Procedure cssTidy(*c.Character)
Protected sz = SizeOf(Character)
Protected OpenBrace, OpenSquareBracket, CountBrace
Protected *tmp, *beginning
If *c = 0 Or *c\c = 0
MessageRequester("Ошибка", "Данные пусты")
ProcedureReturn
; ElseIf *c\c = '{' ; защита уже сделана
; MessageRequester("Ошибка", "{ - фигурная скобка не может быть первым символом соответсвенно невозможно осуществить просмотр назад")
; ProcedureReturn
EndIf
*beginning = *c
; Удаление стартовых пробелов
; While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
; *c\c = 1
; *c + sz
; Wend
While *c\c
Select *c\c
;- comment
Case '/' ; проверка комментариев, если найдено то ищем закрытие
*c + sz
If *c\c = '*'
*c + sz
While *c\c
If *c\c = '*'
*c + sz
If *c\c = '/'
Break
EndIf
*c - sz
EndIf
*c + sz
Wend
If *c\c = 0 ; проверка если комент не закрыт в конце файла
Break
EndIf
Else
Continue
EndIf
;- '
Case 39 ; проверка апострофа, идём до закрывающего апострофа
; *tmp = *c
*c + sz
While *c\c
If *c\c = 39
; Debug PeekS(*tmp, (*c - *tmp) / 2 + 1, #PB_Unicode)
Break
EndIf
If *c\c > 8 And *c\c < 14
; Debug PeekS(*tmp, (*c - *tmp) / 2, #PB_Unicode)
Error + 1
Break
EndIf
*c + sz
Wend
;- "
Case 34 ; проверка кавычки, идём до закрывающей кавычки
; *tmp = *c
*c + sz
While *c\c
If *c\c = 34
; Debug PeekS(*tmp, (*c - *tmp) / 2 + 1, #PB_Unicode)
Break
ElseIf *c\c > 8 And *c\c < 14
; Debug PeekS(*tmp, (*c - *tmp) / 2, #PB_Unicode)
Error + 1
Break
Else
*c + sz
EndIf
Wend
; Case '['
; OpenSquareBracket = 1
; Case ']'
; OpenSquareBracket = 0
;- ,
Case ','
*c\c = 0
*c + sz
AddElement(TextList())
TextList() = PeekS(*beginning)
AddElement(TextList())
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c + sz
Wend
; без этого OpenBrace перечисление шрифтов делает столбиком. Исправить.
; С другой стороны вложенные классы перестанет обрабатывать
If flag & 4 And Not OpenBrace
TextList() = "," + #CRLF$
ElseIf *c\c = ' '
TextList() = ","
Else
TextList() = ", "
EndIf
*beginning = *c
Continue
;- :
Case ':'
If OpenBrace
*c + sz
If *c\c = ':' Or *c\c = ' '
*c + sz
Continue
EndIf
*c - sz
*c - sz
; If *c\c = ':' Or *c\c = '{' Or *c\c = '}' Or *c\c = ';' Or *c\c = ')' Or *c\c = ' ' Or (*c\c > 8 And *c\c < 14)
; *c + sz
; ; *c + sz
; ; Continue
; Else
; *c + sz
; *c\c = 0
; *c + sz
; AddElement(TextList())
; TextList() = PeekS(*beginning)
; AddElement(TextList())
; TextList() = ": "
; *beginning = *c
; Continue
; EndIf
If (*c\c > 96 And *c\c < 123) And CompareMemoryString(*c + sz * 2, @"not", #PB_String_NoCaseAscii, 3) <> #PB_String_Equal
*c + sz
*c\c = 0
*c + sz
AddElement(TextList())
TextList() = PeekS(*beginning)
AddElement(TextList())
TextList() = ": "
*beginning = *c
Continue
Else
*c + sz
EndIf
EndIf
; If OpenBrace And flag ! 8 ; внутри фигурных скобок
; *c + sz
; If *c\c = ':'
; *c + sz
; Continue
; ElseIf CompareMemoryString(*c , @"not", #PB_String_NoCaseAscii, 3) = #PB_String_Equal
; *c + sz * 3
; Continue
; ElseIf CompareMemoryString(*c , @"root", #PB_String_NoCaseAscii, 4) = #PB_String_Equal
; *c + sz * 4
; Continue
; ; ElseIf PeekS(*c, 3) = "not"
; ; *c + sz * 3
; ; Continue
; ; ElseIf PeekS(*c, 3) = "root"
; ; *c + sz * 4
; ; Continue
; ; ElseIf *c\c = 'n'
; ; *c + sz
; Else
; *c - sz
; EndIf
; EndIf
;- ;
Case ';'
*c\c = 0
*c + sz
AddElement(TextList())
TextList() = PeekS(*beginning)
AddElement(TextList())
If OpenBrace
TextList() = ";" + #CRLF$ + Tab(OpenBrace)
Else
TextList() = ";" + #CRLF$ + Tab(OpenBrace)
EndIf
While *c\c = 32 Or *c\c = ';' Or (*c\c > 8 And *c\c < 14)
*c + sz
Wend
*beginning = *c
Continue
;- !
Case '!'
If OpenBrace And CompareMemoryString(*c , @"!important", #PB_String_NoCaseAscii, 10) = #PB_String_Equal
*c - sz
If *c\c <> 32
*c + sz
*c\c = 0
AddElement(TextList())
TextList() = PeekS(*beginning)
AddElement(TextList())
TextList() = " !important"
; проверка пробелов назад
*c + 10 * sz
*beginning = *c
Continue
Else
*c + sz
EndIf
EndIf
;- (
Case '(' ; при открывающей скобке ищем закрывающую
*c + sz
While *c\c
Select *c\c
Case '(' ; если опять открывается, то используем счётчик, чтобы искать последнюю закрывющуюся.
CountBrace + 1
Case ')'
If CountBrace
CountBrace - 1
Else
If OpenBrace
*c\c = 0
*c + sz
AddElement(TextList())
TextList() = PeekS(*beginning)
AddElement(TextList())
If *c\c = ';' Or *c\c = ':' Or *c\c = ' ' ; Or *c\c = '{'
TextList() = ")"
Else
TextList() = ") "
EndIf
*beginning = *c
*c - sz
EndIf
Break
EndIf
Case 9 To 13
Error + 1
Break
EndSelect
*c + sz
Wend
; )
; Case ')'
;- {
Case '{'
OpenBrace + 1
If OpenBrace > ArraySize(Tab())
ReDim Tab(OpenBrace)
Tab(OpenBrace) = LSet("", OpenBrace, #TAB$)
EndIf
*c\c = 0
*c + sz
AddElement(TextList())
TextList() = PeekS(*beginning)
TextList() = RTrimChar(TextList()) ; не оптимизировано, это можно сделать тут же без функции
AddElement(TextList())
If flag & 2
TextList() = #CRLF$ + "{" + #CRLF$ + Tab(OpenBrace)
Else
TextList() = " {" + #CRLF$ + Tab(OpenBrace)
EndIf
While *c\c = 32 Or *c\c = ';' Or (*c\c > 8 And *c\c < 14)
*c + sz
Wend
*beginning = *c
Continue
;- }
Case '}'
OpenBrace - 1
If OpenBrace < 0
OpenBrace = 0
EndIf
*c\c = 0
*c + sz
TextList() = RTrimChar(TextList()) ; так как здесь добавление отступов, то проверяем что у предыдущего не было добавлено
AddElement(TextList())
TextList() = PeekS(*beginning)
TextList() = RTrimChar(TextList())
AddElement(TextList())
TextList() = #CRLF$ + Tab(OpenBrace) + "}"
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c + sz
Wend
While *c\c = '}'
OpenBrace - 1
If OpenBrace < 0
OpenBrace = 0
EndIf
TextList() + #CRLF$ + Tab(OpenBrace) + "}"
*c + sz
While *c\c = 32 Or (*c\c > 8 And *c\c < 14)
*c + sz
Wend
Wend
TextList() + #CRLF$ + Tab(OpenBrace); + #CRLF$
*beginning = *c
Continue
EndSelect
*c + sz
Wend
EndProcedure
Structure RGBA
StructureUnion
color.l
b.a[4]
EndStructureUnion
EndStructure
Procedure RGBtoHEX(*text.String)
Protected *c.Character, Color.RGBA
Protected *StartNum, *Start0, *Start00
Protected i, count, tmp$
Protected sz = SizeOf(Character)
; Debug *text\s
*c = @*text\s
*Start00 = *c
While *c\c
If *c\c = 'r'
*Start0 = *c
*c - sz
If *c >= *Start00 And (*c\c = ' ' Or *c\c = ':' Or *c\c = #TAB)
*c + sz * 2
Else
*c + sz * 2
Continue
EndIf
If *c\c = 'g'
*c + sz
Else
Continue
EndIf
If *c\c = 'b'
*c + sz
Else
Continue
EndIf
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
If *c\c <> '('
*c + sz
Continue
EndIf
*c + sz
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
*StartNum = *c
While *c\c >= '0' And *c\c <= '9'
*c + sz
Wend
; Debug *StartNum
; Debug *c
If *StartNum <> *c
; Debug PeekS(*StartNum, (*c - *StartNum) / sz)
; red0 = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
Color\b.a[2] = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
; Debug red0
Else
*c + sz
Continue
EndIf
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
If *c\c <> ','
*c + sz
Continue
EndIf
*c + sz
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
*StartNum = *c
While *c\c >= '0' And *c\c <= '9'
*c + sz
Wend
; Debug *StartNum
; Debug *c
If *StartNum <> *c
; Debug PeekS(*StartNum, (*c - *StartNum) / sz)
; green0 = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
Color\b.a[1] = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
; Debug green0
Else
*c + sz
Continue
EndIf
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
If *c\c <> ','
*c + sz
Continue
EndIf
*c + sz
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
*StartNum = *c
While *c\c >= '0' And *c\c <= '9'
*c + sz
Wend
; Debug *StartNum
; Debug *c
If *StartNum <> *c
; Debug PeekS(*StartNum, (*c - *StartNum) / sz)
; blue0 = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
Color\b.a[0] = Val(PeekS(*StartNum, (*c - *StartNum) / sz))
; Debug blue0
Else
*c + sz
Continue
EndIf
While *c\c = 32
*c + sz
Wend
If *c\c = 0
Break
EndIf
If *c\c <> ')'
*c + sz
Continue
EndIf
For i = *Start0 To *c Step SizeOf(Character)
PokeA(i, 1)
Next
count = 0
For i = 0 To 2
If Hex(Color\b[i] >> 4) = Hex(Color\b[i] & $F)
count + 1
EndIf
Next
If count = 3
tmp$ = "#" + Hex(Color\b[0] >> 4) + Hex(Color\b[1] >> 4) + Hex(Color\b[2] >> 4)
Else
tmp$ = "#" + RSet(Hex(Color\color), 6, "0")
EndIf
CopyMemory(@tmp$, *Start0, StringByteLength(tmp$))
EndIf
*c + sz
Wend
*text\s = ReplaceString(*text\s, Chr(1), "")
; ProcedureReturn text$
EndProcedure
current$ = GetPathPart(ProgramFilename())
; Global ini$ = current$ + "css_parser_decompression.ini"
Global ini$ = Left(ProgramFilename(), Len(ProgramFilename()) - 3) + "ini"
; чтение параметров ком-строки
CountPP = CountProgramParameters()
If CountPP
flag = Val(ProgramParameter())
If CountPP > 1
source$ = ProgramParameter()
If CountPP > 2
destination$ = ProgramParameter()
EndIf
EndIf
Else
; если нет параметров, то читаем ini-файл
;- ● ini
If OpenPreferences(ini$)
source$ = ReadPreferenceString("source", "")
destination$ = ReadPreferenceString("destination", "")
flag = ReadPreferenceInteger("flag", 0)
open = ReadPreferenceInteger("open", 0)
msg = ReadPreferenceInteger("msg", 0)
ClosePreferences()
EndIf
EndIf
If flag & 1024
msg | 1
EndIf
If flag & 2048
msg | 2
EndIf
If flag & 4096
msg | 4
EndIf
If flag & 8192
open = 1
EndIf
; Если не получили пути, то открываем диалоговое окно выбора.
If Not Asc(source$) Or FileSize(source$) < 0
Debug "source$ = " + source$
source$ = OpenFileRequester("", current$, "*.css|*.css|*.*|*.*", 0)
If Not Asc(source$) Or FileSize(source$) < 0
End ; если выбор отменён, то закрываем программу
EndIf
EndIf
ext$ = GetExtensionPart(source$)
; Если нет пути сохранения или не создан путь к файлу или имя файла содержит некорректные символы, то пытаемся получить путь через диалог открытия файла
If Not Asc(destination$) Or Not ForceDirectories(GetPathPart(destination$)) Or Not CheckFilename(GetFilePart(destination$))
Debug "destination$ = " + destination$
destination$ = Left(source$, Len(source$) - Len(ext$) - 1) + "_2." + ext$ ; формируем путь к файлу для сохранения данных на основе исходного
destination$ = SaveFileRequester("", destination$, "*." + ext$ + "|*." + ext$ + "|*.*|*.*", 0)
If Not Asc(destination$) Or FileSize(GetPathPart(destination$)) <> -2
Debug "неудача-destination$ = " + destination$
End ; если выбор отменён, то закрываем программу
EndIf
EndIf
; Если исходный файл не существует или файл сохранения игнорирован, то завершение программы, дальнейшее выполнятся не будет
; ClearDebugOutput()
; Debug "source$ = " + source$
; Debug "destination$ = " + destination$
Enumeration
#ch1
#ch2
#ch4
#ch16
#ch128
#chmsg1
#chmsg2
#chmsg4
#btnOK
#btnOpen1
#btnOpen2
#fieldPath1
#fieldPath2
#chOpen
EndEnumeration
;-┌──GUI──┐
If flag & 512 And OpenWindow(0, 0, 0, 420, 430, "Настройки css tidy", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
CheckBoxGadget(#ch1, 10, 10, 400, 30, "1 - Сжатие (удаление пробелов)")
CheckBoxGadget(#ch2, 10, 40, 400, 30, "2 - Фигурная скобка '{' на отдельной строке")
CheckBoxGadget(#ch4, 10, 70, 400, 30, "4 - Списки классов в столбик, перенос после ','")
CheckBoxGadget(#ch16, 10, 100, 400, 30, "16 - Преобразовать rgb(x,x,x) в #hex")
CheckBoxGadget(#ch128, 10, 130, 400, 30, "128 - не удалять комментарии при сжатии")
CheckBoxGadget(#chmsg1, 10, 170, 400, 30, "1 - показать ошибки незавершённой кавычки")
CheckBoxGadget(#chmsg2, 10, 200, 400, 30, "2 - показать время выполнения обработки css")
CheckBoxGadget(#chmsg4, 10, 230, 400, 30, "4 - показать пути")
CheckBoxGadget(#chOpen, 10, 270, 400, 30, "Открыть файл после обработки")
If flag & 1
SetGadgetState(#ch1, #PB_Checkbox_Checked)
EndIf
If flag & 2
SetGadgetState(#ch2, #PB_Checkbox_Checked)
EndIf
If flag & 4
SetGadgetState(#ch4, #PB_Checkbox_Checked)
EndIf
If flag & 16
SetGadgetState(#ch16, #PB_Checkbox_Checked)
EndIf
If flag & 128
SetGadgetState(#ch128, #PB_Checkbox_Checked)
EndIf
If msg & 1
SetGadgetState(#chmsg1, #PB_Checkbox_Checked)
EndIf
If msg & 2
SetGadgetState(#chmsg2, #PB_Checkbox_Checked)
EndIf
If msg & 4
SetGadgetState(#chmsg4, #PB_Checkbox_Checked)
EndIf
If open
SetGadgetState(#chOpen, #PB_Checkbox_Checked)
EndIf
StringGadget(#fieldPath1, 10, 310, 400 - 26, 26, source$)
StringGadget(#fieldPath2, 10, 350, 400 - 26, 26, destination$)
ButtonGadget(#btnOpen1, 420 - 36, 310, 26, 26, Chr($2026)) ; … (обзор)
ButtonGadget(#btnOpen2, 420 - 36, 350, 26, 26, Chr($2026)) ; … (обзор)
ButtonGadget(#btnOK, 300, 383, 111, 40, "OK")
;-┌──Loop──┐
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
Break
Case #btnOpen1
tmp$ = OpenFileRequester("", current$, "*.css|*.css|*.*|*.*", 0)
If Asc(tmp$)
SetGadgetText(#fieldPath1, tmp$)
EndIf
Case #btnOpen2
tmp$ = SaveFileRequester("", destination$, "*." + ext$ + "|*." + ext$ + "|*.*|*.*", 0)
If Asc(tmp$)
SetGadgetText(#fieldPath2, tmp$)
EndIf
EndSelect
Case #PB_Event_CloseWindow ; тоже что отмена, закрытие окна ничего не делает
CloseWindow(0)
End
EndSelect
ForEver
;-└──Loop──┘
source$ = GetGadgetText(#fieldPath1)
If Not Asc(source$) Or FileSize(source$) < 0
MessageRequester("", "Исходный файл не существует, завершаем программу")
End ; если выбор отменён, то закрываем программу
EndIf
destination$ = GetGadgetText(#fieldPath2)
If Not Asc(destination$) Or FileSize(GetPathPart(destination$)) <> -2
MessageRequester("", "Не указан файл назначения или не существует каталог для файла, завершаем программу")
End ; если выбор отменён, то закрываем программу
EndIf
flag = 0
If GetGadgetState(#ch1)
flag + 1
EndIf
If GetGadgetState(#ch2)
flag + 2
EndIf
If GetGadgetState(#ch4)
flag + 4
EndIf
If GetGadgetState(#ch16)
flag + 16
EndIf
If GetGadgetState(#ch128)
flag + 128
EndIf
msg = 0
If GetGadgetState(#chmsg1)
msg + 1
EndIf
If GetGadgetState(#chmsg2)
msg + 2
EndIf
If GetGadgetState(#chmsg4)
msg + 4
EndIf
If GetGadgetState(#chOpen)
open = 1
Else
open = 0
EndIf
EndIf
Result\s = OpenFileToGadget(source$) ; вызов функции чтения файла с учётом кодировки.
;- Обработка
If msg & 2
StartTime = ElapsedMilliseconds()
EndIf
If flag & 1
cssCompression(@Result\s)
Result\s = ReplaceString(Result\s, Chr(1), "")
Result\s = ReplaceString(Result\s, ":0 0 0 0;", ":0;")
If flag & 16
RGBtoHEX(@Result)
EndIf
Else
If flag & 16
RGBtoHEX(@Result)
EndIf
cssTidy(@Result\s)
; Вычисляем длину данных css
; Len = 0
ForEach TextList()
Len + Len(TextList())
Next
; Экспортируем список в текстовые данные css
Result\s = Space(Len)
*Point = @Result\s
ForEach TextList()
CopyMemoryString(TextList(), @*Point)
Next
EndIf
If msg & 2
StartTime = ElapsedMilliseconds() - StartTime
EndIf
#File = 0
If CreateFile(#File, destination$, g_Format)
WriteStringFormat(#File, g_Format)
WriteString(#File, Result\s)
CloseFile(#File)
If open
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
RunProgram(destination$) ; открывает файл
CompilerCase #PB_OS_Linux
RunProgram("xdg-open", destination$, "") ; открывает файл
CompilerEndSelect
EndIf
EndIf
;- Message
; Вывод сообщений
If msg & 1 And Error
; реагируем на ошибку, когда открыта кавычка, но не найдена закрывающая кавычка, пришлось оборвать ожидание кавычки на конце строки
Message$ + "Количество ошибок: " + Str(Error) + #CRLF$
EndIf
If msg & 2
Message$ + "Выполнено за " + Str(StartTime) + " мсек" + #CRLF$
EndIf
If msg & 4
Message$ + source$ + #CRLF$ + destination$ + #CRLF$
EndIf
If Asc(Message$)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
MessageRequester("info", Message$, #MB_SYSTEMMODAL)
CompilerCase #PB_OS_Linux
MessageRequester("info", Message$)
CompilerEndSelect
EndIf
;- END