001package org.apache.maven.doxia.module.twiki; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.PrintWriter; 023import java.io.StringWriter; 024import java.io.Writer; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Stack; 028 029import javax.swing.text.MutableAttributeSet; 030import javax.swing.text.html.HTML.Attribute; 031import javax.swing.text.html.HTML.Tag; 032 033import org.apache.maven.doxia.sink.SinkEventAttributes; 034import org.apache.maven.doxia.sink.impl.AbstractTextSink; 035import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; 036import org.apache.maven.doxia.sink.impl.SinkUtils; 037import org.apache.maven.doxia.util.HtmlTools; 038import org.codehaus.plexus.util.StringUtils; 039 040/** 041 * TWiki Sink implementation. 042 * <br> 043 * <b>Note</b>: The encoding used is UTF-8. 044 * 045 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a> 046 * @since 1.0 047 */ 048public class TWikiSink 049 extends AbstractTextSink 050 implements TWikiMarkup 051{ 052 /** The writer to use. */ 053 private final PrintWriter out; 054 055 /** The writer to use. */ 056 private StringWriter writer; 057 058 /** An indication on if we're in bold mode. */ 059 private boolean boldFlag; 060 061 /** An indication on if we're in head mode. */ 062 private boolean headFlag; 063 064 private int levelList = 0; 065 066 /** listStyles. */ 067 private final Stack<String> listStyles; 068 069 /** Keep track of the nested bold flag. */ 070 protected Stack<Boolean> boldStack = new Stack<>(); 071 072 /** Keep track of the closing tags for inline events. */ 073 protected Stack<List<String>> inlineStack = new Stack<>(); 074 075 /** 076 * Constructor, initialize the Writer and the variables. 077 * 078 * @param writer not null writer to write the result. <b>Should</b> be an UTF-8 Writer. 079 * You could use <code>newWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}. 080 */ 081 protected TWikiSink( Writer writer ) 082 { 083 this.out = new PrintWriter( writer ); 084 this.listStyles = new Stack<>(); 085 086 init(); 087 } 088 089 /** {@inheritDoc} */ 090 public void anchor( String name ) 091 { 092 write( EOL ); 093 write( ANCHOR_MARKUP + name ); 094 } 095 096 /** {@inheritDoc} */ 097 public void anchor( String name, SinkEventAttributes attributes ) 098 { 099 anchor( name ); 100 } 101 102 /** 103 * Not used. 104 * {@inheritDoc} 105 */ 106 public void anchor_() 107 { 108 // nop 109 } 110 111 /** 112 * Not used. 113 * {@inheritDoc} 114 */ 115 public void author() 116 { 117 // nop 118 } 119 120 /** {@inheritDoc} */ 121 public void author( SinkEventAttributes attributes ) 122 { 123 author(); 124 } 125 126 /** 127 * Not used. 128 * {@inheritDoc} 129 */ 130 public void author_() 131 { 132 // nop 133 } 134 135 /** 136 * Not used. 137 * {@inheritDoc} 138 */ 139 public void body() 140 { 141 // nop 142 } 143 144 /** {@inheritDoc} */ 145 public void body( SinkEventAttributes attributes ) 146 { 147 body(); 148 } 149 150 /** 151 * Not used. 152 * {@inheritDoc} 153 */ 154 public void body_() 155 { 156 // nop 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 public void bold() 163 { 164 inline( SinkEventAttributeSet.Semantics.BOLD ); 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 public void bold_() 171 { 172 inline_(); 173 } 174 175 /** 176 * Not used. 177 * {@inheritDoc} 178 */ 179 public void comment( String comment ) 180 { 181 // nop 182 } 183 184 /** 185 * {@inheritDoc} 186 */ 187 public void close() 188 { 189 out.write( writer.toString() ); 190 out.close(); 191 192 init(); 193 } 194 195 /** 196 * Not used. 197 * {@inheritDoc} 198 */ 199 public void date() 200 { 201 // nop 202 } 203 204 /** {@inheritDoc} */ 205 public void date( SinkEventAttributes attributes ) 206 { 207 date(); 208 } 209 210 /** 211 * Not used. 212 * {@inheritDoc} 213 */ 214 public void date_() 215 { 216 // nop 217 } 218 219 /** 220 * Not used. 221 * {@inheritDoc} 222 */ 223 public void definedTerm() 224 { 225 // nop 226 } 227 228 /** {@inheritDoc} */ 229 public void definedTerm( SinkEventAttributes attributes ) 230 { 231 definedTerm(); 232 } 233 234 /** 235 * Not used. 236 * {@inheritDoc} 237 */ 238 public void definedTerm_() 239 { 240 // nop 241 } 242 243 /** 244 * {@inheritDoc} 245 */ 246 public void definition() 247 { 248 write( DEFINITION_LIST_DEFINITION_MARKUP ); 249 } 250 251 /** {@inheritDoc} */ 252 public void definition( SinkEventAttributes attributes ) 253 { 254 definition(); 255 } 256 257 /** 258 * {@inheritDoc} 259 */ 260 public void definition_() 261 { 262 writeEOL(); 263 } 264 265 /** 266 * Not used. 267 * {@inheritDoc} 268 */ 269 public void definitionList() 270 { 271 // nop 272 } 273 274 /** {@inheritDoc} */ 275 public void definitionList( SinkEventAttributes attributes ) 276 { 277 definitionList(); 278 } 279 280 /** 281 * Not used. 282 * {@inheritDoc} 283 */ 284 public void definitionList_() 285 { 286 // nop 287 } 288 289 /** 290 * {@inheritDoc} 291 */ 292 public void definitionListItem() 293 { 294 write( DEFINITION_LIST_ITEM_MARKUP ); 295 } 296 297 /** {@inheritDoc} */ 298 public void definitionListItem( SinkEventAttributes attributes ) 299 { 300 definitionListItem(); 301 } 302 303 /** 304 * Not used. 305 * {@inheritDoc} 306 */ 307 public void definitionListItem_() 308 { 309 // nop 310 } 311 312 /** 313 * {@inheritDoc} 314 */ 315 public void figure() 316 { 317 write( LESS_THAN + Tag.IMG.toString() + SPACE ); 318 } 319 320 /** {@inheritDoc} */ 321 public void figure( SinkEventAttributes attributes ) 322 { 323 figure(); 324 } 325 326 /** 327 * Not used. 328 * {@inheritDoc} 329 */ 330 public void figure_() 331 { 332 write( SLASH + String.valueOf( GREATER_THAN ) ); 333 } 334 335 /** 336 * Not used. 337 * {@inheritDoc} 338 */ 339 public void figureCaption() 340 { 341 write( Attribute.ALT.toString() + EQUAL + QUOTE ); 342 } 343 344 /** {@inheritDoc} */ 345 public void figureCaption( SinkEventAttributes attributes ) 346 { 347 figureCaption(); 348 } 349 350 /** 351 * Not used. 352 * {@inheritDoc} 353 */ 354 public void figureCaption_() 355 { 356 write( QUOTE + String.valueOf( SPACE ) ); 357 } 358 359 /** {@inheritDoc} */ 360 public void figureGraphics( String name ) 361 { 362 write( Attribute.SRC.toString() + EQUAL + QUOTE + name + QUOTE + SPACE ); 363 } 364 365 /** {@inheritDoc} */ 366 public void figureGraphics( String src, SinkEventAttributes attributes ) 367 { 368 figureGraphics( src ); 369 } 370 371 /** 372 * {@inheritDoc} 373 */ 374 public void flush() 375 { 376 close(); 377 writer.flush(); 378 } 379 380 /** 381 * {@inheritDoc} 382 */ 383 public void head() 384 { 385 init(); 386 387 headFlag = true; 388 } 389 390 /** {@inheritDoc} */ 391 public void head( SinkEventAttributes attributes ) 392 { 393 head(); 394 } 395 396 /** 397 * {@inheritDoc} 398 */ 399 public void head_() 400 { 401 headFlag = false; 402 } 403 404 /** 405 * {@inheritDoc} 406 */ 407 public void horizontalRule() 408 { 409 writeEOL( true ); 410 write( HORIZONTAL_RULE_MARKUP ); 411 writeEOL( true ); 412 } 413 414 /** {@inheritDoc} */ 415 public void horizontalRule( SinkEventAttributes attributes ) 416 { 417 horizontalRule(); 418 } 419 420 /** 421 * {@inheritDoc} 422 */ 423 public void inline() 424 { 425 inline( null ); 426 } 427 428 /** {@inheritDoc} */ 429 public void inline( SinkEventAttributes attributes ) 430 { 431 List<String> tags = new ArrayList<>(); 432 433 boldStack.push( boldFlag ); 434 435 if ( attributes != null ) 436 { 437 438 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "bold" ) ) 439 { 440 boldFlag = true; 441 write( BOLD_START_MARKUP ); 442 tags.add( 0, BOLD_END_MARKUP ); 443 } 444 445 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "italic" ) ) 446 { 447 if ( boldFlag ) 448 { 449 String tmp = writer.toString(); 450 writer = new StringWriter(); 451 writer.write( tmp.substring( 0, tmp.length() - 1 ) ); 452 write( BOLD_ITALIC_START_MARKUP ); 453 tags.add( 0, BOLD_ITALIC_END_MARKUP ); 454 } 455 else 456 { 457 write( ITALIC_START_MARKUP ); 458 tags.add( ITALIC_END_MARKUP ); 459 } 460 } 461 462 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "code" ) ) 463 { 464 if ( boldFlag ) 465 { 466 String tmp = writer.toString(); 467 writer = new StringWriter(); 468 writer.write( tmp.substring( 0, tmp.length() - 1 ) ); 469 write( BOLD_MONOSPACED_START_MARKUP ); 470 tags.add( 0, BOLD_MONOSPACED_END_MARKUP ); 471 } 472 else 473 { 474 write( MONOSPACED_START_MARKUP ); 475 tags.add( 0, MONOSPACED_END_MARKUP ); 476 } 477 } 478 479 } 480 481 inlineStack.push( tags ); 482 } 483 484 /** 485 * {@inheritDoc} 486 */ 487 public void inline_() 488 { 489 for ( String tag: inlineStack.pop() ) 490 { 491 write( tag ); 492 } 493 this.boldFlag = boldStack.pop(); 494 } 495 496 /** 497 * {@inheritDoc} 498 */ 499 public void italic() 500 { 501 inline( SinkEventAttributeSet.Semantics.ITALIC ); 502 } 503 504 /** 505 * {@inheritDoc} 506 */ 507 public void italic_() 508 { 509 inline_(); 510 } 511 512 /** 513 * Not used. 514 * {@inheritDoc} 515 */ 516 public void lineBreak() 517 { 518 // nop 519 } 520 521 /** {@inheritDoc} */ 522 public void lineBreak( SinkEventAttributes attributes ) 523 { 524 lineBreak(); 525 } 526 527 /** {@inheritDoc} */ 528 public void link( String name ) 529 { 530 write( LINK_START_MARKUP + name + LINK_MIDDLE_MARKUP ); 531 } 532 533 /** {@inheritDoc} */ 534 public void link( String name, SinkEventAttributes attributes ) 535 { 536 link( name ); 537 } 538 539 /** 540 * {@inheritDoc} 541 */ 542 public void link_() 543 { 544 write( LINK_END_MARKUP ); 545 } 546 547 /** 548 * {@inheritDoc} 549 */ 550 public void list() 551 { 552 if ( !writer.toString().endsWith( EOL + EOL ) ) 553 { 554 writeEOL( true ); 555 } 556 557 levelList++; 558 } 559 560 /** {@inheritDoc} */ 561 public void list( SinkEventAttributes attributes ) 562 { 563 list(); 564 } 565 566 /** 567 * {@inheritDoc} 568 */ 569 public void list_() 570 { 571 levelList--; 572 } 573 574 /** 575 * {@inheritDoc} 576 */ 577 public void listItem() 578 { 579 String indent = StringUtils.repeat( THREE_SPACES_MARKUP, levelList ); 580 write( indent + LIST_ITEM_MARKUP ); 581 } 582 583 /** {@inheritDoc} */ 584 public void listItem( SinkEventAttributes attributes ) 585 { 586 listItem(); 587 } 588 589 /** 590 * {@inheritDoc} 591 */ 592 public void listItem_() 593 { 594 writeEOL( true ); 595 } 596 597 /** 598 * {@inheritDoc} 599 */ 600 public void monospaced() 601 { 602 inline( SinkEventAttributeSet.Semantics.CODE ); 603 } 604 605 /** 606 * {@inheritDoc} 607 */ 608 public void monospaced_() 609 { 610 inline_(); 611 } 612 613 /** 614 * Not used. 615 * {@inheritDoc} 616 */ 617 public void nonBreakingSpace() 618 { 619 // nop 620 } 621 622 /** {@inheritDoc} */ 623 public void numberedList( int numbering ) 624 { 625 levelList++; 626 627 String style; 628 switch ( numbering ) 629 { 630 case NUMBERING_UPPER_ALPHA: 631 style = NUMBERING_UPPER_ALPHA_MARKUP; 632 break; 633 case NUMBERING_LOWER_ALPHA: 634 style = NUMBERING_LOWER_ALPHA_MARKUP; 635 break; 636 case NUMBERING_UPPER_ROMAN: 637 style = NUMBERING_UPPER_ROMAN_MARKUP; 638 break; 639 case NUMBERING_LOWER_ROMAN: 640 style = NUMBERING_LOWER_ROMAN_MARKUP; 641 break; 642 case NUMBERING_DECIMAL: 643 default: 644 style = NUMBERING_MARKUP; 645 } 646 647 listStyles.push( style ); 648 } 649 650 /** {@inheritDoc} */ 651 public void numberedList( int numbering, SinkEventAttributes attributes ) 652 { 653 numberedList( numbering ); 654 } 655 656 /** 657 * {@inheritDoc} 658 */ 659 public void numberedList_() 660 { 661 levelList--; 662 listStyles.pop(); 663 } 664 665 /** 666 * {@inheritDoc} 667 */ 668 public void numberedListItem() 669 { 670 writeEOL( true ); 671 String style = listStyles.peek(); 672 String indent = StringUtils.repeat( THREE_SPACES_MARKUP, levelList ); 673 write( indent + style + SPACE ); 674 } 675 676 /** {@inheritDoc} */ 677 public void numberedListItem( SinkEventAttributes attributes ) 678 { 679 numberedListItem(); 680 } 681 682 /** 683 * {@inheritDoc} 684 */ 685 public void numberedListItem_() 686 { 687 writeEOL( true ); 688 } 689 690 /** 691 * Not used. 692 * {@inheritDoc} 693 */ 694 public void pageBreak() 695 { 696 // nop 697 } 698 699 /** 700 * Not used. 701 * {@inheritDoc} 702 */ 703 public void paragraph() 704 { 705 // nop 706 } 707 708 /** {@inheritDoc} */ 709 public void paragraph( SinkEventAttributes attributes ) 710 { 711 paragraph(); 712 } 713 714 /** 715 * {@inheritDoc} 716 */ 717 public void paragraph_() 718 { 719 writeEOL( true ); 720 writeEOL(); 721 } 722 723 /** 724 * Not used. 725 * {@inheritDoc} 726 */ 727 public void rawText( String text ) 728 { 729 // nop 730 } 731 732 /** 733 * Not used. 734 * {@inheritDoc} 735 */ 736 public void section( int level, SinkEventAttributes attributes ) 737 { 738 // nop 739 } 740 741 /** 742 * Not used. 743 * {@inheritDoc} 744 */ 745 public void section1() 746 { 747 // nop 748 } 749 750 /** 751 * Not used. 752 * {@inheritDoc} 753 */ 754 public void section1_() 755 { 756 // nop 757 } 758 759 /** 760 * Not used. 761 * {@inheritDoc} 762 */ 763 public void section2() 764 { 765 // nop 766 } 767 768 /** 769 * Not used. 770 * {@inheritDoc} 771 */ 772 public void section2_() 773 { 774 // nop 775 } 776 777 /** 778 * Not used. 779 * {@inheritDoc} 780 */ 781 public void section3() 782 { 783 // nop 784 } 785 786 /** 787 * Not used. 788 * {@inheritDoc} 789 */ 790 public void section3_() 791 { 792 // nop 793 } 794 795 /** 796 * Not used. 797 * {@inheritDoc} 798 */ 799 public void section4() 800 { 801 // nop 802 } 803 804 /** 805 * Not used. 806 * {@inheritDoc} 807 */ 808 public void section4_() 809 { 810 // nop 811 } 812 813 /** 814 * Not used. 815 * {@inheritDoc} 816 */ 817 public void section5() 818 { 819 // nop 820 } 821 822 /** 823 * Not used. 824 * {@inheritDoc} 825 */ 826 public void section5_() 827 { 828 // nop 829 } 830 831 /** 832 * Not used. 833 * {@inheritDoc} 834 */ 835 public void section_( int level ) 836 { 837 // nop 838 } 839 840 /** 841 * Not used. 842 * {@inheritDoc} 843 */ 844 public void sectionTitle() 845 { 846 // nop 847 } 848 849 /** {@inheritDoc} */ 850 public void sectionTitle( int level, SinkEventAttributes attributes ) 851 { 852 if ( level > 0 && level < 6 ) 853 { 854 write( StringUtils.repeat( "-", 3 ) + StringUtils.repeat( "+", level ) ); 855 } 856 } 857 858 /** 859 * {@inheritDoc} 860 */ 861 public void sectionTitle1() 862 { 863 sectionTitle( 1, null ); 864 } 865 866 /** 867 * {@inheritDoc} 868 */ 869 public void sectionTitle1_() 870 { 871 sectionTitle_( 1 ); 872 } 873 874 /** 875 * {@inheritDoc} 876 */ 877 public void sectionTitle2() 878 { 879 sectionTitle( 2, null ); 880 } 881 882 /** 883 * {@inheritDoc} 884 */ 885 public void sectionTitle2_() 886 { 887 sectionTitle_( 2 ); 888 } 889 890 /** 891 * {@inheritDoc} 892 */ 893 public void sectionTitle3() 894 { 895 sectionTitle( 3, null ); 896 } 897 898 /** 899 * {@inheritDoc} 900 */ 901 public void sectionTitle3_() 902 { 903 sectionTitle_( 3 ); 904 } 905 906 /** 907 * {@inheritDoc} 908 */ 909 public void sectionTitle4() 910 { 911 sectionTitle( 4, null ); 912 } 913 914 /** 915 * {@inheritDoc} 916 */ 917 public void sectionTitle4_() 918 { 919 sectionTitle_( 4 ); 920 } 921 922 /** 923 * {@inheritDoc} 924 */ 925 public void sectionTitle5() 926 { 927 sectionTitle( 5, null ); 928 } 929 930 /** 931 * {@inheritDoc} 932 */ 933 public void sectionTitle5_() 934 { 935 sectionTitle_( 5 ); 936 } 937 938 /** 939 * Not used. 940 * {@inheritDoc} 941 */ 942 public void sectionTitle_() 943 { 944 // nop 945 } 946 947 /** {@inheritDoc} */ 948 public void sectionTitle_( int level ) 949 { 950 writeEOL( true ); 951 writeEOL(); 952 } 953 954 /** 955 * Not used. 956 * {@inheritDoc} 957 */ 958 public void table() 959 { 960 // nop 961 } 962 963 /** {@inheritDoc} */ 964 public void table( SinkEventAttributes attributes ) 965 { 966 table(); 967 } 968 969 /** 970 * Not used. 971 * {@inheritDoc} 972 */ 973 public void table_() 974 { 975 // nop 976 } 977 978 /** 979 * Not used. 980 * {@inheritDoc} 981 */ 982 public void tableCaption() 983 { 984 // nop 985 } 986 987 /** {@inheritDoc} */ 988 public void tableCaption( SinkEventAttributes attributes ) 989 { 990 tableCaption(); 991 } 992 993 /** 994 * Not used. 995 * {@inheritDoc} 996 */ 997 public void tableCaption_() 998 { 999 // nop 1000 } 1001 1002 /** 1003 * {@inheritDoc} 1004 */ 1005 public void tableCell() 1006 { 1007 write( " " ); 1008 } 1009 1010 /** {@inheritDoc} */ 1011 public void tableCell( SinkEventAttributes attributes ) 1012 { 1013 tableCell(); 1014 } 1015 1016 /** {@inheritDoc} */ 1017 public void tableCell( String width ) 1018 { 1019 tableCell(); 1020 } 1021 1022 /** 1023 * {@inheritDoc} 1024 */ 1025 public void tableCell_() 1026 { 1027 write( TABLE_CELL_MARKUP ); 1028 } 1029 1030 /** 1031 * {@inheritDoc} 1032 */ 1033 public void tableHeaderCell() 1034 { 1035 write( TABLE_CELL_HEADER_START_MARKUP ); 1036 } 1037 1038 /** {@inheritDoc} */ 1039 public void tableHeaderCell( SinkEventAttributes attributes ) 1040 { 1041 tableHeaderCell(); 1042 } 1043 1044 /** {@inheritDoc} */ 1045 public void tableHeaderCell( String width ) 1046 { 1047 tableHeaderCell(); 1048 } 1049 1050 /** 1051 * {@inheritDoc} 1052 */ 1053 public void tableHeaderCell_() 1054 { 1055 write( TABLE_CELL_HEADER_END_MARKUP ); 1056 } 1057 1058 /** 1059 * {@inheritDoc} 1060 */ 1061 public void tableRow() 1062 { 1063 write( TABLE_ROW_MARKUP ); 1064 } 1065 1066 /** {@inheritDoc} */ 1067 public void tableRow( SinkEventAttributes attributes ) 1068 { 1069 tableRow(); 1070 } 1071 1072 /** 1073 * {@inheritDoc} 1074 */ 1075 public void tableRow_() 1076 { 1077 writeEOL( true ); 1078 } 1079 1080 /** 1081 * Not used. 1082 * {@inheritDoc} 1083 */ 1084 public void tableRows( int[] justification, boolean grid ) 1085 { 1086 // nop 1087 } 1088 1089 /** 1090 * Not used. 1091 * {@inheritDoc} 1092 */ 1093 public void tableRows_() 1094 { 1095 // nop 1096 } 1097 1098 /** {@inheritDoc} */ 1099 public void text( String text ) 1100 { 1101 if ( headFlag ) 1102 { 1103 return; 1104 } 1105 1106 content( text ); 1107 } 1108 1109 /** {@inheritDoc} */ 1110 public void text( String text, SinkEventAttributes attributes ) 1111 { 1112 if ( attributes == null ) 1113 { 1114 text( text ); 1115 } 1116 else 1117 { 1118 if ( attributes.containsAttribute( SinkEventAttributes.DECORATION, "underline" ) ) 1119 { 1120 writeStartTag( Tag.U ); 1121 } 1122 if ( attributes.containsAttribute( SinkEventAttributes.DECORATION, "line-through" ) ) 1123 { 1124 writeStartTag( Tag.S ); 1125 } 1126 if ( attributes.containsAttribute( SinkEventAttributes.VALIGN, "sub" ) ) 1127 { 1128 writeStartTag( Tag.SUB ); 1129 } 1130 if ( attributes.containsAttribute( SinkEventAttributes.VALIGN, "sup" ) ) 1131 { 1132 writeStartTag( Tag.SUP ); 1133 } 1134 1135 text( text ); 1136 1137 if ( attributes.containsAttribute( SinkEventAttributes.VALIGN, "sup" ) ) 1138 { 1139 writeEndTag( Tag.SUP ); 1140 } 1141 if ( attributes.containsAttribute( SinkEventAttributes.VALIGN, "sub" ) ) 1142 { 1143 writeEndTag( Tag.SUB ); 1144 } 1145 if ( attributes.containsAttribute( SinkEventAttributes.DECORATION, "line-through" ) ) 1146 { 1147 writeEndTag( Tag.S ); 1148 } 1149 if ( attributes.containsAttribute( SinkEventAttributes.DECORATION, "underline" ) ) 1150 { 1151 writeEndTag( Tag.U ); 1152 } 1153 } 1154 } 1155 1156 /** 1157 * Not used. 1158 * {@inheritDoc} 1159 */ 1160 public void title() 1161 { 1162 // nop 1163 } 1164 1165 /** {@inheritDoc} */ 1166 public void title( SinkEventAttributes attributes ) 1167 { 1168 title(); 1169 } 1170 1171 /** 1172 * Not used. 1173 * {@inheritDoc} 1174 */ 1175 public void title_() 1176 { 1177 // nop 1178 } 1179 1180 /** 1181 * Not used. 1182 * {@inheritDoc} 1183 */ 1184 public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) 1185 { 1186 // nop 1187 } 1188 1189 /** {@inheritDoc} */ 1190 public void verbatim( boolean boxed ) 1191 { 1192 SinkEventAttributeSet att = new SinkEventAttributeSet(); 1193 1194 if ( boxed ) 1195 { 1196 att.addAttribute( SinkEventAttributes.DECORATION, "boxed" ); 1197 } 1198 1199 verbatim( att ); 1200 } 1201 1202 /** 1203 * {@inheritDoc} 1204 * 1205 * @param attributes a {@link org.apache.maven.doxia.sink.SinkEventAttributes} object. 1206 */ 1207 public void verbatim( SinkEventAttributes attributes ) 1208 { 1209 MutableAttributeSet atts = SinkUtils.filterAttributes( attributes, SinkUtils.SINK_VERBATIM_ATTRIBUTES ); 1210 1211 if ( atts == null ) 1212 { 1213 atts = new SinkEventAttributeSet(); 1214 } 1215 1216 boolean boxed = false; 1217 1218 if ( atts.isDefined( SinkEventAttributes.DECORATION ) ) 1219 { 1220 boxed = "boxed".equals( atts.getAttribute( SinkEventAttributes.DECORATION ).toString() ); 1221 } 1222 1223 if ( boxed ) 1224 { 1225 atts.addAttribute( Attribute.CLASS, "source" ); 1226 } 1227 1228 atts.removeAttribute( SinkEventAttributes.DECORATION ); 1229 1230 String width = (String) atts.getAttribute( Attribute.WIDTH.toString() ); 1231 atts.removeAttribute( Attribute.WIDTH.toString() ); 1232 1233 writeStartTag( Tag.DIV, atts ); 1234 writeEOL( true ); 1235 1236 if ( width != null ) 1237 { 1238 atts.addAttribute( Attribute.WIDTH.toString(), width ); 1239 } 1240 1241 atts.removeAttribute( Attribute.ALIGN.toString() ); 1242 atts.removeAttribute( Attribute.CLASS.toString() ); 1243 1244 writeStartTag( VERBATIM_TAG, atts ); 1245 } 1246 1247 /** 1248 * {@inheritDoc} 1249 */ 1250 public void verbatim_() 1251 { 1252 writeEndTag( VERBATIM_TAG ); 1253 writeEOL( true ); 1254 writeEndTag( Tag.DIV ); 1255 writeEOL( true ); 1256 } 1257 1258 // ---------------------------------------------------------------------- 1259 // Private methods 1260 // ---------------------------------------------------------------------- 1261 1262 private void write( String text ) 1263 { 1264 writer.write( unifyEOLs( text ) ); 1265 } 1266 1267 /** 1268 * Starts a Tag. For instance: 1269 * <pre> 1270 * <tag> 1271 * </pre> 1272 * <br> 1273 * 1274 * @param t a non null tag 1275 * @see #writeStartTag(javax.swing.text.html.HTML.Tag) 1276 */ 1277 private void writeStartTag( Tag t ) 1278 { 1279 writeStartTag( t, null ); 1280 } 1281 1282 /** 1283 * Starts a Tag with attributes. For instance: 1284 * <pre> 1285 * <tag attName="attValue"> 1286 * </pre> 1287 * <br> 1288 * 1289 * @param t a non null tag 1290 * @param att a set of attributes 1291 * @see #writeStartTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, boolean) 1292 */ 1293 private void writeStartTag( Tag t, MutableAttributeSet att ) 1294 { 1295 writeStartTag( t, att, false ); 1296 } 1297 1298 /** 1299 * Starts a Tag with attributes. For instance: 1300 * <pre> 1301 * <tag attName="attValue"> 1302 * </pre> 1303 * <br> 1304 * 1305 * @param t a non null tag 1306 * @param att a set of attributes 1307 * @param isSimpleTag boolean to write as a simple tag 1308 */ 1309 private void writeStartTag( Tag t, MutableAttributeSet att, boolean isSimpleTag ) 1310 { 1311 if ( t == null ) 1312 { 1313 throw new IllegalArgumentException( "A tag is required" ); 1314 } 1315 1316 StringBuilder sb = new StringBuilder(); 1317 sb.append( LESS_THAN ); 1318 1319 sb.append( t.toString() ); 1320 1321 sb.append( SinkUtils.getAttributeString( att ) ); 1322 1323 if ( isSimpleTag ) 1324 { 1325 sb.append( SPACE ).append( SLASH ); 1326 } 1327 1328 sb.append( GREATER_THAN ); 1329 1330 write( sb.toString() ); 1331 } 1332 1333 /** 1334 * Writes a system EOL. 1335 */ 1336 private void writeEOL() 1337 { 1338 write( EOL ); 1339 } 1340 1341 /** 1342 * Writes a system EOL, with or without trim. 1343 */ 1344 private void writeEOL( boolean trim ) 1345 { 1346 if ( !trim ) 1347 { 1348 writeEOL(); 1349 return; 1350 } 1351 1352 String tmp = writer.toString().trim(); 1353 writer = new StringWriter(); 1354 writer.write( tmp ); 1355 write( EOL ); 1356 } 1357 1358 /** 1359 * Ends a Tag without writing an EOL. For instance: <pre></tag></pre>. 1360 * 1361 * @param t a tag. 1362 */ 1363 private void writeEndTag( Tag t ) 1364 { 1365 StringBuilder sb = new StringBuilder(); 1366 sb.append( LESS_THAN ); 1367 sb.append( SLASH ); 1368 1369 sb.append( t.toString() ); 1370 sb.append( GREATER_THAN ); 1371 1372 write( sb.toString() ); 1373 } 1374 1375 /** 1376 * Write HTML escaped text to output. 1377 * 1378 * @param text The text to write. 1379 */ 1380 protected void content( String text ) 1381 { 1382 write( escapeHTML( text ) ); 1383 } 1384 1385 /** 1386 * {@inheritDoc} 1387 */ 1388 protected void init() 1389 { 1390 super.init(); 1391 1392 this.writer = new StringWriter(); 1393 this.headFlag = false; 1394 this.levelList = 0; 1395 this.listStyles.clear(); 1396 this.boldFlag = false; 1397 } 1398 1399 /** 1400 * Forward to HtmlTools.escapeHTML( text ). 1401 * 1402 * @param text the String to escape, may be null 1403 * @return the text escaped, "" if null String input 1404 * @see org.apache.maven.doxia.util.HtmlTools#escapeHTML(String) 1405 */ 1406 protected static String escapeHTML( String text ) 1407 { 1408 return HtmlTools.escapeHTML( text ); 1409 } 1410}