code: function tokenString(quote, f) {
      return function(stream, state) {
        var ch;
  
        if(isInString(state) && stream.current() == quote) {
          popStateStack(state);
          if(f) state.tokenize = f;
          return ret("string", "string");
        }
  
        pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) });
  
        // if we're in a string and in an XML block, allow an embedded code block
        if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
          state.tokenize = tokenBase;
          return ret("string", "string"); 
        }
  
        
        while (ch = stream.next()) {
          if (ch ==  quote) {
            popStateStack(state);
            if(f) state.tokenize = f;
            break;
          }
          else {
            // if we're in a string and in an XML block, allow an embedded code block in an attribute
            if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
              state.tokenize = tokenBase;
              return ret("string", "string"); 
            }
  
          }
        }
        
        return ret("string", "string");
      };
    }
docs: tokenizer for string literals optionally pass a tokenizer function to set state.tokenize back to when finished