原文

The ical.js parser uses the design data available via ICAL.design to decide if the received data is semantically correct. It contains information about components, properties, property parameters and property values. There is specific design data for iCalendar, vCard 3 and vCard 4 which is used based on the component type or the passed design set.

ical.js解析器使用ICAL.design来判断接收到的数据,包含组件、属性、属性参数和属性值,语义是否正确。基于组件类型,支持识别iCalendar,vCard 3和vCard 4等类型,也可以传入其他的设计集合。

Not all aspects of the design data you see in design.js are actually enforced, a strict mode parser or validator is conceivable in the future.

实际上,design.js中设计的数据并不要求完全具备,有可能在以后会添加一种严格模式的解析器或验证器。

注册属性数据(Registering property data)

If a new property is added for which the property name is not set in the design data, the default type unknown will be set in the jCal array as the type. While this is not incorrect and works well when converting from jCal to iCalendar by fully ommitting the VALUE parameter, in many cases you will want to register an explicit type for the property.

如果添加了一个设计数据中不包含的新属性时,jCal会使用unknown作为其数据类型。虽然这并不正确,但并不会抛出异常——从jCal转化为iCalendar时会完全忽略对应的值参数。大多数情况下,需要显式的为这个属性注册确定的数据类型。

The iCalendar specification works with implicit value and parameter types, but allows explicitly mentioning the value data type through the VALUE parameter. jCal on the other hand explicitly mentions the value type in its array structure. During conversion from iCalendar to jCal, some assumptions have to be made if the value data type is not explicitly mentioned. This is mostly the case for X-Properties and additionally registered IANA properties.

iCalendar规范接受不确定的值和参数类型,但也允许通过VALUE参数明确指定参数的数据类型。另一方面,jCal的数组结构中要求确定的数据类型。当从iCalendar转化为jCal的时候,会对不明确的值类型作出假设,比如X-属性和IANA注册的属性。

While the iCalendar specification assumes that unknown values should be of the TEXT type, this doesn’t work in practice. If an extension to iCalendar has registered a property with the default type being PERIOD while also allowing multiple values, round-tripping between iCalendar and jCal will cause extra escaping of the comma character used to separate the values (FOO:bar,baz becomes FOO:bar\,baz).

虽然iCalendar规范会把未知数据类型的值假设为TEXT类型,但这种方式并不完美。比如一个iCalendar扩展注册了PERIOD属性的默认类型允许多值,当数据在iCalendar和jCal之间来回转化时,可能导致逗号被额外的转移(FOO:bar,baz转义为FOO:bar\,baz)。

To solve this, jCal has introduced the “unknown” type. It is used for all properties the parser doesn’t know about and keeps the value as it is. Lets say you have your own X-Property that uses multiple values and you want to retrieve them separately, or there is a new IANA property from an extension that has not been added to the ical.js design data. In the latter case, please file an issue to make sure it will be included in the future.

为了解决这个问题,jCal引入了“unknown”类型当属性类型未知时保持原值。有可能你有自己的支持多值的X-属性需要单独处理,或者一个新的IANA属性尚未包含在ical.js的设计数据中。对于后面这种情况,一定要创建一个issue来确保其包含在未来的版本中。

You can make sure your property is understood by adding information to the design set for the type of component you are working with:

可以将自定义属性的解析信息添加到对应类型组件的设计数据中,来保证工作正常:

// iCalendar: X-MY-PROPERTY:foo
//      jCal: ["x-my-property", {}, "text", "foo"]
ICAL.design.icalendar.property["x-my-property"] = {
  defaultType: "text", // [required] The default type from ICAL.design.value
  allowedTypes: ["period", "text"], // [optional] Valid value types this property can have (currently unused)
  detectType: function(value) { ... } // [optional] A function called to determine which type the value is
};

// iCalendar: X-MY-MULTIVAL:foo,bar,baz
//      jCal: ["x-my-multival", {}, "text", "foo", "bar", "baz"]
ICAL.design.icalendar.property["x-my-multival"] = {
  defaultType: "text", // [required] The default type from ICAL.design.value
  multiValue: "," // [optional] This property takes multiple, comma-separated values
                  //              and turns each of them into a jCal value.
};

// iCalendar: X-MY-STRUCTUREDVAL:foo;bar;baz
//      jCal: ["x-my-structuredval", {}, "text", [ "foo", "bar", "baz" ] ]
ICAL.design.icalendar.property["x-my-structuredval"] = {
  defaultType: "text", // [required] The default type from ICAL.design.value
  structuredValue: ";" // [optional] This property takes multiple, semicolon-separated values
                       //              and turns them into a single jCal value.
};

注册参数值类型(Registering parameter value types)

A parameter doesn’t have an explicit value type, but can be parsed in various ways. If you have your own parameters that need a different format, you can do it the following way:

