Initial import
This commit is contained in:
parent
ea6a546f97
commit
e95bc01469
9 changed files with 581 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -31,3 +31,6 @@ DerivedData
|
|||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# DS_Store
|
||||
.DS_Store
|
||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "CommandLine"]
|
||||
path = CommandLine
|
||||
url = https://github.com/jatoben/CommandLine.git
|
1
CommandLine
Submodule
1
CommandLine
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 7a8323d3a037c0a0d82c6cf734b46d98da10498a
|
60
README.md
Normal file
60
README.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
opml2html
|
||||
=========
|
||||
|
||||
### What is this? (aka the Problem to be Solved)
|
||||
|
||||
O HAI
|
||||
Need stuff here
|
||||
|
||||
[NosillaCast][NC]
|
||||
[Omni Group][OMNI]
|
||||
[OmniOutliner][OO]
|
||||
|
||||
### Usage
|
||||
|
||||
```
|
||||
Usage: opml2html [options]
|
||||
-f, --input-file:
|
||||
Path to the input file. (Required)
|
||||
-o, --output-file:
|
||||
Path to the output file. (Optional, default = <filename without extension>.html)
|
||||
-l, --full-mode:
|
||||
Create full HTML output (including <head>, etc.)
|
||||
-h, --help:
|
||||
Prints a help message.
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
This software is licensed under the terms of the [MIT License][MIT].
|
||||
|
||||
Copyright (c) 2015 Donald Burr <[dburr@DonaldBurr.com][EMAIL]>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
### Credits
|
||||
|
||||
Uses Ben Gollmer's Swift [CommandLine][CL] library.
|
||||
|
||||
[NC]: http://podfeet.com/ "NosillaCast"
|
||||
[OMNI]: https://www.omnigroup.com "The Omni Group"
|
||||
[OO]: https://www.omnigroup.com/omnioutliner "OmniOutliner"
|
||||
[EMAIL]: mailto:dburr@DonaldBurr.com?subject=opml2html "Email"
|
||||
[MIT]: http://opensource.org/licenses/MIT "MIT License"
|
||||
[CL]: https://github.com/jatoben/CommandLine "CommandLine"
|
BIN
bin/opml2html
Executable file
BIN
bin/opml2html
Executable file
Binary file not shown.
260
opml2html.xcodeproj/project.pbxproj
Normal file
260
opml2html.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,260 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
EA273E611B7D0E810083B1C5 /* CommandLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA273E5E1B7D0E810083B1C5 /* CommandLine.swift */; };
|
||||
EA273E621B7D0E810083B1C5 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA273E5F1B7D0E810083B1C5 /* Option.swift */; };
|
||||
EA273E631B7D0E810083B1C5 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA273E601B7D0E810083B1C5 /* StringExtensions.swift */; };
|
||||
EA37B3E91B7C6A970025B496 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA37B3E81B7C6A970025B496 /* main.swift */; };
|
||||
EA37B3F01B7C6D7C0025B496 /* ParseEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA37B3EF1B7C6D7C0025B496 /* ParseEngine.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
EA37B3E31B7C6A970025B496 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
EA273E5E1B7D0E810083B1C5 /* CommandLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CommandLine.swift; path = ../CommandLine/CommandLine/CommandLine.swift; sourceTree = "<group>"; };
|
||||
EA273E5F1B7D0E810083B1C5 /* Option.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Option.swift; path = ../CommandLine/CommandLine/Option.swift; sourceTree = "<group>"; };
|
||||
EA273E601B7D0E810083B1C5 /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StringExtensions.swift; path = ../CommandLine/CommandLine/StringExtensions.swift; sourceTree = "<group>"; };
|
||||
EA37B3E51B7C6A970025B496 /* opml2html */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = opml2html; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
EA37B3E81B7C6A970025B496 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
EA37B3EF1B7C6D7C0025B496 /* ParseEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParseEngine.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
EA37B3E21B7C6A970025B496 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
EA37B3DC1B7C6A970025B496 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EA37B3E71B7C6A970025B496 /* opml2html */,
|
||||
EA37B3E61B7C6A970025B496 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EA37B3E61B7C6A970025B496 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EA37B3E51B7C6A970025B496 /* opml2html */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EA37B3E71B7C6A970025B496 /* opml2html */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EA37B3E81B7C6A970025B496 /* main.swift */,
|
||||
EA37B3EF1B7C6D7C0025B496 /* ParseEngine.swift */,
|
||||
EA273E5E1B7D0E810083B1C5 /* CommandLine.swift */,
|
||||
EA273E5F1B7D0E810083B1C5 /* Option.swift */,
|
||||
EA273E601B7D0E810083B1C5 /* StringExtensions.swift */,
|
||||
);
|
||||
path = opml2html;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
EA37B3E41B7C6A970025B496 /* opml2html */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = EA37B3EC1B7C6A970025B496 /* Build configuration list for PBXNativeTarget "opml2html" */;
|
||||
buildPhases = (
|
||||
EA37B3E11B7C6A970025B496 /* Sources */,
|
||||
EA37B3E21B7C6A970025B496 /* Frameworks */,
|
||||
EA37B3E31B7C6A970025B496 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = opml2html;
|
||||
productName = opml2html;
|
||||
productReference = EA37B3E51B7C6A970025B496 /* opml2html */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
EA37B3DD1B7C6A970025B496 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0640;
|
||||
ORGANIZATIONNAME = "Donald Burr";
|
||||
TargetAttributes = {
|
||||
EA37B3E41B7C6A970025B496 = {
|
||||
CreatedOnToolsVersion = 6.4;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = EA37B3E01B7C6A970025B496 /* Build configuration list for PBXProject "opml2html" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = EA37B3DC1B7C6A970025B496;
|
||||
productRefGroup = EA37B3E61B7C6A970025B496 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
EA37B3E41B7C6A970025B496 /* opml2html */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
EA37B3E11B7C6A970025B496 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
EA273E621B7D0E810083B1C5 /* Option.swift in Sources */,
|
||||
EA273E611B7D0E810083B1C5 /* CommandLine.swift in Sources */,
|
||||
EA273E631B7D0E810083B1C5 /* StringExtensions.swift in Sources */,
|
||||
EA37B3E91B7C6A970025B496 /* main.swift in Sources */,
|
||||
EA37B3F01B7C6D7C0025B496 /* ParseEngine.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
EA37B3EA1B7C6A970025B496 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
EA37B3EB1B7C6A970025B496 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
EA37B3ED1B7C6A970025B496 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
EA37B3EE1B7C6A970025B496 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
EA37B3E01B7C6A970025B496 /* Build configuration list for PBXProject "opml2html" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
EA37B3EA1B7C6A970025B496 /* Debug */,
|
||||
EA37B3EB1B7C6A970025B496 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
EA37B3EC1B7C6A970025B496 /* Build configuration list for PBXNativeTarget "opml2html" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
EA37B3ED1B7C6A970025B496 /* Debug */,
|
||||
EA37B3EE1B7C6A970025B496 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = EA37B3DD1B7C6A970025B496 /* Project object */;
|
||||
}
|
7
opml2html.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
opml2html.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:opml2html.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
156
opml2html/ParseEngine.swift
Normal file
156
opml2html/ParseEngine.swift
Normal file
|
@ -0,0 +1,156 @@
|
|||
//
|
||||
// ParseEngine.swift
|
||||
// opml2html
|
||||
//
|
||||
// Created by Donald Burr on 8/12/15.
|
||||
// Copyright (c) 2015 Donald Burr. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol ParseEngineDelegate {
|
||||
func parseDidSucceed(output: String)
|
||||
func parseDidFail(error: NSError)
|
||||
}
|
||||
|
||||
class ParseEngine : NSObject, NSXMLParserDelegate {
|
||||
var parser: NSXMLParser?
|
||||
var currentElementText: String = ""
|
||||
var level: Int = 0
|
||||
var fullOutput: Bool = false
|
||||
var parseOutput: String = ""
|
||||
var delegate: ParseEngineDelegate?
|
||||
var validChars: NSMutableCharacterSet
|
||||
|
||||
override init() {
|
||||
self.validChars = NSMutableCharacterSet(charactersInString: " ")
|
||||
self.validChars.formUnionWithCharacterSet(NSCharacterSet.URLPathAllowedCharacterSet())
|
||||
}
|
||||
|
||||
init(delegate: ParseEngineDelegate) {
|
||||
self.delegate = delegate
|
||||
self.validChars = NSMutableCharacterSet(charactersInString: " ")
|
||||
self.validChars.formUnionWithCharacterSet(NSCharacterSet.URLPathAllowedCharacterSet())
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
|
||||
}
|
||||
|
||||
func parse(#path: String, fullOutput: Bool) {
|
||||
self.fullOutput = fullOutput
|
||||
if !NSFileManager.defaultManager().fileExistsAtPath(path) {
|
||||
if let delegate = delegate {
|
||||
let userInfo: [String:String] =
|
||||
[
|
||||
NSLocalizedDescriptionKey: "Operation was unsuccessful.",
|
||||
NSLocalizedFailureReasonErrorKey: "File does not exist.",
|
||||
NSLocalizedRecoverySuggestionErrorKey: "Check the filename."
|
||||
]
|
||||
|
||||
let error = NSError(domain: "ParseEngineErrorDomain", code: 1, userInfo: userInfo)
|
||||
delegate.parseDidFail(error)
|
||||
}
|
||||
return
|
||||
}
|
||||
let fileUrl = NSURL(fileURLWithPath: path)
|
||||
parser = NSXMLParser(contentsOfURL: fileUrl)
|
||||
if let p = parser {
|
||||
p.delegate = self
|
||||
if !p.parse() {
|
||||
if let delegate = delegate {
|
||||
let userInfo: [String:String] =
|
||||
[
|
||||
NSLocalizedDescriptionKey: "Operation was unsuccessful.",
|
||||
NSLocalizedFailureReasonErrorKey: "Parser failed to parse file.",
|
||||
NSLocalizedRecoverySuggestionErrorKey: "Check to make sure that the OPML file syntax is correct."
|
||||
]
|
||||
let error = NSError(domain: "ParseEngineErrorDomain", code: 2, userInfo: userInfo)
|
||||
delegate.parseDidFail(error)
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if let delegate = delegate {
|
||||
let userInfo: [String:String] =
|
||||
[
|
||||
NSLocalizedDescriptionKey: "Operation was unsuccessful.",
|
||||
NSLocalizedFailureReasonErrorKey: "Parser failed to initialize.",
|
||||
NSLocalizedRecoverySuggestionErrorKey: "Check to make sure that the OPML file syntax is correct."
|
||||
]
|
||||
let error = NSError(domain: "ParseEngineErrorDomain", code: 2, userInfo: userInfo)
|
||||
delegate.parseDidFail(error)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {
|
||||
if (elementName == "outline") {
|
||||
let outlineText: String = attributeDict["text"] as! String
|
||||
let saneText = saneify(outlineText)
|
||||
addParsedText("<UL>\n")
|
||||
addParsedText("<LI>\(saneText)</LI>\n")
|
||||
level++
|
||||
}
|
||||
}
|
||||
|
||||
func parser(parser: NSXMLParser, foundCharacters string: String?) {
|
||||
if let string = string {
|
||||
currentElementText += string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
|
||||
}
|
||||
}
|
||||
|
||||
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
|
||||
let saneText = saneify(currentElementText)
|
||||
|
||||
if (elementName == "title") {
|
||||
if (fullOutput) {
|
||||
addParsedText("<HTML>\n<HEAD>\n<TITLE>\(saneText)</TITLE>\n</HEAD>\n<BODY>\n")
|
||||
}
|
||||
addParsedText("<H1>\(saneText)</H1>\n")
|
||||
currentElementText = ""
|
||||
} else if (elementName == "outline") {
|
||||
addParsedText("</UL>\n")
|
||||
level--;
|
||||
if (level == 0 && fullOutput) {
|
||||
addParsedText("</BODY>\n</HTML>\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parserDidEndDocument(parser: NSXMLParser) {
|
||||
if let delegate = delegate {
|
||||
delegate.parseDidSucceed(parseOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
|
||||
if let delegate = delegate {
|
||||
let userInfo: [String:String] =
|
||||
[
|
||||
NSLocalizedDescriptionKey: "Parse Failed.",
|
||||
NSLocalizedFailureReasonErrorKey: "Parse Error #\(parseError.code): \(parseError.localizedDescription)",
|
||||
NSLocalizedRecoverySuggestionErrorKey: "Check the validity of your XML."
|
||||
]
|
||||
let error = NSError(domain: "ParseEngineErrorDomain", code: 3, userInfo: userInfo)
|
||||
delegate.parseDidFail(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func addParsedText(text: String) {
|
||||
parseOutput += text
|
||||
}
|
||||
|
||||
private func saneify(string: String) -> String {
|
||||
// let escapedText = currentElementText.stringByAddingPercentEncodingWithAllowedCharacters(self.validChars)!
|
||||
// let escapedText = currentElementText.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
|
||||
|
||||
let string1 = string.stringByReplacingOccurrencesOfString("’", withString: "'", options: NSStringCompareOptions.LiteralSearch, range: nil)
|
||||
if (string1.rangeOfString("http") != nil) {
|
||||
return "<A HREF=\"\(string1)\">\(string1)</A>"
|
||||
} else {
|
||||
return string1
|
||||
}
|
||||
}
|
||||
}
|
91
opml2html/main.swift
Normal file
91
opml2html/main.swift
Normal file
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// main.swift
|
||||
// opml2html
|
||||
//
|
||||
// Created by Donald Burr on 8/12/15.
|
||||
// Copyright (c) 2015 Donald Burr. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
var full: Bool = false
|
||||
var fileName: String?
|
||||
|
||||
let cli = CommandLine()
|
||||
|
||||
class Handler: NSObject, ParseEngineDelegate {
|
||||
var fileName: String?
|
||||
let parseEngine = ParseEngine()
|
||||
|
||||
func process(#inFile: String, outFile: String, fullOutput: Bool) {
|
||||
parseEngine.delegate = self
|
||||
println("Operating on file: \(inFile)")
|
||||
print("Saving to file: \(outFile)")
|
||||
if (fullOutput) {
|
||||
println(" (full mode)")
|
||||
} else {
|
||||
println()
|
||||
}
|
||||
self.fileName = outFile
|
||||
parseEngine.parse(path: inFile, fullOutput: fullOutput)
|
||||
}
|
||||
|
||||
func parseDidSucceed(output: String) {
|
||||
if let fileName = fileName {
|
||||
output.writeToFile(fileName, atomically: true, encoding: NSUTF8StringEncoding, error: nil)
|
||||
} else {
|
||||
println(output)
|
||||
}
|
||||
}
|
||||
|
||||
func parseDidFail(error: NSError) {
|
||||
println("Parse Failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
let handler = Handler()
|
||||
|
||||
let filePath = StringOption(shortFlag: "f", longFlag: "input-file", required: true,
|
||||
helpMessage: "Path to the input file. (Required)")
|
||||
let outputFilePath = StringOption(shortFlag: "o", longFlag: "output-file", required: false,
|
||||
helpMessage: "Path to the output file. (Optional, default = <filename without extension>.html)")
|
||||
let fullMode = BoolOption(shortFlag: "l", longFlag: "full-mode",
|
||||
helpMessage: "Create full HTML output (including <head>, etc.)")
|
||||
let help = BoolOption(shortFlag: "h", longFlag: "help",
|
||||
helpMessage: "Prints a help message.")
|
||||
|
||||
cli.addOptions(filePath, outputFilePath, fullMode, help)
|
||||
|
||||
let (success, error) = cli.parse()
|
||||
if !success {
|
||||
println(error!)
|
||||
cli.printUsage()
|
||||
exit(EX_USAGE)
|
||||
}
|
||||
|
||||
full = fullMode.value
|
||||
|
||||
if let fn = filePath.value {
|
||||
if let saveFile = outputFilePath.value {
|
||||
handler.process(inFile: fn, outFile: saveFile, fullOutput: full)
|
||||
} else {
|
||||
let saveFile = fn.stringByDeletingPathExtension.stringByAppendingPathExtension("html")!
|
||||
handler.process(inFile: fn, outFile: saveFile, fullOutput: full)
|
||||
}
|
||||
} else {
|
||||
println("Error: no file name specified")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
/*
|
||||
for argument in Process.arguments {
|
||||
switch argument {
|
||||
case "--full":
|
||||
println("Full mode enabled")
|
||||
full = true
|
||||
|
||||
default:
|
||||
println("an argument: \(argument)")
|
||||
}
|
||||
}
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue