vcard_dart 2.0.1
vcard_dart: ^2.0.1 copied to clipboard
A comprehensive vCard parsing and generation library supporting vCard 2.1, 3.0, and 4.0 formats with jCard and xCard representations.
vcard_dart #
English | 简体中文
A comprehensive vCard parsing and generation library for Dart/Flutter.
📖 API Documentation | 📦 pub.dev
Features #
- ✅ Full vCard 2.1, 3.0, and 4.0 support (RFC 2426, RFC 6350)
- ✅ jCard (JSON) representation (RFC 7095)
- ✅ xCard (XML) representation (RFC 6351)
- ✅ Platform-agnostic (Web, Mobile, Desktop)
- ✅ Type-safe API with comprehensive validation
- ✅ Zero dependencies - pure Dart implementation
- ✅ Extensive test coverage
Installation #
Add to your pubspec.yaml:
dependencies:
vcard_dart: ^2.0.0
Then run:
dart pub get
Quick Start #
import 'package:vcard_dart/vcard_dart.dart';
// Create a vCard
final vcard = VCard()
..formattedName = 'John Doe'
..name = const StructuredName(
family: 'Doe',
given: 'John',
)
..emails.add(Email.work('john@example.com'))
..telephones.add(Telephone.cell('+1-555-123-4567'))
..addresses.add(const Address(
street: '123 Main St',
city: 'Anytown',
region: 'CA',
postalCode: '12345',
country: 'USA',
types: ['work'],
));
// Generate vCard 4.0 string
final generator = VCardGenerator();
final vcardString = generator.generate(vcard, version: VCardVersion.v40);
// Parse vCard
final parser = VCardParser();
final parsed = parser.parseSingle(vcardString);
print(parsed.formattedName); // John Doe
Usage #
Creating vCards #
final vcard = VCard()
// Required
..formattedName = 'Dr. Jane Smith, PhD'
// Structured name
..name = const StructuredName(
family: 'Smith',
given: 'Jane',
additional: ['Marie'],
prefixes: ['Dr.'],
suffixes: ['PhD'],
)
// Communication
..telephones.addAll([
Telephone.cell('+1-555-000-0000'),
Telephone.work('+1-555-111-1111'),
])
..emails.addAll([
Email.work('jane.smith@company.com'),
Email.home('jane@personal.com'),
])
// Organization
..organization = const Organization(
name: 'Acme Corporation',
units: ['Engineering', 'R&D'],
)
..title = 'Senior Engineer'
..role = 'Lead Developer'
// Address
..addresses.add(const Address(
street: '456 Tech Park',
city: 'Silicon Valley',
region: 'CA',
postalCode: '94000',
country: 'USA',
types: ['work'],
))
// Additional info
..birthday = DateOrDateTime(year: 1985, month: 4, day: 15)
..note = 'Key contact for technical projects'
..urls.add(WebUrl.work('https://company.com/jsmith'))
..categories = ['Colleague', 'Tech', 'VIP'];
Parsing vCards #
final parser = VCardParser();
// Parse a single vCard
const vcardText = '''
BEGIN:VCARD
VERSION:4.0
FN:John Doe
N:Doe;John;;;
TEL;TYPE=CELL:+1-555-123-4567
EMAIL:john@example.com
END:VCARD
''';
final vcard = parser.parseSingle(vcardText);
print(vcard.formattedName); // John Doe
print(vcard.telephones.first.number); // +1-555-123-4567
// Parse multiple vCards
const multipleVcards = '''
BEGIN:VCARD
VERSION:4.0
FN:Person One
END:VCARD
BEGIN:VCARD
VERSION:4.0
FN:Person Two
END:VCARD
''';
final vcards = parser.parse(multipleVcards);
print(vcards.length); // 2
// Lenient parsing mode (tolerates some errors)
final lenientParser = VCardParser(lenient: true);
final recovered = lenientParser.parse(malformedVcardText);
Generating vCards #
final generator = VCardGenerator();
// Generate vCard 4.0 (default)
final v40 = generator.generate(vcard);
// Generate vCard 3.0
final v30 = generator.generate(vcard, version: VCardVersion.v30);
// Generate vCard 2.1
final v21 = generator.generate(vcard, version: VCardVersion.v21);
// Generate multiple vCards
final multipleVcards = generator.generateAll([vcard1, vcard2]);
jCard (JSON Format) #
final formatter = JCardFormatter();
// Convert to jCard
final json = formatter.toJson(vcard);
final jsonString = formatter.toJsonString(vcard);
// Parse from jCard
final fromJson = formatter.fromJson(json);
final fromString = formatter.fromJsonString(jsonString);
xCard (XML Format) #
final formatter = XCardFormatter();
// Convert to xCard
final xml = formatter.toXml(vcard);
final prettyXml = formatter.toXml(vcard, pretty: true);
// Parse from xCard
final fromXml = formatter.fromXml(xmlString);
Supported Properties #
Essential Properties #
| Property | vCard 2.1 | vCard 3.0 | vCard 4.0 | Description |
|---|---|---|---|---|
| FN | ✅ | ✅ | ✅ | Formatted Name (Required) |
| N | ✅ | ✅ | ✅ | Structured Name |
| NICKNAME | ❌ | ✅ | ✅ | Nickname |
| PHOTO | ✅ | ✅ | ✅ | Photograph |
| BDAY | ✅ | ✅ | ✅ | Birthday |
| ANNIVERSARY | ❌ | ❌ | ✅ | Anniversary |
| GENDER | ❌ | ❌ | ✅ | Gender |
Communication #
| Property | vCard 2.1 | vCard 3.0 | vCard 4.0 | Description |
|---|---|---|---|---|
| TEL | ✅ | ✅ | ✅ | Telephone Number |
| ✅ | ✅ | ✅ | Email Address | |
| IMPP | ❌ | ✅ | ✅ | Instant Messaging |
| LANG | ❌ | ❌ | ✅ | Language Preference |
Address/Location #
| Property | vCard 2.1 | vCard 3.0 | vCard 4.0 | Description |
|---|---|---|---|---|
| ADR | ✅ | ✅ | ✅ | Postal Address |
| LABEL | ✅ | ✅ | ❌ | Address Label |
| GEO | ✅ | ✅ | ✅ | Geographic Position |
| TZ | ✅ | ✅ | ✅ | Timezone |
Organization #
| Property | vCard 2.1 | vCard 3.0 | vCard 4.0 | Description |
|---|---|---|---|---|
| ORG | ✅ | ✅ | ✅ | Organization Name |
| TITLE | ✅ | ✅ | ✅ | Job Title |
| ROLE | ✅ | ✅ | ✅ | Role |
| LOGO | ✅ | ✅ | ✅ | Organization Logo |
| MEMBER | ❌ | ❌ | ✅ | Group Member |
| RELATED | ❌ | ❌ | ✅ | Related Person |
Other #
| Property | vCard 2.1 | vCard 3.0 | vCard 4.0 | Description |
|---|---|---|---|---|
| NOTE | ✅ | ✅ | ✅ | Notes |
| PRODID | ❌ | ✅ | ✅ | Product ID |
| REV | ✅ | ✅ | ✅ | Revision |
| SOUND | ✅ | ✅ | ✅ | Sound |
| UID | ✅ | ✅ | ✅ | Unique Identifier |
| URL | ✅ | ✅ | ✅ | Website |
| VERSION | ✅ | ✅ | ✅ | Version (Required) |
| KEY | ✅ | ✅ | ✅ | Public Key |
| CATEGORIES | ❌ | ✅ | ✅ | Categories |
| SOURCE | ❌ | ✅ | ✅ | Source Directory |
| KIND | ❌ | ❌ | ✅ | Kind (individual/org/group/location) |
Error Handling #
The library provides detailed exception types:
try {
final vcard = parser.parseSingle(invalidText);
} on VCardParseException catch (e) {
print('Parse error: ${e.message}');
print('Line: ${e.line}');
} on MissingPropertyException catch (e) {
print('Missing required property: ${e.propertyName}');
} on UnsupportedVersionException catch (e) {
print('Version error: ${e.message}');
}
RFC Compliance #
This library implements the following RFCs:
- RFC 2425 - MIME Content-Type for Directory Information
- RFC 2426 - vCard 3.0
- RFC 6350 - vCard 4.0
- RFC 6351 - xCard XML Representation
- RFC 7095 - jCard JSON Format
- vCard 2.1 - Legacy Format
License #
MIT License - see LICENSE for details.
Contributing #
Contributions are welcome! Please read our contributing guidelines first.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Run tests:
dart test - Run analysis:
dart analyze - Format code:
dart format . - Commit:
git commit -m 'feat: add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request