参数没有明确的值类型,但是也可以使用多种方式解析。如果需要为参数设置不同的格式,可以使用下面的方法:

// iCalendar: SUMMARY;MYENUMPARAM=FOO:value
//      jCal: ["summary", { "myenumparam": "FOO" }, "text", "value"]
ICAL.design.icalendar.param["myenumparam"] = {
  values: [ "FOO", "BAR" ],  // [optional] An array of valid values for this parameter
  allowXName: true, // If true, X-Parameters are also allowed
  allowIanaToken: true // If true, other IANA tokens are also allowed
};

// iCalendar: SUMMARY;MYTYPEDPARAM=user@example.com,user2@example.com:value
//      jCal: ["summary", { "mytypedparam": ["user@example.com", "user2@example.com" ] }, "text", "value" ]
ICAL.design.icalendar.param["mytypedparam"] = {
  valueType: "cal-address", // If set, the parameter must use this value type as a format
  multiValue: "," // The parameter can consist of multiple values itself, which will be an array
};

// iCalendar: SUMMARY;MYMULTIPARAM="FOO","BAR":value
//      jCal: ["summary", { "mymultiparam": ["FOO", "BAR"] }, "text", "value"]
ICAL.design.icalendar.param["mymultiparam"] = {
  valueType: "text", // If set, the parameter must use this value type as a format
  multiValue: ",", // The parameter can consist of multiple values itself, which will be an array
  multiValueSeparateDQuote: true // If true, double quotes enclose (multi-)values instead of the whole property.
};

注册值类型(Registering data value types)

Registering a new data value type is rather unlikely, this is usually the result of a new RFC defining a value type. Data value types are things like “text”, “recur”, “cal-address”. If this does happen, please file an issue. Here is the code to register a value type:

注册一个新的值类型是不大可能的,通常情况下新的RFC中才会定义一个新的值类型。数据值类型是“text”,“recur”,“cal-address”之类的东西。如果这种情况发生了,一定要创建一个issue。下面是注册值类型示例代码:

ICAL.design.icalendar.value["newvalue"] = { ... };

The object passed may optionally contain the following functions and properties:

  • decorate and undecorate: Functions to augment the way the value is returned (i.e. as ICAL.Duration)
  • fromICAL and toICAL: Functions to modify the way the value is formatted between iCalendar and jCal
  • values: An array of valid values for this value type (currently unused)
  • matches: A regular expression the value type must match (currently unused)

对象中可能包含下列方法和属性:

  • decorateundecorate:用于增加新的返回方式(比如:ICAL.Duration)
  • fromICALtoICAL:用于在iCalendar和jCal之间修改返回值类型
  • values:包含一组有效的值类型的数组(现在已废弃)
  • matches:值类型必须匹配的正则表达式(现在已废弃)

The functions are further described in the following sections.

下面会继续介绍这些方法的使用。

在iCalendar和jCal之间转换数据(Conversion between iCalendar and jCal values)

Property value design data contains two functions called fromICAL and toICAL, which are used to convert property values between iCalendar and jCal. The type used depends on the value data type in jCal. Here are a few examples:

设计数据中的属性值的包含fromICAL和toICAL一对方法,用来在iCalendar和jCal中转化数据。使用的类型取决于jCal中的数据类型,下面是一些示例:

ICAL.design.icalendar.value['date-time'].fromICAL("20140102T030405"); // "2014-01-02T03:04:05"
ICAL.design.icalendar.value['date-time'].toICAL("2014-01-02T03:04:05"); // "20140102T030405"

ICAL.design.icalendar.value['recur'].fromICAL("FREQ=WEEKLY;COUNT=2"); // { freq: "WEEKLY", count: 2 }
ICAL.design.icalendar.value['recur'].toICAL({ freq: "WEEKLY", count: 2 }); // "FREQ=WEEKLY;COUNT=2"

包装值(Decorating Values)

Property value design data also contains two functions called decorate and undecorate. These are used on the next layer to take jCal data and turn it into a rich object that provides more methods to process the data value. These functions do not take raw iCalendar values, which are different especially for dates and recurrence. Examples:

设计数据中的属性值另外包含decorate和undecorate一对方法。用来将jCal数据转化为一个包含多个方法的富对象,反之亦然。这一对方法跟原始的iCalendar值无关,尤其针对日期和重复策略。示例如下:

var icalTime = ICAL.design.icalendar.value['date-time'].decorate("2014-01-02T03:04:05"); // Returns an ICAL.Time object
ICAL.design.icalendar.value['date-time'].undecorate(icalTime); // Returns "2014-01-02T03:04:05"

var icalRecur = ICAL.design.icalendar.value['recur'].decorate({ freq: "WEEKLY", count: 2 }); // Returns an ICAL.Recur object
ICAL.design.icalendar.value['recur'].undecorate(icalRecur); // Returns { freq: "WEEKLY", count: 2 }