regexp renovations

This commit is contained in:
Ilya Kantor 2015-03-19 17:20:12 +03:00
parent b2f6df9d45
commit bf85f46cf9
24 changed files with 311 additions and 132 deletions

View file

@ -0,0 +1,6 @@
Результат: `123 456`.
Ленивый `\d+?` будет брать цифры до пробела, то есть `123`. После каждой цифры он будет останавливаться, проверять -- не пробел ли дальше? Если нет -- брать ещё цифру, в итоге возьмёт `123`.
З в дело вступит `\d+`, который по-максимуму возьмёт дальнейшие цифры, то есть `456`.

View file

@ -0,0 +1,13 @@
# Совпадение для /d+? d+/
Мы разобрали совпадение:
```js
"123 456".match(/\d+ \d+?/g) ); // 123 4
```
А что будет, если сначала поставить ленивый, а потом жадный квантификаторы?
```js
"123 456".match(/\d+? \d+/g) ); // какой результат?
```

View file

@ -1,4 +1,4 @@
# Жадные и ленивые квантификаторы [todo]
# Жадные и ленивые квантификаторы
Квантификаторы -- с виду очень простая, но на самом деле очень хитрая штука.
@ -55,7 +55,7 @@ alert( str.match(reg) ); // "witch" and her "broom"
</li>
<li>Кавычка найдена, далее движок проверяет, есть ли соответствие для остальной части паттерна.
В данном случае следующий символ паттерна -- `.` (точка). Она обозначает "любой символ", так что следующая буква строки <code class="match">'w'</code> вполне подходит:
В данном случае следующий символ шаблона: <code class="pattern">.</code> (точка). Она обозначает "любой символ", так что следующая буква строки <code class="match">'w'</code> вполне подходит:
<img src="witch_greedy2.svg">
</li>
<li>Далее "любой символ" повторяется, так как стоит квантификатор <code class="pattern">.+</code>. Движок регулярных выражений берёт один символ за другим, до тех пор, пока у него это получается.
@ -63,32 +63,40 @@ alert( str.match(reg) ); // "witch" and her "broom"
В данном случае это означает "до конца строки":
<img src="witch_greedy3.svg">
</li>
<li>Итак, текст закончился, движок регулярных выражений больше не может найти "любой символ", он закончил строить соответствие для <code class="pattern">.+</code> и очень рад по этому поводу.
<li>Итак, текст закончился, движок регулярных выражений больше не может найти "любой символ", он закончил повторения для <code class="pattern">.+</code> и переходит к следующему символу шаблона.
Следующий символ шаблона -- это кавычка. Её тоже необходимо найти, чтобы соответствие было полным. А тут -- беда, ведь поисковый текст завершился!
Движок регулярных выражений понимает, что, наверное, взял многовато <code class="pattern">.+</code> и начинает отступать обратно ("фаза бэктрекинга" -- backtracking на англ.).
Движок регулярных выражений понимает, что, наверное, взял многовато <code class="pattern">.+</code> и начинает отступать обратно.
Иными словами, он сокращает текущее совпадение на один символ:
<img src="witch_greedy4.png">
<img src="witch_greedy4.svg">
После этого он ещё раз пытается подобрать соответствие для остатка паттерна. Но кавычка <code class="pattern">'"'</code> не совпадает с <code class="subject">'e'</code>.</li>
<li>...Так что движок уменьшает число повторений <code class="pattern">.+</code> ещё раз:
Это называется "фаза возврата" или "фаза бэктрекинга" (backtracking -- англ.).
<img src="witch_greedy5.png">
Теперь <code class="pattern">.+</code> соответствует почти вся оставшаяся строка, за исключением одного символа, и движок регулярных выражений ещё раз пытается подобрать соответствие для остатка шаблона, начиная с оставшейся части строки.
Если бы последним символом строки была кавычка <code class="pattern">'"'</code>, то на этом бы всё и закончилось. Но последний символ <code class="subject">'e'</code>, так что совпадения нет.</li>
<li>...Поэтому движок уменьшает число повторений <code class="pattern">.+</code> ещё на один символ:
<img src="witch_greedy5.svg">
Кавычка <code class="pattern">'"'</code> не совпадает с <code class="subject">'n'</code>. Опять неудача.</li>
<li>Движок продолжает отступать, он уменьшает количество повторений точки <code class="pattern">'.'</code> до тех пор, пока остаток паттерна не совпадёт:
<li>Движок продолжает отступать, он уменьшает количество повторений точки <code class="pattern">'.'</code> до тех пор, пока остаток паттерна, то есть в данном случае кавычка <code class="pattern">'"'</code>, не совпадёт:
<img src="witch_greedy6.png">
<img src="witch_greedy6.svg">
</li>
<li>Мы получили результат. Так как у регэкспа есть флаг `g`, то поиск продолжится, однако это произойдёт после первого совпадения и не даст новых результатов.</li>
<li>Совпадение получено. Дальнейший поиск по оставшейся части строки <code class="subject">is one</code> новых совпадений не даст.</li>
</ol>
Возможно, это не совсем то, что мы ожидали.
**В жадном режиме (по умолчанию) регэксп повторяет квантификатор настолько много раз, насколько это возможно, чтобы найти соответствие.**
Возможно, это не совсем то, что мы хотели, но так это работает.
То есть, любой символ <code class="pattern">.+</code> повторился максимальное количество раз, что и привело к такой длинной строке.
А мы, наверное, хотели, чтобы каждая строка в кавычках была независимым совпадением? Для этого можно переключить квантификатор `+` в "ленивый" режим, о котором будет речь далее.
## Ленивый режим
@ -109,40 +117,38 @@ var str = 'a "witch" and her "broom" is one';
alert( str.match(reg) ); // witch, broom
```
Чтобы в точности понять, что происходим, разберём в деталях, как ищется <code class="pattern">".+?"</code>.
Чтобы в точности понять, как поменялась работа квантификатора, разберём поиск по шагам.
<ol>
<li>Первый шаг -- тот же, кавычка <code class="pattern">'"'</code> найдена на 3й позиции:
<img src="witch_greedy1.png">
<img src="witch_greedy1.svg">
</li>
<li>Второй шаг -- тот же, находим произвольный символ <code class="pattern">'.'</code>:
<img src="witch_greedy2.png">
<img src="witch_greedy2.svg">
</li>
<li>А вот дальше -- так как стоит ленивый режим работы `+`, то движок пытается повторять точку (произвольный символ) *минимальное количество раз*.
<li>А вот дальше -- так как стоит ленивый режим работы `+`, то движок не повторет точку (произвольный символ) ещё раз, а останавливается на достигнутом и пытается проверить, есть ли соответствие остальной части шаблона, то есть <code class="pattern">'"'</code>:
<img src="witch_lazy3.svg">
Так что он тут же пытается проверить, достаточно ли повторить 1 раз -- и для этого пытается найти соответствие остальной части шаблона, то есть <code class="pattern">'"'</code>:
<img src="witch_lazy3.png">
Нет, один раз повторить недостаточно. В данном случае, символ `'i' != '"'`, но если бы оставшаяся часть паттерна была бы более сложной -- алгоритм остался бы тем же. Если остаток шаблона не находится -- увеличиваем количество повторений.
Если бы остальная часть шаблона на данной позиции совпала, то совпадение было бы найдено. Но в данном случе -- нет, символ `'i'` не равен '"'.
</li>
<li>Движок регулярных выражений увиличивает количество повторений точки на одно и пытается найти соответствие остатку шаблона ещё раз:
<img src="witch_lazy4.png">
<img src="witch_lazy4.svg">
Опять неудача. Тогда поисковой движок увеличивает количество повторений ещё и ещё...
</li>
<li>Только на 5м шаге поисковой движок наконец находит соответствие для остатка паттерна:
<img src="witch_lazy5.png">
<img src="witch_lazy5.svg">
</li>
<li>Так как поиск происходит с флагом `g`, то он продолжается с конца текущего совпадения, давая ещё один результат:
<img src="witch_lazy6.png">
<img src="witch_lazy6.svg">
</li>
</ol>
В примере выше продемонстрирована работа ленивого режима для <code class="pattern">+?</code>. Квантификаторы <code class="pattern">+?</code> и <code class="pattern">??</code> ведут себя аналогично -- "ленивый" движок увеличивает количество повторений только в том случае, если для остальной части шаблона на данной позиции нет соответствия, в то время как жадный сначала берёт столько повторений, сколько возможно, а потом отступает назад.
В примере выше продемонстрирована работа ленивого режима для <code class="pattern">+?</code>. Квантификаторы <code class="pattern">+?</code> и <code class="pattern">??</code> ведут себя аналогично -- "ленивый" движок увеличивает количество повторений только в том случае, если для остальной части шаблона на данной позиции нет соответствия.
**Ленивость распространяется только на тот квантификатор, после которого стоит `?`.**
@ -156,14 +162,17 @@ alert( "123 456".match(/\d+ \d+?/g) ); // 123 4
```
<ol>
<li>Подпаттерн <code class="pattern">\d+</code> пытается найти столько символов, сколько возможно (работает жадно), так что он находит <code class="match">123</code> и останавливается, поскольку символ пробела <code class="pattern">' '</code> не подходит под <code class="pattern">\d</code>.</li>
<li>Далее идёт пробел, и в игру вступает <code class="pattern">\d+?</code>.
<li>Подшаблон <code class="pattern">\d+</code> пытается найти столько цифр, сколько возможно (работает жадно), так что он находит <code class="match">123</code> и останавливается, поскольку символ пробела <code class="pattern">' '</code> не подходит под <code class="pattern">\d</code>.</li>
<li>Далее в шаблоне пробел, он совпадает.</li>
<li>Далее в шаблоне идёт <code class="pattern">\d+?</code>.
Он находит один символ <code class="match">'4'</code> и пытатся проверить, есть ли совпадение с остатком шаблона (после <code class="pattern">\d+?</code>).
Квантификатор указан в ленивом режиме, поэтому он находит одну цифру <code class="match">4</code> и пытается проверить, есть ли совпадение с остатком шаблона.
Здесь мы ещё раз заметим -- ленивый режим без необходимости ничего не возьмёт.
Но после <code class="pattern">\d+?</code> в шаблоне ничего нет.
Так как шаблон закончился, то поиск завершается и <code class="match">123 4</code> становится результатом.</li>
**Ленивый режим без необходимости лишний раз квантификатор не повторит.**
Так как шаблон завершился, то искать дальше, в общем-то нечего. Получено совпадение <code class="match">123 4</code>.</li>
<li>Следующий поиск продолжится с `5`, но ничего не найдёт.</li>
</ol>
@ -188,7 +197,139 @@ var str = 'a "witch" and her "broom" is one';
alert( str.match(reg) ); // witch, broom
```
Регэксп <code class="pattern">"[^"]+"</code> даст правильные результаты, поскольку ищет кавычку <code class="pattern">'"'</code>, за которой идут столько не-кавычек (исключающие квадратные скобки), сколько возможно. Так что вторая кавычка автоматически прекращает повторения <code class="pattern">[^"]+</code> и позволяет найти остаток шаблона <code class="pattern">"</code>.
Регэксп <code class="pattern">"[^"]+"</code> даст правильные результаты, поскольку ищет кавычку <code class="pattern">'"'</code>, за которой идут столько не-кавычек (исключающие квадратные скобки), сколько возможно.
Так что вторая кавычка автоматически прекращает повторения <code class="pattern">[^"]+</code> и позволяет найти остаток шаблона <code class="pattern">"</code>.
**Эта логика ни в коей мере не заменяет ленивые квантификаторы!**
Она просто другая. И то и другое бывает полезно.
Давайте посмотрим пример, когда нужен именно такой вариант, а ленивые квантификаторы не подойдут.
Например, мы хотим найти в тексте ссылки вида `<a href="..." class="doc">`, с любым содержанием `href`.
Какое регулярное выражение для этого подойдёт?
Первый вариант может выглядеть так: <code class="pattern">/&lt;a href=".*" class="doc"&gt;/g</code>.
Проверим его:
```js
//+ run
var str = '...<a href="link" class="doc">...';
var reg = /<a href=".*" class="doc">/g;
// Сработало!
alert( str.match(reg) ); // <a href="link" class="doc">
```
А если в тексте несколько ссылок?
```js
//+ run
var str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
var reg = /<a href=".*" class="doc">/g;
// Упс! Сразу две ссылки!
alert( str.match(reg) ); // <a href="link1" class="doc">... <a href="link2" class="doc">
```
На этот раз результат неверен.
Жадный <code class="pattern">.*</code> взял слишком много символов.
Соответствие получилось таким:
```
<a href="....................................." class="doc">
<a href="link1" class="doc">... <a href="link2" class="doc">
```
Модифицируем шаблон -- добавим ленивость квантификатору <code class="pattern">.*?</code>:
```js
//+ run
var str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
var reg = /<a href=".*?" class="doc">/g;
// Сработало!
alert( str.match(reg) ); // <a href="link1" class="doc">, <a href="link2" class="doc">
```
Теперь всё верно, два результата:
```
<a href="....." class="doc"> <a href="....." class="doc">
<a href="link1" class="doc">... <a href="link2" class="doc">
```
Почему теперь всё в порядке -- для внимательного читателя, после объяснений, данных выше в этой главе, должно быть полностью очевидно.
Поэтому не будем останавливаться здесь на деталях, а попробуем ещё пример:
```js
//+ run
var str = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
var reg = /<a href=".*?" class="doc">/g;
// Неправильное совпадение!
alert( str.match(reg) ); // <a href="link1" class="wrong">... <p style="" class="doc">
```
Совпадение -- не ссылка, а более длинный текст.
Получилось следующее:
<ol>
<li>Найдено совпадение <code class="match">&lt;a href="</code>.</li>
<li>Лениво ищем <code class="pattern">.*?</code>, после каждого символа проверяя, есть ли совпадение остальной части шаблона.
Подшаблон <code class="pattern">.*?</code> будет брать символы до тех пор, пока не найдёт <code class="match">class="doc"&gt;</code>.
В данном случае этот поиск закончится уже за пределами ссылки, в теге `<p>`, вообще не имеющем отношения к `<a>`.
</li>
<li>Получившееся совпадение:
```
<a href="..................................." class="doc">
<a href="link1" class="wrong">... <p style="" class="doc">
```
</li>
</ol>
Итак, ленивость нам не помогла.
Необходимо как-то прекратить поиск <code class="pattern">.*</code>, чтобы он не вышел за пределы кавычек.
Для этого мы используем более точное указание, какие символы нам подходят, а какие нет.
Правильный вариант: <code class="pattern">[^"]*</code>. Этот шаблон будет брать все символы до ближайшей кавычки, как раз то, что требуется.
Рабочий пример:
```js
//+ run
var str1 = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
var str2 = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
var reg = /<a href="[^"]*" class="doc">/g;
// Работает!
alert( str1.match(reg) ); // null, совпадений нет, и это верно
alert( str2.match(reg) ); // <a href="link1" class="doc">, <a href="link2" class="doc">
```
## Итого
Квантификаторы имеют два режима работы:
<dl>
<dt>Жадный</dt>
<dd>Режим по умолчанию -- движок регулярных выражений повторяет его по-максимуму. Когда повторять уже нельзя, например нет больше цифр для `\d+`, он продолжает поиск с оставшейся части текста. Если совпадение найти не удалось -- отступает обратно, уменьшая количество повторений.</dd>
<dt>Ленивый</dt>
<dd>При указании после квантификатора символа `?` он работает в ленивом режиме. То есть, он перед каждым повторением проверяет совпадение оставшейся части шаблона на текущей позиции.</dd>
</dl>
Как мы видели в примере выше, ленивый режим -- не панацея от "слишком жадного" забора символов. Альтернатива -- более аккуратно настроенный "жадный", с исключением символов. Как мы увидим далее, можно исключать не только символы, но и целые подшаблоны.

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="463px" height="117px" viewBox="0 0 463 117" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<svg width="463px" height="130px" viewBox="0 0 463 130" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>witch_greedy1.svg</title>
<desc>Created with bin/sketchtool.</desc>
@ -7,14 +7,12 @@
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="witch_greedy1.svg" sketch:type="MSArtboardGroup">
<text id="a-&quot;witch&quot;-and-her-&quot;b" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal" fill="#8A704D">
<tspan x="20" y="82">a "witch" and her "broom" is one</tspan>
<tspan x="20" y="112">a "witch" and her "broom" is one</tspan>
</text>
<text id="--&quot;-----------------" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal">
<tspan x="20" y="47" fill="#CB1E31"> " </tspan>
<tspan x="72.78125" y="47" fill="#B8BAC1"> </tspan>
<tspan x="85.9765625" y="47" fill="#CB1E31"> </tspan>
</text>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="20" width="15" height="77"></rect>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="50" width="15" height="77"></rect>
<path d="M52.0039062,60.4414062 L51.6757812,65.9375 L49.7539062,65.9375 L49.4140625,60.4414062 L52.0039062,60.4414062 Z M56.5625,60.4414062 L56.234375,65.9375 L54.3125,65.9375 L53.9726562,60.4414062 L56.5625,60.4414062 Z" id="--&quot;-----------------" fill="#CB1E31" sketch:type="MSShapeGroup"></path>
<path d="M52.5,9.5 L52.5,44.5" id="Line" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M52.5,44.5 C53.55,40.72 54.45,37.48 55.5,33.7 C53.4,33.7 51.6,33.7 49.5,33.7 C50.55,37.48 51.45,40.72 52.5,44.5 C52.5,44.5 52.5,44.5 52.5,44.5 Z" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="463px" height="117px" viewBox="0 0 463 117" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<svg width="463px" height="130px" viewBox="0 0 463 130" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>witch_greedy2.svg</title>
<desc>Created with bin/sketchtool.</desc>
@ -7,14 +7,13 @@
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="witch_greedy2.svg" sketch:type="MSArtboardGroup">
<text id="a-&quot;witch&quot;-and-her-&quot;b" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal" fill="#8A704D">
<tspan x="20" y="82">a "witch" and her "broom" is one</tspan>
<tspan x="20" y="107">a "witch" and her "broom" is one</tspan>
</text>
<text id="--&quot;.----------------" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal">
<tspan x="20" y="47" fill="#CB1E31"> ".</tspan>
<tspan x="72.78125" y="47" fill="#B8BAC1"> </tspan>
<tspan x="85.9765625" y="47" fill="#CB1E31"> </tspan>
</text>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="20" width="29" height="77"></rect>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="45" width="29" height="77"></rect>
<path d="M52.0039062,55.4414062 L51.6757812,60.9375 L49.7539062,60.9375 L49.4140625,55.4414062 L52.0039062,55.4414062 Z M56.5625,55.4414062 L56.234375,60.9375 L54.3125,60.9375 L53.9726562,55.4414062 L56.5625,55.4414062 Z M66.0898438,68.3085938 C66.3554701,68.3085938 66.6074207,68.3593745 66.8457031,68.4609375 C67.0839856,68.5625005 67.2910147,68.7031241 67.4667969,68.8828125 C67.642579,69.0625009 67.7812495,69.2714832 67.8828125,69.5097656 C67.9843755,69.7480481 68.0351562,70.0039049 68.0351562,70.2773438 C68.0351562,70.5429701 67.9843755,70.7929676 67.8828125,71.0273438 C67.7812495,71.2617199 67.642579,71.466796 67.4667969,71.6425781 C67.2910147,71.8183603 67.0839856,71.9570307 66.8457031,72.0585938 C66.6074207,72.1601568 66.3554701,72.2109375 66.0898438,72.2109375 C65.8164049,72.2109375 65.5625012,72.1601568 65.328125,72.0585938 C65.0937488,71.9570307 64.8886728,71.8183603 64.7128906,71.6425781 C64.5371085,71.466796 64.398438,71.2617199 64.296875,71.0273438 C64.195312,70.7929676 64.1445312,70.5429701 64.1445312,70.2773438 C64.1445312,70.0039049 64.195312,69.7480481 64.296875,69.5097656 C64.398438,69.2714832 64.5371085,69.0625009 64.7128906,68.8828125 C64.8886728,68.7031241 65.0937488,68.5625005 65.328125,68.4609375 C65.5625012,68.3593745 65.8164049,68.3085938 66.0898438,68.3085938 L66.0898438,68.3085938 Z" id="--&quot;.----------------" fill="#CB1E31" sketch:type="MSShapeGroup"></path>
<path d="M48.5,32.5 L69.5,32.5" id="Line" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M69.5,32.5 C65.72,31.45 62.48,30.55 58.7,29.5 C58.7,31.6 58.7,33.4 58.7,35.5 C62.48,34.45 65.72,33.55 69.5,32.5 C69.5,32.5 69.5,32.5 69.5,32.5 Z" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47"></path>
</g>
<g id="witch_greedy3.svg" sketch:type="MSArtboardGroup" transform="translate(455.000000, 0.000000)"></g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Before After
Before After

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="463px" height="117px" viewBox="0 0 463 117" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<svg width="463px" height="130px" viewBox="0 0 463 130" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>witch_lazy3.svg</title>
<desc>Created with bin/sketchtool.</desc>
@ -7,14 +7,14 @@
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="witch_lazy3.svg" sketch:type="MSArtboardGroup">
<text id="a-&quot;witch&quot;-and-her-&quot;b" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal" fill="#8A704D">
<tspan x="20" y="82">a "witch" and her "broom" is one</tspan>
<tspan x="20" y="105">a "witch" and her "broom" is one</tspan>
</text>
<text id="--&quot;.&quot;---------------" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal">
<tspan x="20" y="47" fill="#CB1E31"> ".</tspan>
<tspan x="72.78125" y="47" fill="#B8BAC1">"</tspan>
<tspan x="85.9765625" y="47" fill="#CB1E31"> </tspan>
</text>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="20" width="29" height="77"></rect>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="43" width="29" height="77"></rect>
<path d="M52.0039062,53.4414062 L51.6757812,58.9375 L49.7539062,58.9375 L49.4140625,53.4414062 L52.0039062,53.4414062 Z M56.5625,53.4414062 L56.234375,58.9375 L54.3125,58.9375 L53.9726562,53.4414062 L56.5625,53.4414062 Z M66.0898438,66.3085938 C66.3554701,66.3085938 66.6074207,66.3593745 66.8457031,66.4609375 C67.0839856,66.5625005 67.2910147,66.7031241 67.4667969,66.8828125 C67.642579,67.0625009 67.7812495,67.2714832 67.8828125,67.5097656 C67.9843755,67.7480481 68.0351562,68.0039049 68.0351562,68.2773438 C68.0351562,68.5429701 67.9843755,68.7929676 67.8828125,69.0273438 C67.7812495,69.2617199 67.642579,69.466796 67.4667969,69.6425781 C67.2910147,69.8183603 67.0839856,69.9570307 66.8457031,70.0585938 C66.6074207,70.1601568 66.3554701,70.2109375 66.0898438,70.2109375 C65.8164049,70.2109375 65.5625012,70.1601568 65.328125,70.0585938 C65.0937488,69.9570307 64.8886728,69.8183603 64.7128906,69.6425781 C64.5371085,69.466796 64.398438,69.2617199 64.296875,69.0273438 C64.195312,68.7929676 64.1445312,68.5429701 64.1445312,68.2773438 C64.1445312,68.0039049 64.195312,67.7480481 64.296875,67.5097656 C64.398438,67.2714832 64.5371085,67.0625009 64.7128906,66.8828125 C64.8886728,66.7031241 65.0937488,66.5625005 65.328125,66.4609375 C65.5625012,66.3593745 65.8164049,66.3085938 66.0898438,66.3085938 L66.0898438,66.3085938 Z" id="--&quot;.&quot;---------------" fill="#CB1E31" sketch:type="MSShapeGroup"></path>
<path d="M78.3945312,53.4414062 L78.0664062,58.9375 L76.1445312,58.9375 L75.8046875,53.4414062 L78.3945312,53.4414062 Z" id="Path" fill="#5C8058" sketch:type="MSShapeGroup"></path>
<path d="M82.953125,53.4414062 L82.625,58.9375 L80.703125,58.9375 L80.3632812,53.4414062 L82.953125,53.4414062 Z" id="Path" fill="#5C8058" sketch:type="MSShapeGroup"></path>
<path d="M50.5,33.5 L71.5,33.5" id="Line" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M71.5,33.5 C67.72,32.45 64.48,31.55 60.7,30.5 C60.7,32.6 60.7,34.4 60.7,36.5 C64.48,35.45 67.72,34.55 71.5,33.5 C71.5,33.5 71.5,33.5 71.5,33.5 Z" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before After
Before After

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="463px" height="117px" viewBox="0 0 463 117" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<svg width="463px" height="130px" viewBox="0 0 463 130" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>witch_lazy4.svg</title>
<desc>Created with bin/sketchtool.</desc>
@ -7,14 +7,14 @@
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="witch_lazy4.svg" sketch:type="MSArtboardGroup">
<text id="a-&quot;witch&quot;-and-her-&quot;b" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal" fill="#8A704D">
<tspan x="20" y="82">a "witch" and her "broom" is one</tspan>
<tspan x="20" y="105">a "witch" and her "broom" is one</tspan>
</text>
<text id="--&quot;..&quot;--------------" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal">
<tspan x="20" y="47" fill="#CB1E31"> "..</tspan>
<tspan x="85.9765625" y="47" fill="#B8BAC1">"</tspan>
<tspan x="99.171875" y="47" fill="#CB1E31"> </tspan>
</text>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="20" width="41" height="77"></rect>
<rect id="Rectangle-1" stroke="#E8C48E" sketch:type="MSShapeGroup" x="45" y="43" width="41" height="77"></rect>
<path d="M52.0039062,53.4414062 L51.6757812,58.9375 L49.7539062,58.9375 L49.4140625,53.4414062 L52.0039062,53.4414062 Z M56.5625,53.4414062 L56.234375,58.9375 L54.3125,58.9375 L53.9726562,53.4414062 L56.5625,53.4414062 Z M66.0898438,66.3085938 C66.3554701,66.3085938 66.6074207,66.3593745 66.8457031,66.4609375 C67.0839856,66.5625005 67.2910147,66.7031241 67.4667969,66.8828125 C67.642579,67.0625009 67.7812495,67.2714832 67.8828125,67.5097656 C67.9843755,67.7480481 68.0351562,68.0039049 68.0351562,68.2773438 C68.0351562,68.5429701 67.9843755,68.7929676 67.8828125,69.0273438 C67.7812495,69.2617199 67.642579,69.466796 67.4667969,69.6425781 C67.2910147,69.8183603 67.0839856,69.9570307 66.8457031,70.0585938 C66.6074207,70.1601568 66.3554701,70.2109375 66.0898438,70.2109375 C65.8164049,70.2109375 65.5625012,70.1601568 65.328125,70.0585938 C65.0937488,69.9570307 64.8886728,69.8183603 64.7128906,69.6425781 C64.5371085,69.466796 64.398438,69.2617199 64.296875,69.0273438 C64.195312,68.7929676 64.1445312,68.5429701 64.1445312,68.2773438 C64.1445312,68.0039049 64.195312,67.7480481 64.296875,67.5097656 C64.398438,67.2714832 64.5371085,67.0625009 64.7128906,66.8828125 C64.8886728,66.7031241 65.0937488,66.5625005 65.328125,66.4609375 C65.5625012,66.3593745 65.8164049,66.3085938 66.0898438,66.3085938 L66.0898438,66.3085938 Z M79.2851562,66.3085938 C79.5507826,66.3085938 79.8027332,66.3593745 80.0410156,66.4609375 C80.2792981,66.5625005 80.4863272,66.7031241 80.6621094,66.8828125 C80.8378915,67.0625009 80.976562,67.2714832 81.078125,67.5097656 C81.179688,67.7480481 81.2304688,68.0039049 81.2304688,68.2773438 C81.2304688,68.5429701 81.179688,68.7929676 81.078125,69.0273438 C80.976562,69.2617199 80.8378915,69.466796 80.6621094,69.6425781 C80.4863272,69.8183603 80.2792981,69.9570307 80.0410156,70.0585938 C79.8027332,70.1601568 79.5507826,70.2109375 79.2851562,70.2109375 C79.0117174,70.2109375 78.7578137,70.1601568 78.5234375,70.0585938 C78.2890613,69.9570307 78.0839853,69.8183603 77.9082031,69.6425781 C77.732421,69.466796 77.5937505,69.2617199 77.4921875,69.0273438 C77.3906245,68.7929676 77.3398438,68.5429701 77.3398438,68.2773438 C77.3398438,68.0039049 77.3906245,67.7480481 77.4921875,67.5097656 C77.5937505,67.2714832 77.732421,67.0625009 77.9082031,66.8828125 C78.0839853,66.7031241 78.2890613,66.5625005 78.5234375,66.4609375 C78.7578137,66.3593745 79.0117174,66.3085938 79.2851562,66.3085938 L79.2851562,66.3085938 Z" id="--&quot;..&quot;--------------" fill="#CB1E31" sketch:type="MSShapeGroup"></path>
<path d="M91.5898438,53.4414062 L91.2617188,58.9375 L89.3398438,58.9375 L89,53.4414062 L91.5898438,53.4414062 Z" id="Path" fill="#5C8058" sketch:type="MSShapeGroup"></path>
<path d="M96.1484375,53.4414062 L95.8203125,58.9375 L93.8984375,58.9375 L93.5585938,53.4414062 L96.1484375,53.4414062 Z" id="Path" fill="#5C8058" sketch:type="MSShapeGroup"></path>
<path d="M50.5,29.5 L81.5,29.5" id="Line" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M81.5,29.5 C77.72,28.45 74.48,27.55 70.7,26.5 C70.7,28.6 70.7,30.4 70.7,32.5 C74.48,31.45 77.72,30.55 81.5,29.5 C81.5,29.5 81.5,29.5 81.5,29.5 Z" stroke="#EE6B47" stroke-linecap="square" fill="#EE6B47"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After