001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.api.html.lexer;
042:
043: import java.util.Collection;
044: import java.util.EnumSet;
045: import java.util.Map;
046: import org.netbeans.api.lexer.InputAttributes;
047: import org.netbeans.api.lexer.Language;
048: import org.netbeans.api.lexer.LanguagePath;
049: import org.netbeans.api.lexer.Token;
050: import org.netbeans.api.lexer.TokenId;
051: import org.netbeans.lib.html.lexer.HTMLLexer;
052: import org.netbeans.spi.lexer.LanguageEmbedding;
053: import org.netbeans.spi.lexer.LanguageHierarchy;
054: import org.netbeans.spi.lexer.Lexer;
055: import org.netbeans.spi.lexer.LexerRestartInfo;
056:
057: /**
058: * Token ids of HTML language
059: *
060: * @author Jan Lahoda, Miloslav Metelka, Marek Fukala
061: */
062: public enum HTMLTokenId implements TokenId {
063:
064: /** HTML text */
065: TEXT("text"),
066: /** HTML script e.g. javascript. */
067: SCRIPT("script"),
068: /** HTML CSS style.*/
069: STYLE("style"),
070: /** Whitespace in a tag: <code> <BODY" "bgcolor=red></code>. */
071: WS("ws"),
072: /** Error token - returned in various erroneous situations. */
073: ERROR("error"),
074: /** HTML open tag name: <code><"BODY"/></code>.*/
075: TAG_OPEN("tag"),
076: /** HTML close tag name: <code></"BODY"></code>.*/
077: TAG_CLOSE("tag"),
078: /** HTML tag attribute name: <code> <BODY "bgcolor"=red></code>.*/
079: ARGUMENT("argument"),
080: /** Equals sign in HTML tag: <code> <BODY bgcolor"="red></code>.*/
081: OPERATOR("operator"),
082: /** Attribute value in HTML tag: <code> <BODY bgcolor="red"></code>.*/
083: VALUE("value"),
084: /** HTML javascript attribute value, such as one following onclick etc. */
085: VALUE_JAVASCRIPT("value"),
086: /** HTML block comment: <code> <!-- xxx --> </code>.*/
087: BLOCK_COMMENT("block-comment"),
088: /** HTML/SGML comment.*/
089: SGML_COMMENT("sgml-comment"),
090: /** HTML/SGML declaration: <code> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> </code>.*/
091: DECLARATION("sgml-declaration"),
092: /** Character reference: <code> &amp; </code>.*/
093: CHARACTER("character"),
094: /** End of line.*/
095: EOL("text"),
096: /** HTML open tag symbol: <code> "<"BODY> </code>.*/
097: TAG_OPEN_SYMBOL("tag"),
098: /** HTML close tag symbol: <code> "</"BODY> </code>.*/
099: TAG_CLOSE_SYMBOL("tag");
100:
101: private final String primaryCategory;
102:
103: private static final String JAVASCRIPT_MIMETYPE = "text/javascript";//NOI18N
104: private static final String STYLE_MIMETYPE = "text/x-css";//NOI18N
105:
106: HTMLTokenId(String primaryCategory) {
107: this .primaryCategory = primaryCategory;
108: }
109:
110: private static final Language<HTMLTokenId> language = new LanguageHierarchy<HTMLTokenId>() {
111: @Override
112: protected Collection<HTMLTokenId> createTokenIds() {
113: return EnumSet.allOf(HTMLTokenId.class);
114: }
115:
116: @Override
117: protected Map<String, Collection<HTMLTokenId>> createTokenCategories() {
118: //Map<String,Collection<HTMLTokenId>> cats = new HashMap<String,Collection<HTMLTokenId>>();
119: // Additional literals being a lexical error
120: //cats.put("error", EnumSet.of());
121: return null;
122: }
123:
124: @Override
125: protected Lexer<HTMLTokenId> createLexer(
126: LexerRestartInfo<HTMLTokenId> info) {
127: return new HTMLLexer(info);
128: }
129:
130: @SuppressWarnings("unchecked")
131: @Override
132: protected LanguageEmbedding embedding(Token<HTMLTokenId> token,
133: LanguagePath languagePath,
134: InputAttributes inputAttributes) {
135: String mimeType = null;
136: switch (token.id()) {
137: // BEGIN TOR MODIFICATIONS
138: case VALUE_JAVASCRIPT:
139: mimeType = JAVASCRIPT_MIMETYPE;
140: if (mimeType != null) {
141: Language lang = Language.find(mimeType);
142: if (lang == null) {
143: return null; //no language found
144: } else {
145: // TODO:
146: // XXX Don't handle JavaScript for non-quoted attributes
147: // (Or use separate state so I can do 0,0 as offsets there
148: return LanguageEmbedding.create(lang, 1, 1,
149: true);
150: }
151: }
152: break;
153: // END TOR MODIFICATIONS
154: case SCRIPT:
155: mimeType = JAVASCRIPT_MIMETYPE;
156: break;
157: case STYLE:
158: mimeType = STYLE_MIMETYPE;
159: break;
160: }
161: if (mimeType != null) {
162: Language lang = Language.find(mimeType);
163: if (lang == null) {
164: return null; //no language found
165: } else {
166: return LanguageEmbedding.create(lang, 0, 0, true);
167: }
168: }
169: return null;
170: }
171:
172: @Override
173: protected String mimeType() {
174: return "text/html";
175: }
176: }.language();
177:
178: /** Gets a LanguageDescription describing a set of token ids
179: * that comprise the given language.
180: *
181: * @return non-null LanguageDescription
182: */
183: public static Language<HTMLTokenId> language() {
184: return language;
185: }
186:
187: /**
188: * Get name of primary token category into which this token belongs.
189: * <br/>
190: * Other token categories for this id can be defined in the language hierarchy.
191: *
192: * @return name of the primary token category into which this token belongs
193: * or null if there is no primary category for this token.
194: */
195: public String primaryCategory() {
196: return primaryCategory;
197: }
198:
199: }
|