// TODO: This should all be refactored up into an abstract base class with
  // default no-op methods, allowing a subclass to only override the ones they
  // want...
  public void handleNode(ParseContext pContext, Node node) throws IOException {
    ReplayParseContext context = (ReplayParseContext) pContext;
    if (NodeUtils.isRemarkNode(node)) {
      RemarkNode remarkNode = (RemarkNode) node;
      remarkNode.setText(jsBlockTrans.transform(context, remarkNode.getText()));
      emit(context, null, node, null);

    } else if (NodeUtils.isTextNode(node)) {
      TextNode textNode = (TextNode) node;
      if (context.isInCSS()) {
        handleCSSTextNode(context, textNode);

      } else if (context.isInScriptText()) {
        handleJSTextNode(context, textNode);
      } else {
        emit(context, null, textNode, null);
        //				handleContentTextNode(context,textNode);
      }
    } else if (NodeUtils.isTagNode(node)) {
      TagNode tagNode = (TagNode) node;

      if (NodeUtils.isOpenTagNodeNamed(tagNode, NodeUtils.SCRIPT_TAG_NAME)) {
        handleJSIncludeNode(context, tagNode);
      } else if (tagNode.isEndTag()) {

        if (tagNode.getTagName().equals("HEAD")) {
          context.putData(FERRET_IN_HEAD, null);
        }

        if (checkAllowTag(pContext, tagNode)) {
          emit(context, null, tagNode, null);
        }

        //				handleCloseTagNode(context,tagNode);
      } else {
        // assume start, possibly empty:
        handleOpenTagNode(context, tagNode);
      }
    } else {
      throw new IllegalArgumentException("Unknown node type..");
    }
  }
  /**
   * 生成预览内容
   *
   * @param html
   * @param max_count
   * @return
   */
  public static String preview(String html, int max_count) {
    if (html.length() <= max_count * 1.1) return html;
    Parser parser = new Parser();
    StringBuffer prvContent = new StringBuffer();
    try {
      parser.setEncoding(Globals.ENC_8859_1);
      parser.setInputHTML(html);

      parser.setNodeFactory(factory);

      NodeList nodes = parser.extractAllNodesThatMatch(nfilter);
      Node node = null;
      for (int i = 0; i < nodes.size(); i++) {
        if (prvContent.length() >= max_count) {
          if (node instanceof TagNode) {
            TagNode tmp_node = (TagNode) node;
            boolean isEnd = tmp_node.isEndTag();
            if (!isEnd) {
              prvContent.setLength(prvContent.length() - tmp_node.getText().length() - 2);
            }
          }
          // 补齐所有未关闭的标签
          Node parent = node;
          // System.out.println("current node is . "+parent.getText());
          do {
            // System.out.println(parent.getClass().getName()+":"+parent.getText());
            parent = parent.getParent();
            // System.out.println("parent = "+parent);
            if (parent == null) break;
            if (!(parent instanceof TagNode)) continue;
            // System.out.println("Parent node is no ended. "+parent.getText());
            prvContent.append(((TagNode) parent).getEndTag().toHtml());
          } while (true);
          break;
        }
        node = nodes.elementAt(i);
        if (node instanceof TagNode) {
          TagNode tag = (TagNode) node;
          prvContent.append('<');
          prvContent.append(tag.getText());
          prvContent.append('>');
          // System.out.println("TAG: " + '<'+tag.getText()+'>');
        } else if (node instanceof TextNode) {
          int space = max_count - prvContent.length();
          if (space > 10) {
            TextNode text = (TextNode) node;
            if (text.getText().length() < 10) prvContent.append(text.getText());
            else
              prvContent.append(
                  StringUtils.abbreviate(text.getText(), max_count - prvContent.length()));
            // System.out.println("TEXT: " + text.getText());
          }
        }
      }
      return prvContent.toString();
    } catch (ParserException e) {
      e.printStackTrace();
    } finally {
      parser = null;
    }
    return html;
  }