Удобное редактирование CSS (Chrome + Save CSS + autoIt)

Многие знают, что в Chrome Development Tools встроен удобный редактор 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




Установка


  1. Ставим расширение Save CSS в хроме из стора
  2. Возможно потребуется включить экспериментальное API в настройках хрома chrome://flags/
  3. Скачиваем и запускаем exe файл серверной части (людям со страхом к скачиванию EXE читать ниже)
  4. В хроме в Developer Tools настраиваем соответствие путей виртуального сервера и файлов на диске, например так:
  5. Профит: Теперь сразу после изменения стилей в трее всплывет уведомление о сохранении файла. Чтобы постоянно всплывающие сообщения не мешали, они всплывают только 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

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 27

    +7
      0
      WebStorm — 49$
      Chrome + Save CSS + autoIt — Free
        +10
        WebStorm EAP — бесплатно.
          +1
          Brackets еще немного сыроват, но вроде как тоже самое делает и тоже бесплатен. К тому же и html правит подобным образом, и откатываться по CTRL+Z умеет…
            –1
            Я думаю можно повторить идею FireFile плагина FF, который сам заливает css на сайт через предустановленный php скрипт.

            Была бы эта вещь удобнее, как в notepad++ или neatbeans — цены бы не было.



            +1
            Видел это видео. Работал с PHPStorm — почему то достаточно часто происходила полная перезагрузка страницы, вместо изменения только одного стиля. А это очень неудобно, если настраиваешь внешний вид открытого модального окна.

            Приходилось или постоянно кликать, или городить хаки с автоматическим открыванием окон, загрузки аяксовых данных и т.д.

            В общем, с редактированием CSS в PHPStorm у меня как то не сложилось.
              0
              Я сам данным функционалом не пользуюсь (верстка вне моих обязанностей), но подозреваю, что это уже может быть пофикшено — они его регулярно обновляют.
                0
                Да беда везде с этими wusiwug везде капитально(
                в Neatbeans встроеный браузер не работает.
                В php storm через мост не очень удобно.
                Можно через плагин Refrash в FF делать автообновление страницы по таймеру, а в блокноте ctrl+s. Но выбешивает регулярное мелькание браузера при перестройке DOM.
                0
                тоже перестал пользоваться — тормозить стало все и браузер и шторм. на железо не грешу i5 — SSD и 16 гигов RAM — куда уж больше.
              0
              Это здорово, но что делать, если во время редактирования и экспериментов со стилями вы ошиблись и зашли «слишком не туда» и нужно откатить на то, что было до этого?

              Есть ли история изменений? Ревизии?
                0
                Я считаю что это другая задача, и должна ложиться на систему контроля версий.
                Лично я пушу в mercurial после и перед значительными изменениями, поэтому такая проблема не возникает.
                0
                А не писал ли кто подобных велосипедов под FF?
                  –1
                  я давно жду html редактор как есть в firebug только удобнее. Чтобы верстать прямо в браузере.
                  Под FF есть habrahabr.ru/post/142277/ платный cssUpdater
                  или бесплатный FireFile

                  Но последний замечен в убивании комментариев в css. И само собой нужно понимать, что никаких префикосов для других браузеров все способы и вроде как и в статье не сохраняются.
                    0
                    В статье в самом конце я написал что комментарии сохраняются в Chrome.
                      –1
                      извини, я про FireFile писал плагин для FF. Он сразу на сайт заливает с браузера css правленный,(без ftp) только сыроват плагин.
                      0
                      Да, о префиксах я не подумал.
                      Пока будем по старинке — подогнал в FF, переключился на Eclipse…
                      0
                      Я использую связку php-storm — firefox c офигенным плагином x-fire, который все изменения css в фаербаге отображает в нижней панельке ide, откуда их можно выборочно применять к исходному коду. Ничего удобнее пока не встречал.
                      0
                      По ссылке на экзешник
                      Nothing Here
                      The file you are looking for has been deleted or moved.
                        0
                        Спасибо, исправил.
                        –1
                        К сожалению мне не подойдет, я пользуюсь препроцессорами для CSS
                        • UFO just landed and posted this here
                          0
                          Я один зашёл под кат в надежде увидеть ещё картинок с CSS-бодиартом?
                            0
                            У меня сохраняет 3-4 изменения в css и save-css-server это показывает своим значком, а потом просто перестает сохранять.
                              0
                              Ошибка локализована, исправлена, обновления внесены в исходник скрипта и exe файл.
                              Прошу прощения что так долго. =/
                              0
                              Кому интересно, для Sublime Text есть github.com/dz0ny/LiveReload-sublimetext2.
                                0
                                А еще он имеет свойство крашиться, поэтому сразу лучше ставить версию с dev ветки.
                                0
                                Очень рекомендую css_refresh.
                                Подключаете на странице один js-скрипт и получаете почти мгновенное обновление стилей, которые вы редактируете в IDE. Работает со всеми браузерами.

                                Only users with full accounts can post comments. Log in, please.