UNPKG

ical.js-one.com

Version:

[![Build Status](https://secure.travis-ci.org/mozilla-comm/ical.js.png?branch=master)](http://travis-ci.org/mozilla-comm/ical.js)

214 lines (177 loc) 5.27 kB
ICAL.stringify = (function() { 'use strict'; var LINE_ENDING = '\r\n'; var DEFAULT_TYPE = 'text'; var design = ICAL.design; var helpers = ICAL.helpers; /** * Convert a full jCal Array into a ical document. * * @param {Array} jCal document. * @return {String} ical document. */ function stringify(jCal) { if (!jCal[0] || jCal[0] !== 'icalendar') { throw new Error('must provide full jCal document'); } // 1 because we skip the initial element. var i = 1; var len = jCal.length; var result = ''; for (; i < len; i++) { result += stringify.component(jCal[i]) + LINE_ENDING; } return result; } /** * Converts an jCal component array into a ICAL string. * Recursive will resolve sub-components. * * Exact component/property order is not saved all * properties will come before subcomponents. * * @param {Array} component jCal fragment of a component. */ stringify.component = function(component) { var name = component[0].toUpperCase(); var result = 'BEGIN:' + name + LINE_ENDING; var props = component[1]; var propIdx = 0; var propLen = props.length; for (; propIdx < propLen; propIdx++) { result += stringify.property(props[propIdx]) + LINE_ENDING; } var comps = component[2]; var compIdx = 0; var compLen = comps.length; for (; compIdx < compLen; compIdx++) { result += stringify.component(comps[compIdx]) + LINE_ENDING; } result += 'END:' + name; return result; } /** * Converts a single property to a ICAL string. * * @param {Array} property jCal property. */ stringify.property = function(property) { var name = property[0].toUpperCase(); var jsName = property[0]; var params = property[1]; var line = name; var paramName; for (paramName in params) { if (params.hasOwnProperty(paramName)) { line += ';' + paramName.toUpperCase(); line += '=' + stringify.propertyValue(params[paramName]); } } // there is no value so return. if (property.length === 3) { // if no params where inserted and no value // we given we must add a blank value. if (!paramName) { line += ':'; } return line; } var valueType = property[2]; var propDetails; var multiValue = false; var isDefault = false; if (jsName in design.property) { propDetails = design.property[jsName]; if ('multiValue' in propDetails) { multiValue = propDetails.multiValue; } if ('defaultType' in propDetails) { if (valueType === propDetails.defaultType) { isDefault = true; } } else { if (valueType === DEFAULT_TYPE) { isDefault = true; } } } else { if (valueType === DEFAULT_TYPE) { isDefault = true; } } // push the VALUE property if type is not the default // for the current property. if (!isDefault) { // value will never contain ;/:/, so we don't escape it here. line += ';VALUE=' + valueType.toUpperCase(); } line += ':'; if (multiValue) { line += stringify.multiValue( property.slice(3), multiValue, valueType ); } else { line += stringify.value(property[3], valueType); } return ICAL.helpers.foldline(line); } /** * Handles escaping of property values that may contain: * * COLON (:), SEMICOLON (;), or COMMA (,) * * If any of the above are present the result is wrapped * in double quotes. * * @param {String} value raw value. * @return {String} given or escaped value when needed. */ stringify.propertyValue = function(value) { if ((helpers.unescapedIndexOf(value, ',') === -1) && (helpers.unescapedIndexOf(value, ':') === -1) && (helpers.unescapedIndexOf(value, ';') === -1)) { return value; } return '"' + value + '"'; } /** * Converts an array of ical values into a single * string based on a type and a delimiter value (like ","). * * @param {Array} values list of values to convert. * @param {String} delim used to join the values usually (",", ";", ":"). * @param {String} type lowecase ical value type * (like boolean, date-time, etc..). * * @return {String} ical string for value. */ stringify.multiValue = function(values, delim, type) { var result = ''; var len = values.length; var i = 0; for (; i < len; i++) { result += stringify.value(values[i], type); if (i !== (len - 1)) { result += delim; } } return result; } /** * Processes a single ical value runs the associated "toICAL" * method from the design value type if available to convert * the value. * * @param {String|Numeric} value some formatted value. * @param {String} type lowecase ical value type * (like boolean, date-time, etc..). * @return {String} ical value for single value. */ stringify.value = function(value, type) { if (type in design.value && 'toICAL' in design.value[type]) { return design.value[type].toICAL(value); } return value; } return stringify; }());