diff --git a/doc/class-apemsel.AttributedString.AttributedString.html b/doc/class-apemsel.AttributedString.AttributedString.html
index 7a7c494..d3f642b 100644
--- a/doc/class-apemsel.AttributedString.AttributedString.html
+++ b/doc/class-apemsel.AttributedString.AttributedString.html
@@ -124,7 +124,7 @@
Direct known subclasses
Author:
Adrian Pemsel apemsel@gmail.com
- Located at AttributedString.php
+ Located at AttributedString.php
@@ -694,7 +694,7 @@ Returns
#
- toHtml( string $tag = "span", string $classPrefix = "" )
+ toHtml( string $tag = "span", string $classPrefix = "" )
Convert to HTML, using a given class to mark attribute spans
@@ -717,10 +717,6 @@ Returns
string HTML
- Throws
-
- Exception if the AttributedString cannot be converted to HTML due to improper nesting
-
@@ -738,7 +734,7 @@ Throws
#
- combineAttributes( string $op, string $attribute1, string $attribute2 = false, string $to = false )
+ combineAttributes( string $op, string $attribute1, string $attribute2 = false, string $to = false )
Combine attributes with the given boolean operation
@@ -768,6 +764,44 @@ Throws
+
+ |
+
+
+
+
+ public
+
+
+
+ |
+
+
+ #
+ attributeToString( string $attribute, string $true = "-", string $false = " " )
+
+
+ Convert attribute map to a visual string representation (e.g. for debugging)
+
+
+
+ Convert attribute map to a visual string representation (e.g. for debugging)
+
+
+ Parameters
+
+ - $attribute
+ - name of the attribute
+ - $true
+ - char to use for true state of attribute
+ - $false
+ - char to use for false state of attribute
+
+
+
+
+
+
|
@@ -782,7 +816,7 @@ Throws
#
- enablebyteToCharCache( )
+ enablebyteToCharCache( )
Enable and fill cache for byte to char offset conversion
@@ -813,7 +847,7 @@ Throws
#
- byteToCharOffset( $boff )
+ byteToCharOffset( $boff )
@@ -842,7 +876,7 @@ Throws
#
- charToByteOffset( $char )
+ charToByteOffset( $char )
@@ -871,7 +905,7 @@ Throws
#
- byteToCharOffsetString( $string, $boff )
+ byteToCharOffsetString( $string, $boff )
@@ -900,7 +934,7 @@ Throws
#
- utf8CharLen( $byte )
+ utf8CharLen( $byte )
@@ -929,7 +963,7 @@ Throws
#
- count( )
+ count( )
Return string length (number of UTF-8 chars, not strlen())
diff --git a/doc/class-apemsel.AttributedString.MutableAttributedString.html b/doc/class-apemsel.AttributedString.MutableAttributedString.html
index afdc575..3e8396c 100644
--- a/doc/class-apemsel.AttributedString.MutableAttributedString.html
+++ b/doc/class-apemsel.AttributedString.MutableAttributedString.html
@@ -261,6 +261,7 @@ See
__construct() ,
__toString() ,
+ attributeToString() ,
attributesAt() ,
byteToCharOffset() ,
byteToCharOffsetString() ,
diff --git a/doc/class-apemsel.AttributedString.TokenizedAttributedString.html b/doc/class-apemsel.AttributedString.TokenizedAttributedString.html
index 88e808f..808e60d 100644
--- a/doc/class-apemsel.AttributedString.TokenizedAttributedString.html
+++ b/doc/class-apemsel.AttributedString.TokenizedAttributedString.html
@@ -653,6 +653,7 @@ Returns
__toString() ,
+ attributeToString() ,
attributesAt() ,
byteToCharOffset() ,
byteToCharOffsetString() ,
diff --git a/doc/source-class-apemsel.AttributedString.AttributedString.html b/doc/source-class-apemsel.AttributedString.AttributedString.html
index a4a80f3..601a2c0 100644
--- a/doc/source-class-apemsel.AttributedString.AttributedString.html
+++ b/doc/source-class-apemsel.AttributedString.AttributedString.html
@@ -352,175 +352,201 @@ Classes
268 269 270 271 272
-273 public function toHtml($tag = "span", $classPrefix = "") {
-274 foreach($this->attributes as $attribute => $map) $state[$attribute] = false;
-275
-276 $html = "";
-277 $stack = [];
-278 $lastPos = 0;
-279
-280 for ($i=0; $i<$this->length; $i++)
-281 {
-282 foreach($this->attributes as $attribute => &$map)
-283 {
-284 if ($this->attributes[$attribute][$i] != $state[$attribute])
-285 {
-286 $state[$attribute] = $this->attributes[$attribute][$i];
-287
-288 $html .= mb_substr($this->string, $lastPos, $i-$lastPos, "utf-8");
-289 $lastPos = $i;
-290
-291 if ($state[$attribute])
-292 {
-293 $html .= "<$tag class=\"$classPrefix$attribute\">";
-294 $stack[] = $attribute;
-295 }
-296 else
-297 {
-298 if ($attribute != array_pop($stack))
-299 {
-300 throw new Exception("Attributes are not properly nested for HTML conversion");
-301 }
-302 $html .= "</$tag>";
-303 }
-304 }
-305 }
-306 }
-307
-308 $html .= mb_substr($this->string, $lastPos, $this->length-$lastPos, 'utf-8');
-309
-310
-311 $html .= str_repeat("</$tag>", count($stack));
-312
-313 return $html;
-314 }
-315
-316 317 318 319 320 321 322 323 324
-325 public function combineAttributes($op, $attribute1, $attribute2 = false, $to = false)
-326 {
-327 $to = isset($to) ? $to : $attribute1;
-328 $op = strtolower($op);
-329
-330 if ($op == "not") {
-331 $attribute2 = $attribute1;
-332 }
-333
-334 if (!$this->hasAttribute($attribute1) or !$this->hasAttribute($attribute2)) {
-335 throw new \InvalidArgumentException("Attribute does not exist");
-336 }
-337
-338 if (!isset($this->attributes[$to])) {
-339 $this->attributes[$to] = [];
-340 }
-341
-342
-343 switch ($op) {
-344 case 'or':
-345 for($i = 0; $i < $this->length; $i++) {
-346 $this->attributes[$to][$i] = $this->attributes[$attribute1][$i] || $this->attributes[$attribute2][$i];
-347 }
-348 break;
-349
-350 case 'xor':
-351 for($i = 0; $i < $this->length; $i++) {
-352 $this->attributes[$to][$i] = ($this->attributes[$attribute1][$i] xor $this->attributes[$attribute2][$i]);
-353 }
-354 break;
-355
-356 case 'and':
-357 for($i = 0; $i < $this->length; $i++) {
-358 $this->attributes[$to][$i] = $this->attributes[$attribute1][$i] && $this->attributes[$attribute2][$i];
-359 }
-360 break;
-361
-362 case 'not':
-363 for($i = 0; $i < $this->length; $i++) {
-364 $this->attributes[$to][$i] = !$this->attributes[$attribute1][$i];
-365 }
-366 break;
-367
-368 default:
-369 throw new \InvalidArgumentException("Unknown operation");
-370 }
-371 }
-372
-373 374 375 376 377
-378 public function enablebyteToCharCache() {
-379 $this->byteToChar = [];
-380 $char = 0;
-381 for ($i = 0; $i < strlen($this->string); ) {
-382 $char++;
-383 $byte = $this->string[$i];
-384 $cl = self::utf8CharLen($byte);
-385 $i += $cl;
-386
-387 $this->byteToChar[$i] = $char;
-388 }
-389 }
-390
-391 protected function byteToCharOffset($boff) {
-392 if (isset($this->byteToChar[$boff])) return $this->byteToChar[$boff];
+271
+272 public function toHtml($tag = "span", $classPrefix = "") {
+273 foreach($this->attributes as $attribute => $map) $state[$attribute] = false;
+274
+275 $html = "";
+276 $stack = [];
+277 $lastPos = 0;
+278
+279 for ($i=0; $i<$this->length; $i++)
+280 {
+281 foreach($this->attributes as $attribute => &$map)
+282 {
+283 if ($this->attributes[$attribute][$i] != $state[$attribute])
+284 {
+285 $state[$attribute] = $this->attributes[$attribute][$i];
+286
+287 $html .= mb_substr($this->string, $lastPos, $i-$lastPos, "utf-8");
+288 $lastPos = $i;
+289
+290 if ($state[$attribute])
+291 {
+292 $html .= "<$tag class=\"$classPrefix$attribute\">";
+293 $stack[] = $attribute;
+294 }
+295 else
+296 {
+297
+298
+299 $stashed = [];
+300 while($open = array_pop($stack))
+301 {
+302 $html .= "</$tag>";
+303 if ($attribute == $open) {
+304 break;
+305 }
+306 $stashed[] = $open;
+307 }
+308
+309
+310 foreach($stashed as $a) {
+311 $stack[] = $a;
+312 $html .= "<$tag class=\"$classPrefix$a\">";
+313 }
+314 }
+315 }
+316 }
+317 }
+318
+319 $html .= mb_substr($this->string, $lastPos, $this->length-$lastPos, 'utf-8');
+320
+321
+322 $html .= str_repeat("</$tag>", count($stack));
+323
+324 return $html;
+325 }
+326
+327 328 329 330 331 332 333 334 335
+336 public function combineAttributes($op, $attribute1, $attribute2 = false, $to = false)
+337 {
+338 $to = isset($to) ? $to : $attribute1;
+339 $op = strtolower($op);
+340
+341 if ($op == "not") {
+342 $attribute2 = $attribute1;
+343 }
+344
+345 if (!$this->hasAttribute($attribute1) or !$this->hasAttribute($attribute2)) {
+346 throw new \InvalidArgumentException("Attribute does not exist");
+347 }
+348
+349 if (!isset($this->attributes[$to])) {
+350 $this->attributes[$to] = [];
+351 }
+352
+353
+354 switch ($op) {
+355 case 'or':
+356 for($i = 0; $i < $this->length; $i++) {
+357 $this->attributes[$to][$i] = $this->attributes[$attribute1][$i] || $this->attributes[$attribute2][$i];
+358 }
+359 break;
+360
+361 case 'xor':
+362 for($i = 0; $i < $this->length; $i++) {
+363 $this->attributes[$to][$i] = ($this->attributes[$attribute1][$i] xor $this->attributes[$attribute2][$i]);
+364 }
+365 break;
+366
+367 case 'and':
+368 for($i = 0; $i < $this->length; $i++) {
+369 $this->attributes[$to][$i] = $this->attributes[$attribute1][$i] && $this->attributes[$attribute2][$i];
+370 }
+371 break;
+372
+373 case 'not':
+374 for($i = 0; $i < $this->length; $i++) {
+375 $this->attributes[$to][$i] = !$this->attributes[$attribute1][$i];
+376 }
+377 break;
+378
+379 default:
+380 throw new \InvalidArgumentException("Unknown operation");
+381 }
+382 }
+383
+384 385 386 387 388 389 390
+391 public function attributeToString($attribute, $true = "-", $false = " ") {
+392 $map = $this->attributes[$attribute];
393
-394 return $this->byteToChar[$boff] = self::byteToCharOffsetString($this->string, $boff);
-395 }
-396
-397 protected function charToByteOffset($char) {
-398 $byte = strlen(mb_substr($this->string, 0, $char, "utf-8"));
-399 if (!isset($this->byteToChar[$byte])) $this->byteToChar[$byte] = $char;
-400
-401 return $byte;
-402 }
-403
-404 protected static function byteToCharOffsetString($string, $boff) {
-405 $result = 0;
-406
-407 for ($i = 0; $i < $boff; ) {
-408 $result++;
-409 $byte = $string[$i];
+394 return implode("", array_map(function($v) use ($true, $false) {
+395 return $v ? $true : $false;
+396 }, $map));
+397 }
+398
+399 400 401 402 403
+404 public function enablebyteToCharCache() {
+405 $this->byteToChar = [];
+406 $char = 0;
+407 for ($i = 0; $i < strlen($this->string); ) {
+408 $char++;
+409 $byte = $this->string[$i];
410 $cl = self::utf8CharLen($byte);
411 $i += $cl;
-412 }
-413
-414 return $result;
+412
+413 $this->byteToChar[$i] = $char;
+414 }
415 }
416
-417 protected static function utf8CharLen($byte) {
-418 $base2 = str_pad(base_convert((string) ord($byte), 10, 2), 8, "0", STR_PAD_LEFT);
-419 $p = strpos($base2, "0");
-420
-421 if ($p == 0) {
-422 return 1;
-423 } elseif ($p <= 4) {
-424 return $p;
-425 } else {
-426 throw new \InvalidArgumentException();
-427 }
+417 protected function byteToCharOffset($boff) {
+418 if (isset($this->byteToChar[$boff])) return $this->byteToChar[$boff];
+419
+420 return $this->byteToChar[$boff] = self::byteToCharOffsetString($this->string, $boff);
+421 }
+422
+423 protected function charToByteOffset($char) {
+424 $byte = strlen(mb_substr($this->string, 0, $char, "utf-8"));
+425 if (!isset($this->byteToChar[$byte])) $this->byteToChar[$byte] = $char;
+426
+427 return $byte;
428 }
429
-430 431 432 433 434
-435 public function count() {
-436 return $this->length;
-437 }
-438 }
-439
+ 430 protected static function byteToCharOffsetString($string, $boff) {
+431 $result = 0;
+432
+433 for ($i = 0; $i < $boff; ) {
+434 $result++;
+435 $byte = $string[$i];
+436 $cl = self::utf8CharLen($byte);
+437 $i += $cl;
+438 }
+439
+440 return $result;
+441 }
+442
+443 protected static function utf8CharLen($byte) {
+444 $base2 = str_pad(base_convert((string) ord($byte), 10, 2), 8, "0", STR_PAD_LEFT);
+445 $p = strpos($base2, "0");
+446
+447 if ($p == 0) {
+448 return 1;
+449 } elseif ($p <= 4) {
+450 return $p;
+451 } else {
+452 throw new \InvalidArgumentException();
+453 }
+454 }
+455
+456 457 458 459 460
+461 public function count() {
+462 return $this->length;
+463 }
+464 }
+465
| | | | | | |