Многие знают, что в Chrome Development Tools встроен удобный редактор CSS, отображающий изменения мгновенно. Единственная проблема – отсутствие возможности удобного автоматического сохранения изменений.

Для решения задачи автосохранения существуют три расширения для Chrome: DevTools Autosave, Tincr и Save CSS. Так как работа с файлами на диске у расширений невозможна, все они перехватывают событие изменения CSS, а текст измененного файла (или только фрагмент в случае DevTools autosave) отправляется запросом на localhost, на котором уже серверная программа сохраняет непосредственно в файл.
Вышеперечисленные расширения для сохранения в файл используют скрипты на Python, Node.js или Ruby. Мне же, как PHP программисту не связанному с этими языками хотелось простое One click решение для Windows, без необходимости установки ненужных мне в своей работе серверов.
Поэтому я решил написать простенькую утилиту под Windows, решающую эту задачу.
Был выбран скриптовый язык AutoIt как наиболее простой способ быстро получить результат.
Капитан Паранойя подсказывает, что вместо третьего пункта можно сделать следующее:
Если в файле CSS есть комментарии или префиксы вендоров — они тоже сохранятся.
Обновление 16.02.2013:
Исправлена ошибка, возникающая из за незакрытого сокета. Теперь сервер работает корректно.
Скрипт выше и exe файл по ссылке обновлены.
Обновление 18.04.2013:
Исправлена ошибка, когда CSS сохранялся вместе с http заголовком.
Скрипт выше и exe файл по ссылке обновлены.
Автор первого фото Exey Panteleev
Текст и скриншоты раздела «Использование» взяты с сайта автора Save CSS

