1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Evgeny Muravjev Typograph, http://mdash.ru |
4
|
|
|
* Version: 3.0 Gold Master |
5
|
|
|
* Release Date: September 28, 2013 |
6
|
|
|
* Authors: Evgeny Muravjev & Alexander Drutsa |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace EMT; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Class EMTypograph |
13
|
|
|
* @package EMT |
14
|
|
|
*/ |
15
|
|
|
class EMTypograph extends AbstractTypograph |
16
|
|
|
{ |
17
|
|
|
public $trets = array( |
18
|
|
|
'\EMT\Tret\Quote', |
19
|
|
|
'\EMT\Tret\Dash', |
20
|
|
|
'\EMT\Tret\Symbol', |
21
|
|
|
'\EMT\Tret\Punctmark', |
22
|
|
|
'\EMT\Tret\Number', |
23
|
|
|
'\EMT\Tret\Space', |
24
|
|
|
'\EMT\Tret\Abbr', |
25
|
|
|
'\EMT\Tret\Nobr', |
26
|
|
|
'\EMT\Tret\Date', |
27
|
|
|
'\EMT\Tret\OptAlign', |
28
|
|
|
'\EMT\Tret\Etc', |
29
|
|
|
'\EMT\Tret\Text' |
30
|
|
|
); |
31
|
|
|
|
32
|
|
|
protected $group_list = array( |
33
|
|
|
'Quote' => true, |
34
|
|
|
'Dash' => true, |
35
|
|
|
'Nobr' => true, |
36
|
|
|
'Symbol' => true, |
37
|
|
|
'Punctmark' => true, |
38
|
|
|
'Number' => true, |
39
|
|
|
'Date' => true, |
40
|
|
|
'Space' => true, |
41
|
|
|
'Abbr' => true, |
42
|
|
|
'OptAlign' => true, |
43
|
|
|
'Text' => true, |
44
|
|
|
'Etc' => true, |
45
|
|
|
); |
46
|
|
|
protected $all_options = array( |
47
|
|
|
|
48
|
|
|
'Quote.quotes' => array( 'description' => 'Расстановка «кавычек-елочек» первого уровня', 'selector' => "Quote.*quote" ), |
49
|
|
|
'Quote.quotation' => array( 'description' => 'Внутренние кавычки-лапки', 'selector' => "Quote", 'setting' => 'no_bdquotes', 'reversed' => true ), |
50
|
|
|
|
51
|
|
|
'Dash.to_libo_nibud' => 'direct', |
52
|
|
|
'Dash.iz_za_pod' => 'direct', |
53
|
|
|
'Dash.ka_de_kas' => 'direct', |
54
|
|
|
|
55
|
|
|
'Nobr.super_nbsp' => 'direct', |
56
|
|
|
'Nobr.nbsp_in_the_end' => 'direct', |
57
|
|
|
'Nobr.phone_builder' => 'direct', |
58
|
|
|
'Nobr.ip_address' => 'direct', |
59
|
|
|
'Nobr.spaces_nobr_in_surname_abbr' => 'direct', |
60
|
|
|
'Nobr.nbsp_celcius' => 'direct', |
61
|
|
|
'Nobr.hyphen_nowrap_in_small_words' => 'direct', |
62
|
|
|
'Nobr.hyphen_nowrap' => 'direct', |
63
|
|
|
'Nobr.nowrap' => array('description' => 'Nobr (по умолчанию) & nowrap', 'disabled' => true, 'selector' => '*', 'setting' => 'nowrap' ), |
64
|
|
|
|
65
|
|
|
'Symbol.tm_replace' => 'direct', |
66
|
|
|
'Symbol.r_sign_replace' => 'direct', |
67
|
|
|
'Symbol.copy_replace' => 'direct', |
68
|
|
|
'Symbol.apostrophe' => 'direct', |
69
|
|
|
'Symbol.degree_f' => 'direct', |
70
|
|
|
'Symbol.arrows_symbols' => 'direct', |
71
|
|
|
'Symbol.no_inches' => array( 'description' => 'Расстановка дюйма после числа', 'selector' => "Quote", 'setting' => 'no_inches', 'reversed' => true ), |
72
|
|
|
|
73
|
|
|
'Punctmark.auto_comma' => 'direct', |
74
|
|
|
'Punctmark.hellip' => 'direct', |
75
|
|
|
'Punctmark.fix_pmarks' => 'direct', |
76
|
|
|
'Punctmark.fix_excl_quest_marks' => 'direct', |
77
|
|
|
'Punctmark.dot_on_end' => 'direct', |
78
|
|
|
|
79
|
|
|
'Number.minus_between_nums' => 'direct', |
80
|
|
|
'Number.minus_in_numbers_range' => 'direct', |
81
|
|
|
'Number.auto_times_x' => 'direct', |
82
|
|
|
'Number.simple_fraction' => 'direct', |
83
|
|
|
'Number.math_chars' => 'direct', |
84
|
|
|
//'Number.split_number_to_triads' => 'direct', |
85
|
|
|
'Number.thinsp_between_number_triads' => 'direct', |
86
|
|
|
'Number.thinsp_between_no_and_number' => 'direct', |
87
|
|
|
'Number.thinsp_between_sect_and_number' => 'direct', |
88
|
|
|
|
89
|
|
|
'Date.years' => 'direct', |
90
|
|
|
'Date.mdash_month_interval' => 'direct', |
91
|
|
|
'Date.nbsp_and_dash_month_interval' => 'direct', |
92
|
|
|
'Date.nobr_year_in_date' => 'direct', |
93
|
|
|
|
94
|
|
|
'Space.many_spaces_to_one' => 'direct', |
95
|
|
|
'Space.clear_percent' => 'direct', |
96
|
|
|
'Space.clear_before_after_punct' => array( 'description' => 'Удаление пробелов перед и после знаков препинания в предложении', 'selector' => 'Space.remove_space_before_punctuationmarks'), |
97
|
|
|
'Space.autospace_after' => array( 'description' => 'Расстановка пробелов после знаков препинания', 'selector' => 'Space.autospace_after_*'), |
98
|
|
|
'Space.bracket_fix' => array( 'description' => 'Удаление пробелов внутри скобок, а также расстановка пробела перед скобками', |
99
|
|
|
'selector' => array('Space.nbsp_before_open_quote', 'Punctmark.fix_brackets')), |
100
|
|
|
|
101
|
|
|
'Abbr.nbsp_money_abbr' => 'direct', |
102
|
|
|
'Abbr.nobr_vtch_itd_itp' => 'direct', |
103
|
|
|
'Abbr.nobr_sm_im' => 'direct', |
104
|
|
|
'Abbr.nobr_acronym' => 'direct', |
105
|
|
|
'Abbr.nobr_locations' => 'direct', |
106
|
|
|
'Abbr.nobr_abbreviation' => 'direct', |
107
|
|
|
'Abbr.ps_pps' => 'direct', |
108
|
|
|
'Abbr.nbsp_org_abbr' => 'direct', |
109
|
|
|
'Abbr.nobr_gost' => 'direct', |
110
|
|
|
'Abbr.nobr_before_unit_volt' => 'direct', |
111
|
|
|
'Abbr.nbsp_before_unit' => 'direct', |
112
|
|
|
|
113
|
|
|
'OptAlign.all' => array( 'description' => 'Inline стили или CSS', 'hide' => true, 'selector' => 'OptAlign.*'), |
114
|
|
|
'OptAlign.oa_oquote' => 'direct', |
115
|
|
|
'OptAlign.oa_obracket_coma' => 'direct', |
116
|
|
|
'OptAlign.oa_oquote_extra' => 'direct', |
117
|
|
|
'OptAlign.layout' => array( 'description' => 'Inline стили или CSS' ), |
118
|
|
|
|
119
|
|
|
'Text.paragraphs' => 'direct', |
120
|
|
|
'Text.auto_links' => 'direct', |
121
|
|
|
'Text.email' => 'direct', |
122
|
|
|
'Text.breakline' => 'direct', |
123
|
|
|
'Text.no_repeat_words' => 'direct', |
124
|
|
|
|
125
|
|
|
//'Etc.no_nbsp_in_nobr' => 'direct', |
126
|
|
|
'Etc.unicode_convert' => array('description' => 'Преобразовывать html-сущности в юникод', 'selector' => '*', 'setting' => 'dounicode' , 'disabled' => true), |
127
|
|
|
|
128
|
|
|
); |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Получить список имеющихся опций |
132
|
|
|
* |
133
|
|
|
* @return array |
134
|
|
|
* all - полный список |
135
|
|
|
* group - сгруппрованный по группам |
136
|
|
|
*/ |
137
|
|
|
public function get_options_list() |
138
|
|
|
{ |
139
|
|
|
$arr['all'] = array(); |
|
|
|
|
140
|
|
|
$bygroup = array(); |
141
|
|
|
foreach ($this->all_options as $opt => $op) { |
142
|
|
|
$arr['all'][$opt] = $this->get_option_info($opt); |
143
|
|
|
$x = explode(".",$opt); |
144
|
|
|
$bygroup[$x[0]][] = $opt; |
145
|
|
|
} |
146
|
|
|
$arr['group'] = array(); |
147
|
|
|
foreach ($this->group_list as $group => $ginfo) { |
148
|
|
|
if ($ginfo === true) { |
149
|
|
|
$tret = $this->get_tret($group); |
150
|
|
|
if($tret) $info['title'] = $tret->title; else $info['title'] = "Не определено"; |
|
|
|
|
151
|
|
|
} else { |
152
|
|
|
$info = $ginfo; |
153
|
|
|
} |
154
|
|
|
$info['name'] = $group; |
|
|
|
|
155
|
|
|
$info['options'] = array(); |
156
|
|
|
if(is_array($bygroup[$group])) foreach($bygroup[$group] as $opt) $info['options'][] = $opt; |
157
|
|
|
$arr['group'][] = $info; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
return $arr; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Получить информацию о настройке |
165
|
|
|
* |
166
|
|
|
* @param string $key |
167
|
|
|
* @return array|false |
168
|
|
|
*/ |
169
|
|
|
protected function get_option_info($key) |
170
|
|
|
{ |
171
|
|
|
if (!isset($this->all_options[$key])) { |
172
|
|
|
return false; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
if (is_array($this->all_options[$key])) { |
176
|
|
|
return $this->all_options[$key]; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
if (($this->all_options[$key] == "direct") || ($this->all_options[$key] == "reverse")) { |
180
|
|
|
$pa = explode(".", $key); |
181
|
|
|
$tret_pattern = $pa[0]; |
182
|
|
|
$tret = $this->get_tret($tret_pattern); |
183
|
|
|
|
184
|
|
|
if (!$tret) { |
185
|
|
|
return false; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
if (!isset($tret->rules[$pa[1]])) { |
189
|
|
|
return false; |
190
|
|
|
} |
191
|
|
|
$array = $tret->rules[$pa[1]]; |
192
|
|
|
$array['way'] = $this->all_options[$key]; |
193
|
|
|
|
194
|
|
|
return $array; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
return false; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Установка одной метанастройки |
202
|
|
|
* |
203
|
|
|
* @param string $name |
204
|
|
|
* @param mixed $value |
205
|
|
|
*/ |
206
|
|
|
public function do_setup($name, $value) |
207
|
|
|
{ |
208
|
|
|
if (!isset($this->all_options[$name])) { |
209
|
|
|
return; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
// эта настрока связана с правилом ядра |
213
|
|
|
if (is_string($this->all_options[$name])) { |
214
|
|
|
$this->set($name, "active", $value ); |
215
|
|
|
|
216
|
|
|
return ; |
217
|
|
|
} |
218
|
|
|
if (is_array($this->all_options[$name])) { |
219
|
|
|
if (isset($this->all_options[$name]['selector'])) { |
220
|
|
|
$settingname = "active"; |
221
|
|
|
if(isset($this->all_options[$name]['setting'])) $settingname = $this->all_options[$name]['setting']; |
222
|
|
|
$this->set($this->all_options[$name]['selector'], $settingname, $value); |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
if ($name == "OptAlign.layout") { |
227
|
|
|
if($value == "style") $this->set_tag_layout(Util::LAYOUT_STYLE); |
228
|
|
|
if($value == "class") $this->set_tag_layout(Util::LAYOUT_CLASS); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Запустить типограф со стандартными параметрами |
235
|
|
|
* |
236
|
|
|
* @param string $text |
237
|
|
|
* @param array $options |
238
|
|
|
* @return string |
239
|
|
|
*/ |
240
|
|
|
public static function fast_apply($text, $options = null) |
241
|
|
|
{ |
242
|
|
|
$obj = new self(); |
243
|
|
|
|
244
|
|
|
if (is_array($options)) { |
245
|
|
|
$obj->setup($options); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
$obj->set_text($text); |
249
|
|
|
|
250
|
|
|
return $obj->apply(); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* @param string $text |
255
|
|
|
* @return string |
256
|
|
|
*/ |
257
|
|
|
public function process($text) |
258
|
|
|
{ |
259
|
|
|
$this->set_text($text); |
260
|
|
|
return $this->apply(); |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
|
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.
Let’s take a look at an example:
As you can see in this example, the array
$myArray
is initialized the first time when the foreach loop is entered. You can also see that the value of thebar
key is only written conditionally; thus, its value might result from a previous iteration.This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.