Для решения задачи автосохранения существуют три расширения для Chrome: DevTools Autosave, Tincr и Save CSS. Так как работа с файлами на диске у расширений невозможна, все они перехватывают событие изменения CSS, а текст измененного файла (или только фрагмент в случае DevTools autosave) отправляется запросом на localhost, на котором уже серверная программа сохраняет непосредственно в файл.
Вышеперечисленные расширения для сохранения в файл используют скрипты на Python, Node.js или Ruby. Мне же, как PHP программисту не связанному с этими языками хотелось простое One click решение для Windows, без необходимости установки ненужных мне в своей работе серверов.
Поэтому я решил написать простенькую утилиту под Windows, решающую эту задачу.
Был выбран скриптовый язык AutoIt как наиболее простой способ быстро получить результат.
Текст скрипта (Обновлен 18 апреля 2013)
#cs # save-css-server.au3: receive CSS and JS files from Chrome extension # and save files locally # # Author: Ilya Zenin # Based on AutoIt HTTP Server by Manadar # 18.01.2013 - Created # 16.02.2013 - Updated # 18.04.2013 - Updated #ce Local $sIP = "127.0.0.1"; ip address Local $iPort = 8080 ; the listening port Local $sBuffer = ""; Local $aSavedFilepaths = ""; needed to show tray tip only once per file Local $iStartTime = TimerInit() TCPStartup() $iMainSocket = TCPListen($sIP, $iPort, 10) If @error Then MsgBox(0x20, "Save CSS server", "Unable to create a socket on port " & $iPort & ".") Exit EndIf ConsoleWrite("Save CSS server running at port " & $iPort & "..."& @CRLF) TrayTip("Save CSS server", "Save CSS server running at port " & $iPort & "...", 0, 0) While True $iSock = TCPAccept($iMainSocket) ;Check for new connections If TimerDiff($iStartTime) > 250 Then ;reset tray icon to standart TraySetIcon() EndIf sleep(10) If $iSock = -1 Then ContinueLoop If _TCP_Server_ClientIP($iSock) <> "127.0.0.1" Then ConsoleWrite("External connection! Disconnect." & @CRLF) TCPCloseSocket($iSock) ; Kill any not local connections ContinueLoop EndIf ConsoleWrite("A new client has connected!" & @CRLF) $sBuffer = "" $break = false; Do $sRecv = TCPRecv($iSock, 2048) If $sRecv Then $sBuffer &= $sRecv $receivedLength = StringLen($sRecv); $bufferLength = StringLen($sBuffer); $headerLength = StringInStr($sBuffer, @CRLF&@CRLF) + 3 $array = StringRegExp($sBuffer, 'Content-Length: (.*)', 2) $contentLength = StringStripCR($array[1]) If ($contentLength + $headerLength == $bufferLength) Then $break = True EndIf EndIf Until $break ConsoleWrite("READY!" & @CRLF) $array = StringRegExp($sBuffer, 'X-origurl: (.*)', 2) $xOrigurl = StringStripCR($array[1]); $array = StringRegExp($sBuffer, 'X-filepath: (.*)', 2) $xFilepath = urldecode(StringStripCR($array[1])); $body = StringTrimLeft($sBuffer, $headerLength) ConsoleWrite("Saving file " & $xFilepath) Local $file = FileOpen($xFilepath, 2) $result = FileWrite ($file, $body) FileClose($file) If $result == 1 Then ConsoleWrite(" - Success " & @CRLF); If Not StringInStr($aSavedFilepaths, $xFilepath) Then ; show tray bubble only once per file TrayTip("Save CSS server", $xFilepath & " - saved!", 1, 0) $aSavedFilepaths &= '|'&$xFilepath; EndIf TraySetIcon("info"); $iStartTime = TimerInit() Else ConsoleWrite(" - ERROR!!!"& @CRLF); TrayTip("Save CSS server ERROR", $xFilepath & " - file save error!", 0, 3) EndIf $sBuffer = "" $sRecv = "" $iSock = -1 TCPSend($iMainSocket, "HTTP/1.1 200 OK"& @CRLF) TCPSend($iMainSocket, "Content-Length: 2"& @CRLF) TCPSend($iMainSocket, @CRLF) TCPSend($iMainSocket, "OK") TCPCloseSocket($iMainSocket) sleep(1000) TCPShutdown () TCPStartup() $iMainSocket = TCPListen($sIP, $iPort, 1) WEnd Func urldecode($str) Local $i, $return, $tmp $return = "" $str = StringReplace ($str, "+", " ") For $i = 1 To StringLen($str) $tmp = StringMid($str, $i, 3) If StringRegExp($tmp, "%[0-9A-Fa-f]{2}", 0) = 1 Then $i += 2 While StringRegExp(StringMid($str, $i+1, 3), "%[0-9A-Fa-f]{2}", 0) = 1 $tmp = $tmp & StringMid($str, $i+2, 2) $i += 3 Wend $return &= BinaryToString(StringRegExpReplace($tmp, "%([0-9A-Fa-f]*)", "0x$1"), 4) Else $return &= StringMid($str, $i, 1) EndIf Next Return $return EndFunc ; Function to return IP Address from a connected socket. ;---------------------------------------------------------------------- Func _TCP_Server_ClientIP($hSocket) Local $pSocketAddress, $aReturn $pSocketAddress = DllStructCreate("short;ushort;uint;char[8]") $aReturn = DllCall("Ws2_32.dll", "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($pSocketAddress), "int*", DllStructGetSize($pSocketAddress)) If @error Or $aReturn[0] <> 0 Then Return 0 $aReturn = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($pSocketAddress, 3)) If @error Then Return 0 $pSocketAddress = 0 Return $aReturn[0] EndFunc
Установка
- Ставим расширение Save CSS в хроме из стора
- Возможно потребуется включить экспериментальное API в настройках хрома chrome://flags/
- Скачиваем и запускаем exe файл серверной части (людям со страхом к скачиванию EXE читать ниже)
- В хроме в Developer Tools настраиваем соответствие путей виртуального сервера и файлов на диске, например так:

- Профит: Теперь сразу после изменения стилей в трее всплывет уведомление о сохранении файла. Чтобы постоянно всплывающие сообщения не мешали, они всплывают только 1 раз на файл, последующие автосохранения будет только моргать иконка:

Капитан Паранойя подсказывает, что вместо третьего пункта можно сделать следующее:
- Скачиваем и устанавливаем autoit (http://www.autoitscript.com/)
- Сохраняем вышеприведенный скрипт как save-css-server.au3
- Правой клавишей на файле -> compile script
- Запускаем exe
Использование
| Чтобы поменять свойство CSS кликните на имя свойства или значение и введите с клавиатуры. Цифровые значения могут быть так же изменены колесом мыши или стрелочками вверх/вниз на клавиатуре |
![]() |
| Чтобы добавить новое свойство два раза щелкните на строке с символом “}” и напишите имя свойства | ![]() |
| Чтобы удалить свойство сотрите его имя и нажмите enter | ![]() |
Если в файле CSS есть комментарии или префиксы вендоров — они тоже сохранятся.
Обновление 16.02.2013:
Исправлена ошибка, возникающая из за незакрытого сокета. Теперь сервер работает корректно.
Скрипт выше и exe файл по ссылке обновлены.
Обновление 18.04.2013:
Исправлена ошибка, когда CSS сохранялся вместе с http заголовком.
Скрипт выше и exe файл по ссылке обновлены.
Автор первого фото Exey Panteleev
Текст и скриншоты раздела «Использование» взяты с сайта автора Save CSS




