Make packing and unpacking item data consistent

This commit is contained in:
Veronica Berglyd Olsen
2022-11-03 17:30:54 +01:00
parent da4f4b0801
commit 3eee8442a7
9 changed files with 2650 additions and 1873 deletions
+23 -18
View File
@@ -187,29 +187,34 @@ class NWItem:
def unpack(self, data): def unpack(self, data):
"""Set the values from a data dictionary. """Set the values from a data dictionary.
""" """
if "handle" in data: item = data.get("itemAttr", {})
self.setHandle(data["handle"]) meta = data.get("metaAttr", {})
name = data.get("nameAttr", {})
if "handle" in item:
self.setHandle(item["handle"])
else: else:
logger.error("Item does not have a handle") logger.error("Item does not have a handle")
return False return False
self.setName(data.get("label", "")) self.setName(data.get("name", ""))
self.setParent(data.get("parent", None)) self.setParent(item.get("parent", None))
self.setRoot(data.get("root", None)) self.setRoot(item.get("root", None))
self.setOrder(data.get("order", 0)) self.setOrder(item.get("order", 0))
self.setType(data.get("type", nwItemType.NO_TYPE)) self.setType(item.get("type", nwItemType.NO_TYPE))
self.setClass(data.get("class", nwItemClass.NO_CLASS)) self.setClass(item.get("class", nwItemClass.NO_CLASS))
self.setLayout(data.get("layout", nwItemLayout.NO_LAYOUT)) self.setExpanded(meta.get("expanded", False))
self.setStatus(name.get("status", None))
self.setImport(name.get("import", None))
self.setExpanded(data.get("expanded", False)) if self._type == nwItemType.FILE:
self.setStatus(data.get("status", None)) self.setLayout(item.get("layout", nwItemLayout.NO_LAYOUT))
self.setImport(data.get("import", None)) self.setMainHeading(meta.get("heading", "H0"))
self.setMainHeading(data.get("heading", "H0")) self.setCharCount(meta.get("charCount", 0))
self.setCharCount(data.get("charCount", 0)) self.setWordCount(meta.get("wordCount", 0))
self.setWordCount(data.get("wordCount", 0)) self.setParaCount(meta.get("paraCount", 0))
self.setParaCount(data.get("paraCount", 0)) self.setCursorPos(meta.get("cursorPos", 0))
self.setCursorPos(data.get("cursorPos", 0)) self.setActive(name.get("active", True))
self.setActive(data.get("active", True))
# Make some checks to ensure consistency # Make some checks to ensure consistency
if self._type == nwItemType.ROOT: if self._type == nwItemType.ROOT:
+60 -42
View File
@@ -68,24 +68,24 @@ class ProjectXMLReader:
"""The main project XML file reader class. All data is read into a """The main project XML file reader class. All data is read into a
NWProjectData instance, which must be provided. NWProjectData instance, which must be provided.
Version Change History File Format Version Change History
====================== ==================================
1.0 Original file format. 1.0 Original file format.
1.1 Changes the way documents are structured in the project folder 1.1 Changes the way documents are structured in the project folder
from data_X, where X is the first hex value of the handle, to a from data_X, where X is the first hex value of the handle, to a
single content folder. Introduced in version 0.7. single content folder. Introduced in version 0.7.
1.2 Changes the way autoReplace entries are stored. The 1.1 parser 1.2 Changes the way autoReplace entries are stored. Introduced in
will lose the autoReplace settings if allowed to read the file. version 0.10.
Introduced in version 0.10.
1.3 Reduces the number of layouts to only two. One for novel 1.3 Reduces the number of layouts to only two. One for novel
documents and one for project notes. Introduced in version 1.5. documents and one for project notes. Introduced in version 1.5.
1.4 Introduces a more compact format for storing items. All settings 1.4 Introduces a more compact format for storing items. All settings
aside from name are now attributes. This format also changes the aside from name are now attributes. This format also changes the
way satus and importance labels are stored and handled. way satus and importance labels, last used handles, and title
formats are stored. They are now all stored as key/value sets.
Introduced in version 2.0. Introduced in version 2.0.
""" """
@@ -158,7 +158,7 @@ class ProjectXMLReader:
except Exception as exc: except Exception as exc:
# Trying to open backup file instead # Trying to open backup file instead
logger.error("Failed to parse project xml", exc_info=exc) logger.error("Failed to parse project XML", exc_info=exc)
self._state = XMLReadState.CANNOT_PARSE self._state = XMLReadState.CANNOT_PARSE
backFile = self._path[:-3]+"bak" backFile = self._path[:-3]+"bak"
@@ -168,7 +168,7 @@ class ProjectXMLReader:
self._state = XMLReadState.PARSED_BACKUP self._state = XMLReadState.PARSED_BACKUP
logger.info("Backup project file parsed") logger.info("Backup project file parsed")
except Exception as exc: except Exception as exc:
logger.error("Failed to parse backup project xml", exc_info=exc) logger.error("Failed to parse backup project XML", exc_info=exc)
self._state = XMLReadState.CANNOT_PARSE self._state = XMLReadState.CANNOT_PARSE
return False return False
else: else:
@@ -205,7 +205,7 @@ class ProjectXMLReader:
else: else:
self._parseProjectContentLegacy(xSection, projContent, projData) self._parseProjectContentLegacy(xSection, projContent, projData)
else: else:
logger.warning("Ignored <root/%s> in xml", xSection.tag) logger.warning("Ignored <root/%s> in XML", xSection.tag)
if self._version == 0x0104: if self._version == 0x0104:
self._state = XMLReadState.PARSED_OK self._state = XMLReadState.PARSED_OK
@@ -238,7 +238,7 @@ class ProjectXMLReader:
elif xItem.tag == "editTime": elif xItem.tag == "editTime":
projData.setEditTime(xItem.text) projData.setEditTime(xItem.text)
else: else:
logger.warning("Ignored <root/project/%s> in xml", xItem.tag) logger.warning("Ignored <root/project/%s> in XML", xItem.tag)
return return
@@ -277,7 +277,7 @@ class ProjectXMLReader:
else: # Pre 1.4 format else: # Pre 1.4 format
projData.setTitleFormat(self._parseDictTagText(xItem)) projData.setTitleFormat(self._parseDictTagText(xItem))
else: else:
logger.warning("Ignored <root/settings/%s> in xml", xItem.tag) logger.warning("Ignored <root/settings/%s> in XML", xItem.tag)
return return
@@ -289,6 +289,10 @@ class ProjectXMLReader:
for xItem in xSection: for xItem in xSection:
if xItem.tag == "item": if xItem.tag == "item":
item = {} item = {}
meta = {}
name = {}
itemName = ""
item["handle"] = checkStringNone(xItem.attrib.get("handle"), None) item["handle"] = checkStringNone(xItem.attrib.get("handle"), None)
item["parent"] = checkStringNone(xItem.attrib.get("parent"), None) item["parent"] = checkStringNone(xItem.attrib.get("parent"), None)
item["root"] = checkStringNone(xItem.attrib.get("root"), None) item["root"] = checkStringNone(xItem.attrib.get("root"), None)
@@ -298,28 +302,33 @@ class ProjectXMLReader:
item["layout"] = checkString(xItem.attrib.get("layout"), "NO_LAYOUT") item["layout"] = checkString(xItem.attrib.get("layout"), "NO_LAYOUT")
for xVal in xItem: for xVal in xItem:
if xVal.tag == "meta": if xVal.tag == "meta":
item["expanded"] = checkBool(xVal.attrib.get("expanded"), False) meta["expanded"] = checkBool(xVal.attrib.get("expanded"), False)
item["heading"] = checkString(xVal.attrib.get("heading"), "H0") meta["heading"] = checkString(xVal.attrib.get("heading"), "H0")
item["charCount"] = checkInt(xVal.attrib.get("charCount"), 0) meta["charCount"] = checkInt(xVal.attrib.get("charCount"), 0)
item["wordCount"] = checkInt(xVal.attrib.get("wordCount"), 0) meta["wordCount"] = checkInt(xVal.attrib.get("wordCount"), 0)
item["paraCount"] = checkInt(xVal.attrib.get("paraCount"), 0) meta["paraCount"] = checkInt(xVal.attrib.get("paraCount"), 0)
item["cursorPos"] = checkInt(xVal.attrib.get("cursorPos"), 0) meta["cursorPos"] = checkInt(xVal.attrib.get("cursorPos"), 0)
elif xVal.tag == "name": elif xVal.tag == "name":
item["label"] = simplified(checkString(xVal.text, "")) itemName = simplified(checkString(xVal.text, ""))
item["status"] = checkStringNone(xVal.attrib.get("status"), None) name["status"] = checkStringNone(xVal.attrib.get("status"), None)
item["import"] = checkStringNone(xVal.attrib.get("import"), None) name["import"] = checkStringNone(xVal.attrib.get("import"), None)
item["active"] = checkBool(xVal.attrib.get("active"), False) name["active"] = checkBool(xVal.attrib.get("active"), False)
# ToDo: Remove before 2.0 release. Only needed for 2.0 pre-releases. # ToDo: Remove before 2.0 release. Only needed for 2.0 pre-releases.
if "exported" in xVal.attrib: if "exported" in xVal.attrib:
item["active"] = checkBool(xVal.attrib.get("exported"), False) name["active"] = checkBool(xVal.attrib.get("exported"), False)
else: else:
logger.warning("Ignored <root/content/item/%s> in xml", xVal.tag) logger.warning("Ignored <root/content/item/%s> in XML", xVal.tag)
projContent.append(item) projContent.append({
"name": itemName,
"itemAttr": item,
"metaAttr": meta,
"nameAttr": name,
})
else: else:
logger.warning("Ignored item <root/content/%s> in xml", xItem.tag) logger.warning("Ignored item <root/content/%s> in XML", xItem.tag)
return return
@@ -334,17 +343,21 @@ class ProjectXMLReader:
for xItem in xSection: for xItem in xSection:
item = {} item = {}
meta = {}
name = {}
itemName = ""
if xItem.tag == "item": if xItem.tag == "item":
item["handle"] = checkStringNone(xItem.attrib.get("handle", None), None) item["handle"] = checkStringNone(xItem.attrib.get("handle", None), None)
item["parent"] = checkStringNone(xItem.attrib.get("parent", None), None) item["parent"] = checkStringNone(xItem.attrib.get("parent", None), None)
item["root"] = None # Value was added in 1.4 item["root"] = None # Value was added in 1.4
item["order"] = checkInt(xItem.attrib.get("order", 0), 0) item["order"] = checkInt(xItem.attrib.get("order", 0), 0)
item["heading"] = "H0" # Value was added in 1.4 meta["heading"] = "H0" # Value was added in 1.4
tmpStatus = "" tmpStatus = ""
for xVal in xItem: for xVal in xItem:
if xVal.tag == "name": if xVal.tag == "name":
item["label"] = simplified(checkString(xVal.text, "")) itemName = simplified(checkString(xVal.text, ""))
elif xVal.tag == "status": elif xVal.tag == "status":
tmpStatus = checkStringNone(xVal.text, None) tmpStatus = checkStringNone(xVal.text, None)
elif xVal.tag == "type": elif xVal.tag == "type":
@@ -354,25 +367,25 @@ class ProjectXMLReader:
elif xVal.tag == "layout": elif xVal.tag == "layout":
item["layout"] = checkString(xVal.text, "") item["layout"] = checkString(xVal.text, "")
elif xVal.tag == "expanded": elif xVal.tag == "expanded":
item["expanded"] = checkBool(xVal.text, False) meta["expanded"] = checkBool(xVal.text, False)
elif xVal.tag == "exported": # Renamed to active in 1.4 elif xVal.tag == "exported": # Renamed to active in 1.4
item["active"] = checkBool(xVal.text, False) name["active"] = checkBool(xVal.text, False)
elif xVal.tag == "charCount": elif xVal.tag == "charCount":
item["charCount"] = checkInt(xVal.text, 0) meta["charCount"] = checkInt(xVal.text, 0)
elif xVal.tag == "wordCount": elif xVal.tag == "wordCount":
item["wordCount"] = checkInt(xVal.text, 0) meta["wordCount"] = checkInt(xVal.text, 0)
elif xVal.tag == "paraCount": elif xVal.tag == "paraCount":
item["paraCount"] = checkInt(xVal.text, 0) meta["paraCount"] = checkInt(xVal.text, 0)
elif xVal.tag == "cursorPos": elif xVal.tag == "cursorPos":
item["cursorPos"] = checkInt(xVal.text, 0) meta["cursorPos"] = checkInt(xVal.text, 0)
else: else:
logger.warning("Ignored <root/content/item/%s> in xml", xVal.tag) logger.warning("Ignored <root/content/item/%s> in XML", xVal.tag)
# Status was split into separate status/import with a key in 1.4 # Status was split into separate status/import with a key in 1.4
if item.get("class", "") in ("NOVEL", "ARCHIVE"): if item.get("class", "") in ("NOVEL", "ARCHIVE"):
item["status"] = statusMap.get(tmpStatus, None) name["status"] = statusMap.get(tmpStatus, None)
else: else:
item["import"] = importMap.get(tmpStatus, None) name["import"] = importMap.get(tmpStatus, None)
# A number of layouts were removed in 1.3 # A number of layouts were removed in 1.3
if item.get("layout", "") in ( if item.get("layout", "") in (
@@ -384,10 +397,15 @@ class ProjectXMLReader:
if item.get("type", "") == "TRASH": if item.get("type", "") == "TRASH":
item["type"] = "ROOT" item["type"] = "ROOT"
projContent.append(item) projContent.append({
"name": itemName,
"itemAttr": item,
"metaAttr": meta,
"nameAttr": name,
})
else: else:
logger.warning("Ignored <root/content/%s> in xml", xItem.tag) logger.warning("Ignored <root/content/%s> in XML", xItem.tag)
return return
@@ -495,7 +513,7 @@ class ProjectXMLWriter:
xName = etree.SubElement(xItem, "name", attrib=item.get("nameAttr", {})) xName = etree.SubElement(xItem, "name", attrib=item.get("nameAttr", {}))
xName.text = item["name"] xName.text = item["name"]
# Write the xml tree to file # Write the XML tree to file
saveFile = os.path.join(self._path, nwFiles.PROJ_FILE) saveFile = os.path.join(self._path, nwFiles.PROJ_FILE)
tempFile = os.path.join(self._path, nwFiles.PROJ_FILE+"~") tempFile = os.path.join(self._path, nwFiles.PROJ_FILE+"~")
backFile = os.path.join(self._path, nwFiles.PROJ_FILE[:-3]+"bak") backFile = os.path.join(self._path, nwFiles.PROJ_FILE[:-3]+"bak")
@@ -530,14 +548,14 @@ class ProjectXMLWriter:
## ##
def _packSingleValue(self, xParent, name, value, attrib=None): def _packSingleValue(self, xParent, name, value, attrib=None):
"""Pack a single value into an xml element. """Pack a single value into an XML element.
""" """
xItem = etree.SubElement(xParent, name, attrib=attrib) xItem = etree.SubElement(xParent, name, attrib=attrib)
xItem.text = str(value) or "" xItem.text = str(value) or ""
return return
def _packListValue(self, xParent, name, data): def _packListValue(self, xParent, name, data):
"""Pack a list of values into an xml element. """Pack a list of values into an XML element.
""" """
for value in data: for value in data:
xItem = etree.SubElement(xParent, name) xItem = etree.SubElement(xParent, name)
@@ -545,7 +563,7 @@ class ProjectXMLWriter:
return return
def _packDictKeyValue(self, xParent, name, data): def _packDictKeyValue(self, xParent, name, data):
"""Pack the entries of a dictionary into an xml element. """Pack the entries of a dictionary into an XML element.
""" """
xItem = etree.SubElement(xParent, name) xItem = etree.SubElement(xParent, name)
for key, value in data.items(): for key, value in data.items():
File diff suppressed because it is too large Load Diff
+449 -317
View File
@@ -1,362 +1,494 @@
[ [
{ {
"handle": "7031beac91f75", "name": "Novel",
"parent": null, "itemAttr": {
"root": null, "handle": "7031beac91f75",
"order": 0, "parent": null,
"heading": "H0", "root": null,
"label": "Novel", "order": 0,
"type": "ROOT", "type": "ROOT",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000002" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000002"
}
}, },
{ {
"handle": "53b69b83cdafc", "name": "Title Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "53b69b83cdafc",
"order": 0, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Title Page", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 72, "heading": "H0",
"wordCount": 15, "expanded": false,
"paraCount": 2, "charCount": 72,
"cursorPos": 78, "wordCount": 15,
"status": "s000002" "paraCount": 2,
"cursorPos": 78
},
"nameAttr": {
"active": true,
"status": "s000002"
}
}, },
{ {
"handle": "974e400180a99", "name": "Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "974e400180a99",
"order": 1, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Page", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 208, "heading": "H0",
"wordCount": 40, "expanded": false,
"paraCount": 2, "charCount": 208,
"cursorPos": 213, "wordCount": 40,
"status": "s000000" "paraCount": 2,
"cursorPos": 213
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "edca4be2fcaf8", "name": "Part One",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "edca4be2fcaf8",
"order": 2, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Part One", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 23, "heading": "H0",
"wordCount": 5, "expanded": false,
"paraCount": 1, "charCount": 23,
"cursorPos": 0, "wordCount": 5,
"status": "s000000" "paraCount": 1,
"cursorPos": 0
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "e7ded148d6e4a", "name": "A Folder",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "e7ded148d6e4a",
"order": 3, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "A Folder", "order": 3,
"type": "FOLDER", "type": "FOLDER",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000003" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000003"
}
}, },
{ {
"handle": "6a2d6d5f4f401", "name": "Chapter One",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "6a2d6d5f4f401",
"order": 0, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter One", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 12, "heading": "H0",
"wordCount": 3, "expanded": false,
"paraCount": 0, "charCount": 12,
"cursorPos": 215, "wordCount": 3,
"status": "s000001" "paraCount": 0,
"cursorPos": 215
},
"nameAttr": {
"active": true,
"status": "s000001"
}
}, },
{ {
"handle": "636b6aa9b697b", "name": "Making a Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "636b6aa9b697b",
"order": 1, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Making a Scene", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 1199, "heading": "H0",
"wordCount": 216, "expanded": false,
"paraCount": 7, "charCount": 1199,
"cursorPos": 527, "wordCount": 216,
"status": "s000003" "paraCount": 7,
"cursorPos": 527
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "bc0cbd2a407f3", "name": "Another Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "bc0cbd2a407f3",
"order": 2, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Another Scene", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 476, "heading": "H0",
"wordCount": 93, "expanded": false,
"paraCount": 3, "charCount": 476,
"cursorPos": 551, "wordCount": 93,
"status": "s000003" "paraCount": 3,
"cursorPos": 551
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ba8a28a246524", "name": "Interlude",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ba8a28a246524",
"order": 3, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Interlude", "order": 3,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 633, "heading": "H0",
"wordCount": 101, "expanded": false,
"paraCount": 3, "charCount": 633,
"cursorPos": 1238, "wordCount": 101,
"status": "s000006" "paraCount": 3,
"cursorPos": 1238
},
"nameAttr": {
"active": true,
"status": "s000006"
}
}, },
{ {
"handle": "96b68994dfa3d", "name": "A Note on Structure",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "96b68994dfa3d",
"order": 4, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "A Note on Structure", "order": 4,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "NOTE"
"active": false, },
"layout": "NOTE", "metaAttr": {
"charCount": 1692, "heading": "H0",
"wordCount": 313, "expanded": false,
"paraCount": 6, "charCount": 1692,
"cursorPos": 1721, "wordCount": 313,
"status": "s000004" "paraCount": 6,
"cursorPos": 1721
},
"nameAttr": {
"active": false,
"status": "s000004"
}
}, },
{ {
"handle": "88706ddc78b1b", "name": "Chapter Two",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "88706ddc78b1b",
"order": 5, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter Two", "order": 5,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 139, "heading": "H0",
"wordCount": 28, "expanded": false,
"paraCount": 1, "charCount": 139,
"cursorPos": 343, "wordCount": 28,
"status": "s000003" "paraCount": 1,
"cursorPos": 343
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ae7339df26ded", "name": "We Found John!",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ae7339df26ded",
"order": 6, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "We Found John!", "order": 6,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 189, "heading": "H0",
"wordCount": 37, "expanded": false,
"paraCount": 1, "charCount": 189,
"cursorPos": 224, "wordCount": 37,
"status": "s000003" "paraCount": 1,
"cursorPos": 224
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "f6622b4617424", "name": "Characters",
"parent": null, "itemAttr": {
"root": null, "handle": "f6622b4617424",
"order": 1, "parent": null,
"heading": "H0", "root": null,
"label": "Characters", "order": 1,
"type": "ROOT", "type": "ROOT",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "f7e2d9f330615", "name": "Main Characters",
"parent": "f6622b4617424", "itemAttr": {
"root": null, "handle": "f7e2d9f330615",
"order": 0, "parent": "f6622b4617424",
"heading": "H0", "root": null,
"label": "Main Characters", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "14298de4d9524", "name": "John Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "14298de4d9524",
"order": 0, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "John Smith", "order": 0,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"expanded": false, "layout": "NOTE"
"active": true, },
"layout": "NOTE", "metaAttr": {
"charCount": 49, "heading": "H0",
"wordCount": 9, "expanded": false,
"paraCount": 1, "charCount": 49,
"cursorPos": 24, "wordCount": 9,
"import": "i000008" "paraCount": 1,
"cursorPos": 24
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "bb2c23b3c42cc", "name": "Jane Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "bb2c23b3c42cc",
"order": 1, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "Jane Smith", "order": 1,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"expanded": false, "layout": "NOTE"
"active": true, },
"layout": "NOTE", "metaAttr": {
"charCount": 55, "heading": "H0",
"wordCount": 9, "expanded": false,
"paraCount": 1, "charCount": 55,
"cursorPos": 25, "wordCount": 9,
"import": "i000009" "paraCount": 1,
"cursorPos": 25
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "15c4492bd5107", "name": "Locations",
"parent": null, "itemAttr": {
"root": null, "handle": "15c4492bd5107",
"order": 2, "parent": null,
"heading": "H0", "root": null,
"label": "Locations", "order": 2,
"type": "ROOT", "type": "ROOT",
"class": "WORLD", "class": "WORLD"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b3e74dbc1f584", "name": "Earth",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "b3e74dbc1f584",
"order": 0, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Earth", "order": 0,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"expanded": false, "layout": "NOTE"
"active": true, },
"layout": "NOTE", "metaAttr": {
"charCount": 76, "heading": "H0",
"wordCount": 15, "expanded": false,
"paraCount": 1, "charCount": 76,
"cursorPos": 20, "wordCount": 15,
"import": "i00000a" "paraCount": 1,
"cursorPos": 20
},
"nameAttr": {
"active": true,
"import": "i00000a"
}
}, },
{ {
"handle": "f1471bef9f2ae", "name": "Space",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "f1471bef9f2ae",
"order": 1, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Space", "order": 1,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"expanded": false, "layout": "NOTE"
"active": true, },
"layout": "NOTE", "metaAttr": {
"charCount": 115, "heading": "H0",
"wordCount": 24, "expanded": false,
"paraCount": 1, "charCount": 115,
"cursorPos": 133, "wordCount": 24,
"import": "i000008" "paraCount": 1,
"cursorPos": 133
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "5eaea4e8cdee8", "name": "Mars",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "5eaea4e8cdee8",
"order": 2, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Mars", "order": 2,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"expanded": false, "layout": "NOTE"
"active": true, },
"layout": "NOTE", "metaAttr": {
"charCount": 28, "heading": "H0",
"wordCount": 6, "expanded": false,
"paraCount": 1, "charCount": 28,
"cursorPos": 45, "wordCount": 6,
"import": "i000009" "paraCount": 1,
"cursorPos": 45
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "98acd8c76c93a", "name": "Trash",
"parent": null, "itemAttr": {
"root": null, "handle": "98acd8c76c93a",
"order": 3, "parent": null,
"heading": "H0", "root": null,
"label": "Trash", "order": 3,
"type": "ROOT", "type": "ROOT",
"class": "TRASH", "class": "TRASH"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b8136a5a774a0", "name": "Delete Me!",
"parent": "98acd8c76c93a", "itemAttr": {
"root": null, "handle": "b8136a5a774a0",
"order": 0, "parent": "98acd8c76c93a",
"heading": "H0", "root": null,
"label": "Delete Me!", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"expanded": false, "layout": "DOCUMENT"
"active": true, },
"layout": "DOCUMENT", "metaAttr": {
"charCount": 0, "heading": "H0",
"wordCount": 0, "expanded": false,
"paraCount": 0, "charCount": 0,
"cursorPos": 36, "wordCount": 0,
"status": "s000000" "paraCount": 0,
"cursorPos": 36
},
"nameAttr": {
"active": true,
"status": "s000000"
}
} }
] ]
+433 -301
View File
@@ -1,346 +1,478 @@
[ [
{ {
"handle": "7031beac91f75", "name": "Novel",
"parent": null, "itemAttr": {
"root": null, "handle": "7031beac91f75",
"order": 0, "parent": null,
"heading": "H0", "root": null,
"label": "Novel", "order": 0,
"type": "ROOT", "type": "ROOT",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000002" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000002"
}
}, },
{ {
"handle": "53b69b83cdafc", "name": "Title Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "53b69b83cdafc",
"order": 0, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Title Page", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 72, "metaAttr": {
"wordCount": 15, "heading": "H0",
"paraCount": 2, "charCount": 72,
"cursorPos": 78, "wordCount": 15,
"status": "s000002" "paraCount": 2,
"cursorPos": 78
},
"nameAttr": {
"active": true,
"status": "s000002"
}
}, },
{ {
"handle": "974e400180a99", "name": "Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "974e400180a99",
"order": 1, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Page", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 210, "metaAttr": {
"wordCount": 40, "heading": "H0",
"paraCount": 2, "charCount": 210,
"cursorPos": 213, "wordCount": 40,
"status": "s000000" "paraCount": 2,
"cursorPos": 213
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "edca4be2fcaf8", "name": "Part One",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "edca4be2fcaf8",
"order": 2, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Part One", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 23, "metaAttr": {
"wordCount": 5, "heading": "H0",
"paraCount": 1, "charCount": 23,
"cursorPos": 0, "wordCount": 5,
"status": "s000000" "paraCount": 1,
"cursorPos": 0
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "e7ded148d6e4a", "name": "A Folder",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "e7ded148d6e4a",
"order": 3, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "A Folder", "order": 3,
"type": "FOLDER", "type": "FOLDER",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000003" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000003"
}
}, },
{ {
"handle": "6a2d6d5f4f401", "name": "Chapter One",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "6a2d6d5f4f401",
"order": 0, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter One", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 12, "metaAttr": {
"wordCount": 3, "heading": "H0",
"paraCount": 0, "charCount": 12,
"cursorPos": 215, "wordCount": 3,
"status": "s000001" "paraCount": 0,
"cursorPos": 215
},
"nameAttr": {
"active": true,
"status": "s000001"
}
}, },
{ {
"handle": "636b6aa9b697b", "name": "Making a Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "636b6aa9b697b",
"order": 1, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Making a Scene", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 1483, "metaAttr": {
"wordCount": 263, "heading": "H0",
"paraCount": 8, "charCount": 1483,
"cursorPos": 1086, "wordCount": 263,
"status": "s000003" "paraCount": 8,
"cursorPos": 1086
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "bc0cbd2a407f3", "name": "Another Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "bc0cbd2a407f3",
"order": 2, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Another Scene", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 476, "metaAttr": {
"wordCount": 93, "heading": "H0",
"paraCount": 3, "charCount": 476,
"cursorPos": 428, "wordCount": 93,
"status": "s000003" "paraCount": 3,
"cursorPos": 428
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ba8a28a246524", "name": "Interlude",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ba8a28a246524",
"order": 3, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Interlude", "order": 3,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 633, "metaAttr": {
"wordCount": 101, "heading": "H0",
"paraCount": 3, "charCount": 633,
"cursorPos": 1238, "wordCount": 101,
"status": "s000006" "paraCount": 3,
"cursorPos": 1238
},
"nameAttr": {
"active": true,
"status": "s000006"
}
}, },
{ {
"handle": "96b68994dfa3d", "name": "A Note on Structure",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "96b68994dfa3d",
"order": 4, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "A Note on Structure", "order": 4,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": false, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 1692, "metaAttr": {
"wordCount": 313, "heading": "H0",
"paraCount": 6, "charCount": 1692,
"cursorPos": 1721, "wordCount": 313,
"status": "s000004" "paraCount": 6,
"cursorPos": 1721
},
"nameAttr": {
"active": false,
"status": "s000004"
}
}, },
{ {
"handle": "88706ddc78b1b", "name": "Chapter Two",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "88706ddc78b1b",
"order": 5, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter Two", "order": 5,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 139, "metaAttr": {
"wordCount": 28, "heading": "H0",
"paraCount": 1, "charCount": 139,
"cursorPos": 343, "wordCount": 28,
"status": "s000003" "paraCount": 1,
"cursorPos": 343
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ae7339df26ded", "name": "We Found John!",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ae7339df26ded",
"order": 6, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "We Found John!", "order": 6,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 189, "metaAttr": {
"wordCount": 37, "heading": "H0",
"paraCount": 1, "charCount": 189,
"cursorPos": 224, "wordCount": 37,
"status": "s000003" "paraCount": 1,
"cursorPos": 224
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "f6622b4617424", "name": "Characters",
"parent": null, "itemAttr": {
"root": null, "handle": "f6622b4617424",
"order": 1, "parent": null,
"heading": "H0", "root": null,
"label": "Characters", "order": 1,
"type": "ROOT", "type": "ROOT",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "f7e2d9f330615", "name": "Main Characters",
"parent": "f6622b4617424", "itemAttr": {
"root": null, "handle": "f7e2d9f330615",
"order": 0, "parent": "f6622b4617424",
"heading": "H0", "root": null,
"label": "Main Characters", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "14298de4d9524", "name": "John Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "14298de4d9524",
"order": 0, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "John Smith", "order": 0,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 49, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 49,
"cursorPos": 24, "wordCount": 9,
"import": "i000008" "paraCount": 1,
"cursorPos": 24
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "bb2c23b3c42cc", "name": "Jane Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "bb2c23b3c42cc",
"order": 1, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "Jane Smith", "order": 1,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 55, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 55,
"cursorPos": 25, "wordCount": 9,
"import": "i000009" "paraCount": 1,
"cursorPos": 25
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "15c4492bd5107", "name": "Locations",
"parent": null, "itemAttr": {
"root": null, "handle": "15c4492bd5107",
"order": 2, "parent": null,
"heading": "H0", "root": null,
"label": "Locations", "order": 2,
"type": "ROOT", "type": "ROOT",
"class": "WORLD", "class": "WORLD"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b3e74dbc1f584", "name": "Earth",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "b3e74dbc1f584",
"order": 0, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Earth", "order": 0,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 76, "metaAttr": {
"wordCount": 15, "heading": "H0",
"paraCount": 1, "charCount": 76,
"cursorPos": 20, "wordCount": 15,
"import": "i00000a" "paraCount": 1,
"cursorPos": 20
},
"nameAttr": {
"active": true,
"import": "i00000a"
}
}, },
{ {
"handle": "f1471bef9f2ae", "name": "Space",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "f1471bef9f2ae",
"order": 1, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Space", "order": 1,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 115, "metaAttr": {
"wordCount": 24, "heading": "H0",
"paraCount": 1, "charCount": 115,
"cursorPos": 133, "wordCount": 24,
"import": "i000008" "paraCount": 1,
"cursorPos": 133
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "5eaea4e8cdee8", "name": "Mars",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "5eaea4e8cdee8",
"order": 2, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Mars", "order": 2,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 28, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 28,
"cursorPos": 45, "wordCount": 6,
"import": "i000009" "paraCount": 1,
"cursorPos": 45
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "98acd8c76c93a", "name": "Trash",
"parent": null, "itemAttr": {
"root": null, "handle": "98acd8c76c93a",
"order": 3, "parent": null,
"heading": "H0", "root": null,
"label": "Trash", "order": 3,
"type": "ROOT", "type": "ROOT",
"class": "TRASH", "class": "TRASH"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b8136a5a774a0", "name": "Delete Me!",
"parent": "98acd8c76c93a", "itemAttr": {
"root": null, "handle": "b8136a5a774a0",
"order": 0, "parent": "98acd8c76c93a",
"heading": "H0", "root": null,
"label": "Delete Me!", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 30, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 30,
"cursorPos": 36, "wordCount": 6,
"status": "s000000" "paraCount": 1,
"cursorPos": 36
},
"nameAttr": {
"active": true,
"status": "s000000"
}
} }
] ]
+486 -336
View File
@@ -1,387 +1,537 @@
[ [
{ {
"handle": "7031beac91f75", "name": "Novel",
"parent": null, "itemAttr": {
"root": null, "handle": "7031beac91f75",
"order": 0, "parent": null,
"heading": "H0", "root": null,
"label": "Novel", "order": 0,
"type": "ROOT", "type": "ROOT",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000002" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000002"
}
}, },
{ {
"handle": "53b69b83cdafc", "name": "Title Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "53b69b83cdafc",
"order": 0, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Title Page", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 241, "metaAttr": {
"wordCount": 42, "heading": "H0",
"paraCount": 3, "charCount": 241,
"cursorPos": 252, "wordCount": 42,
"status": "s000002" "paraCount": 3,
"cursorPos": 252
},
"nameAttr": {
"active": true,
"status": "s000002"
}
}, },
{ {
"handle": "974e400180a99", "name": "Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "974e400180a99",
"order": 1, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Page", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 125, "metaAttr": {
"wordCount": 26, "heading": "H0",
"paraCount": 2, "charCount": 125,
"cursorPos": 127, "wordCount": 26,
"status": "s000000" "paraCount": 2,
"cursorPos": 127
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "edca4be2fcaf8", "name": "Part One",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "edca4be2fcaf8",
"order": 2, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Part One", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 26, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 26,
"cursorPos": 30, "wordCount": 6,
"status": "s000000" "paraCount": 1,
"cursorPos": 30
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "e7ded148d6e4a", "name": "A Folder",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "e7ded148d6e4a",
"order": 3, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "A Folder", "order": 3,
"type": "FOLDER", "type": "FOLDER",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000003" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000003"
}
}, },
{ {
"handle": "6a2d6d5f4f401", "name": "Chapter One",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "6a2d6d5f4f401",
"order": 0, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter One", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 75, "metaAttr": {
"wordCount": 14, "heading": "H0",
"paraCount": 1, "charCount": 75,
"cursorPos": 279, "wordCount": 14,
"status": "s000001" "paraCount": 1,
"cursorPos": 279
},
"nameAttr": {
"active": true,
"status": "s000001"
}
}, },
{ {
"handle": "636b6aa9b697b", "name": "Making a Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "636b6aa9b697b",
"order": 1, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Making a Scene", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 2429, "metaAttr": {
"wordCount": 432, "heading": "H0",
"paraCount": 14, "charCount": 2429,
"cursorPos": 61, "wordCount": 432,
"status": "s000003" "paraCount": 14,
"cursorPos": 61
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "bc0cbd2a407f3", "name": "Another Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "bc0cbd2a407f3",
"order": 2, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Another Scene", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 476, "metaAttr": {
"wordCount": 93, "heading": "H0",
"paraCount": 3, "charCount": 476,
"cursorPos": 577, "wordCount": 93,
"status": "s000003" "paraCount": 3,
"cursorPos": 577
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ba8a28a246524", "name": "Interlude",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ba8a28a246524",
"order": 3, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Interlude", "order": 3,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 617, "metaAttr": {
"wordCount": 101, "heading": "H0",
"paraCount": 3, "charCount": 617,
"cursorPos": 1137, "wordCount": 101,
"status": "s000000" "paraCount": 3,
"cursorPos": 1137
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "96b68994dfa3d", "name": "A Note on Structure",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "96b68994dfa3d",
"order": 4, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "A Note on Structure", "order": 4,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": false, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 1692, "metaAttr": {
"wordCount": 313, "heading": "H0",
"paraCount": 6, "charCount": 1692,
"cursorPos": 1110, "wordCount": 313,
"status": "s000004" "paraCount": 6,
"cursorPos": 1110
},
"nameAttr": {
"active": false,
"status": "s000004"
}
}, },
{ {
"handle": "88706ddc78b1b", "name": "Chapter Two",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "88706ddc78b1b",
"order": 5, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter Two", "order": 5,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 139, "metaAttr": {
"wordCount": 28, "heading": "H0",
"paraCount": 1, "charCount": 139,
"cursorPos": 343, "wordCount": 28,
"status": "s000003" "paraCount": 1,
"cursorPos": 343
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ae7339df26ded", "name": "We Found John!",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ae7339df26ded",
"order": 6, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "We Found John!", "order": 6,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 189, "metaAttr": {
"wordCount": 37, "heading": "H0",
"paraCount": 1, "charCount": 189,
"cursorPos": 224, "wordCount": 37,
"status": "s000003" "paraCount": 1,
"cursorPos": 224
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "f6622b4617424", "name": "Characters",
"parent": null, "itemAttr": {
"root": null, "handle": "f6622b4617424",
"order": 1, "parent": null,
"heading": "H0", "root": null,
"label": "Characters", "order": 1,
"type": "ROOT", "type": "ROOT",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "f7e2d9f330615", "name": "Main Characters",
"parent": "f6622b4617424", "itemAttr": {
"root": null, "handle": "f7e2d9f330615",
"order": 0, "parent": "f6622b4617424",
"heading": "H0", "root": null,
"label": "Main Characters", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "14298de4d9524", "name": "John Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "14298de4d9524",
"order": 0, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "John Smith", "order": 0,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 49, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 49,
"cursorPos": 24, "wordCount": 9,
"import": "i000008" "paraCount": 1,
"cursorPos": 24
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "bb2c23b3c42cc", "name": "Jane Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "bb2c23b3c42cc",
"order": 1, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "Jane Smith", "order": 1,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 55, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 55,
"cursorPos": 25, "wordCount": 9,
"import": "i000009" "paraCount": 1,
"cursorPos": 25
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "15c4492bd5107", "name": "Locations",
"parent": null, "itemAttr": {
"root": null, "handle": "15c4492bd5107",
"order": 2, "parent": null,
"heading": "H0", "root": null,
"label": "Locations", "order": 2,
"type": "ROOT", "type": "ROOT",
"class": "WORLD", "class": "WORLD"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b3e74dbc1f584", "name": "Earth",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "b3e74dbc1f584",
"order": 0, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Earth", "order": 0,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 76, "metaAttr": {
"wordCount": 15, "heading": "H0",
"paraCount": 1, "charCount": 76,
"cursorPos": 20, "wordCount": 15,
"import": "i00000a" "paraCount": 1,
"cursorPos": 20
},
"nameAttr": {
"active": true,
"import": "i00000a"
}
}, },
{ {
"handle": "f1471bef9f2ae", "name": "Space",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "f1471bef9f2ae",
"order": 1, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Space", "order": 1,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 115, "metaAttr": {
"wordCount": 24, "heading": "H0",
"paraCount": 1, "charCount": 115,
"cursorPos": 133, "wordCount": 24,
"import": "i000008" "paraCount": 1,
"cursorPos": 133
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "5eaea4e8cdee8", "name": "Mars",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "5eaea4e8cdee8",
"order": 2, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Mars", "order": 2,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 28, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 28,
"cursorPos": 45, "wordCount": 6,
"import": "i000009" "paraCount": 1,
"cursorPos": 45
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "6827118336ac1", "name": "Outtakes",
"parent": null, "itemAttr": {
"root": null, "handle": "6827118336ac1",
"order": 3, "parent": null,
"heading": "H0", "root": null,
"label": "Outtakes", "order": 3,
"type": "ROOT", "type": "ROOT",
"class": "ARCHIVE", "class": "ARCHIVE"
"expanded": true, },
"status": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": null
}
}, },
{ {
"handle": "ae9bf3c3ea159", "name": "Scenes",
"parent": "6827118336ac1", "itemAttr": {
"root": null, "handle": "ae9bf3c3ea159",
"order": 0, "parent": "6827118336ac1",
"heading": "H0", "root": null,
"label": "Scenes", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "ARCHIVE", "class": "ARCHIVE"
"expanded": true, },
"status": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": null
}
}, },
{ {
"handle": "8a5deb88c0e97", "name": "Old File",
"parent": "ae9bf3c3ea159", "itemAttr": {
"root": null, "handle": "8a5deb88c0e97",
"order": 0, "parent": "ae9bf3c3ea159",
"heading": "H0", "root": null,
"label": "Old File", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 315, "metaAttr": {
"wordCount": 55, "heading": "H0",
"paraCount": 1, "charCount": 315,
"cursorPos": 322, "wordCount": 55,
"status": "s000003" "paraCount": 1,
"cursorPos": 322
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "98acd8c76c93a", "name": "Trash",
"parent": null, "itemAttr": {
"root": null, "handle": "98acd8c76c93a",
"order": 4, "parent": null,
"heading": "H0", "root": null,
"label": "Trash", "order": 4,
"type": "ROOT", "type": "ROOT",
"class": "TRASH", "class": "TRASH"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b8136a5a774a0", "name": "Delete Me!",
"parent": "98acd8c76c93a", "itemAttr": {
"root": null, "handle": "b8136a5a774a0",
"order": 0, "parent": "98acd8c76c93a",
"heading": "H0", "root": null,
"label": "Delete Me!", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 30, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 30,
"cursorPos": 36, "wordCount": 6,
"status": "s000000" "paraCount": 1,
"cursorPos": 36
},
"nameAttr": {
"active": true,
"status": "s000000"
}
} }
] ]
+486 -336
View File
@@ -1,387 +1,537 @@
[ [
{ {
"handle": "7031beac91f75", "name": "Novel",
"parent": null, "itemAttr": {
"root": null, "handle": "7031beac91f75",
"order": 0, "parent": null,
"heading": "H0", "root": null,
"label": "Novel", "order": 0,
"type": "ROOT", "type": "ROOT",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000002" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000002"
}
}, },
{ {
"handle": "53b69b83cdafc", "name": "Title Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "53b69b83cdafc",
"order": 0, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Title Page", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 93, "metaAttr": {
"wordCount": 19, "heading": "H0",
"paraCount": 2, "charCount": 93,
"cursorPos": 2, "wordCount": 19,
"status": "s000002" "paraCount": 2,
"cursorPos": 2
},
"nameAttr": {
"active": true,
"status": "s000002"
}
}, },
{ {
"handle": "974e400180a99", "name": "Page",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "974e400180a99",
"order": 1, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Page", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 186, "metaAttr": {
"wordCount": 39, "heading": "H0",
"paraCount": 2, "charCount": 186,
"cursorPos": 212, "wordCount": 39,
"status": "s000000" "paraCount": 2,
"cursorPos": 212
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "edca4be2fcaf8", "name": "Part One",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "edca4be2fcaf8",
"order": 2, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "Part One", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 26, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 26,
"cursorPos": 33, "wordCount": 6,
"status": "s000000" "paraCount": 1,
"cursorPos": 33
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "e7ded148d6e4a", "name": "A Folder",
"parent": "7031beac91f75", "itemAttr": {
"root": null, "handle": "e7ded148d6e4a",
"order": 3, "parent": "7031beac91f75",
"heading": "H0", "root": null,
"label": "A Folder", "order": 3,
"type": "FOLDER", "type": "FOLDER",
"class": "NOVEL", "class": "NOVEL"
"expanded": true, },
"status": "s000003" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000003"
}
}, },
{ {
"handle": "6a2d6d5f4f401", "name": "Chapter One",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "6a2d6d5f4f401",
"order": 0, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter One", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 75, "metaAttr": {
"wordCount": 14, "heading": "H0",
"paraCount": 1, "charCount": 75,
"cursorPos": 279, "wordCount": 14,
"status": "s000001" "paraCount": 1,
"cursorPos": 279
},
"nameAttr": {
"active": true,
"status": "s000001"
}
}, },
{ {
"handle": "636b6aa9b697b", "name": "Making a Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "636b6aa9b697b",
"order": 1, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Making a Scene", "order": 1,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 2429, "metaAttr": {
"wordCount": 432, "heading": "H0",
"paraCount": 14, "charCount": 2429,
"cursorPos": 62, "wordCount": 432,
"status": "s000003" "paraCount": 14,
"cursorPos": 62
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "bc0cbd2a407f3", "name": "Another Scene",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "bc0cbd2a407f3",
"order": 2, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Another Scene", "order": 2,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 476, "metaAttr": {
"wordCount": 93, "heading": "H0",
"paraCount": 3, "charCount": 476,
"cursorPos": 577, "wordCount": 93,
"status": "s000003" "paraCount": 3,
"cursorPos": 577
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ba8a28a246524", "name": "Interlude",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ba8a28a246524",
"order": 3, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Interlude", "order": 3,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 617, "metaAttr": {
"wordCount": 101, "heading": "H0",
"paraCount": 3, "charCount": 617,
"cursorPos": 4, "wordCount": 101,
"status": "s000000" "paraCount": 3,
"cursorPos": 4
},
"nameAttr": {
"active": true,
"status": "s000000"
}
}, },
{ {
"handle": "96b68994dfa3d", "name": "A Note on Structure",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "96b68994dfa3d",
"order": 4, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "A Note on Structure", "order": 4,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": false, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 1692, "metaAttr": {
"wordCount": 313, "heading": "H0",
"paraCount": 6, "charCount": 1692,
"cursorPos": 1110, "wordCount": 313,
"status": "s000004" "paraCount": 6,
"cursorPos": 1110
},
"nameAttr": {
"active": false,
"status": "s000004"
}
}, },
{ {
"handle": "88706ddc78b1b", "name": "Chapter Two",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "88706ddc78b1b",
"order": 5, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "Chapter Two", "order": 5,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 139, "metaAttr": {
"wordCount": 28, "heading": "H0",
"paraCount": 1, "charCount": 139,
"cursorPos": 343, "wordCount": 28,
"status": "s000003" "paraCount": 1,
"cursorPos": 343
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "ae7339df26ded", "name": "We Found John!",
"parent": "e7ded148d6e4a", "itemAttr": {
"root": null, "handle": "ae7339df26ded",
"order": 6, "parent": "e7ded148d6e4a",
"heading": "H0", "root": null,
"label": "We Found John!", "order": 6,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 189, "metaAttr": {
"wordCount": 37, "heading": "H0",
"paraCount": 1, "charCount": 189,
"cursorPos": 224, "wordCount": 37,
"status": "s000003" "paraCount": 1,
"cursorPos": 224
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "f6622b4617424", "name": "Characters",
"parent": null, "itemAttr": {
"root": null, "handle": "f6622b4617424",
"order": 1, "parent": null,
"heading": "H0", "root": null,
"label": "Characters", "order": 1,
"type": "ROOT", "type": "ROOT",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "f7e2d9f330615", "name": "Main Characters",
"parent": "f6622b4617424", "itemAttr": {
"root": null, "handle": "f7e2d9f330615",
"order": 0, "parent": "f6622b4617424",
"heading": "H0", "root": null,
"label": "Main Characters", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "CHARACTER", "class": "CHARACTER"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "14298de4d9524", "name": "John Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "14298de4d9524",
"order": 0, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "John Smith", "order": 0,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 49, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 49,
"cursorPos": 24, "wordCount": 9,
"import": "i000008" "paraCount": 1,
"cursorPos": 24
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "bb2c23b3c42cc", "name": "Jane Smith",
"parent": "f7e2d9f330615", "itemAttr": {
"root": null, "handle": "bb2c23b3c42cc",
"order": 1, "parent": "f7e2d9f330615",
"heading": "H0", "root": null,
"label": "Jane Smith", "order": 1,
"type": "FILE", "type": "FILE",
"class": "CHARACTER", "class": "CHARACTER",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 55, "metaAttr": {
"wordCount": 9, "heading": "H0",
"paraCount": 1, "charCount": 55,
"cursorPos": 25, "wordCount": 9,
"import": "i000009" "paraCount": 1,
"cursorPos": 25
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "15c4492bd5107", "name": "Locations",
"parent": null, "itemAttr": {
"root": null, "handle": "15c4492bd5107",
"order": 2, "parent": null,
"heading": "H0", "root": null,
"label": "Locations", "order": 2,
"type": "ROOT", "type": "ROOT",
"class": "WORLD", "class": "WORLD"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b3e74dbc1f584", "name": "Earth",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "b3e74dbc1f584",
"order": 0, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Earth", "order": 0,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 76, "metaAttr": {
"wordCount": 15, "heading": "H0",
"paraCount": 1, "charCount": 76,
"cursorPos": 20, "wordCount": 15,
"import": "i00000a" "paraCount": 1,
"cursorPos": 20
},
"nameAttr": {
"active": true,
"import": "i00000a"
}
}, },
{ {
"handle": "f1471bef9f2ae", "name": "Space",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "f1471bef9f2ae",
"order": 1, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Space", "order": 1,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 115, "metaAttr": {
"wordCount": 24, "heading": "H0",
"paraCount": 1, "charCount": 115,
"cursorPos": 133, "wordCount": 24,
"import": "i000008" "paraCount": 1,
"cursorPos": 133
},
"nameAttr": {
"active": true,
"import": "i000008"
}
}, },
{ {
"handle": "5eaea4e8cdee8", "name": "Mars",
"parent": "15c4492bd5107", "itemAttr": {
"root": null, "handle": "5eaea4e8cdee8",
"order": 2, "parent": "15c4492bd5107",
"heading": "H0", "root": null,
"label": "Mars", "order": 2,
"type": "FILE", "type": "FILE",
"class": "WORLD", "class": "WORLD",
"active": true, "layout": "NOTE"
"layout": "NOTE", },
"charCount": 28, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 28,
"cursorPos": 45, "wordCount": 6,
"import": "i000009" "paraCount": 1,
"cursorPos": 45
},
"nameAttr": {
"active": true,
"import": "i000009"
}
}, },
{ {
"handle": "6827118336ac1", "name": "Archive",
"parent": null, "itemAttr": {
"root": null, "handle": "6827118336ac1",
"order": 3, "parent": null,
"heading": "H0", "root": null,
"label": "Archive", "order": 3,
"type": "ROOT", "type": "ROOT",
"class": "ARCHIVE", "class": "ARCHIVE"
"expanded": true, },
"status": "s000000" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000000"
}
}, },
{ {
"handle": "ae9bf3c3ea159", "name": "Scenes",
"parent": "6827118336ac1", "itemAttr": {
"root": null, "handle": "ae9bf3c3ea159",
"order": 0, "parent": "6827118336ac1",
"heading": "H0", "root": null,
"label": "Scenes", "order": 0,
"type": "FOLDER", "type": "FOLDER",
"class": "ARCHIVE", "class": "ARCHIVE"
"expanded": true, },
"status": "s000000" "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"status": "s000000"
}
}, },
{ {
"handle": "8a5deb88c0e97", "name": "Old File",
"parent": "ae9bf3c3ea159", "itemAttr": {
"root": null, "handle": "8a5deb88c0e97",
"order": 0, "parent": "ae9bf3c3ea159",
"heading": "H0", "root": null,
"label": "Old File", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 314, "metaAttr": {
"wordCount": 55, "heading": "H0",
"paraCount": 1, "charCount": 314,
"cursorPos": 322, "wordCount": 55,
"status": "s000003" "paraCount": 1,
"cursorPos": 322
},
"nameAttr": {
"active": true,
"status": "s000003"
}
}, },
{ {
"handle": "98acd8c76c93a", "name": "Trash",
"parent": null, "itemAttr": {
"root": null, "handle": "98acd8c76c93a",
"order": 4, "parent": null,
"heading": "H0", "root": null,
"label": "Trash", "order": 4,
"type": "ROOT", "type": "ROOT",
"class": "TRASH", "class": "TRASH"
"expanded": true, },
"import": null "metaAttr": {
"heading": "H0",
"expanded": true
},
"nameAttr": {
"import": null
}
}, },
{ {
"handle": "b8136a5a774a0", "name": "Delete Me!",
"parent": "98acd8c76c93a", "itemAttr": {
"root": null, "handle": "b8136a5a774a0",
"order": 0, "parent": "98acd8c76c93a",
"heading": "H0", "root": null,
"label": "Delete Me!", "order": 0,
"type": "FILE", "type": "FILE",
"class": "NOVEL", "class": "NOVEL",
"active": true, "layout": "DOCUMENT"
"layout": "DOCUMENT", },
"charCount": 30, "metaAttr": {
"wordCount": 6, "heading": "H0",
"paraCount": 1, "charCount": 30,
"cursorPos": 36, "wordCount": 6,
"status": "s000000" "paraCount": 1,
"cursorPos": 36
},
"nameAttr": {
"active": true,
"status": "s000000"
}
} }
] ]
+69 -51
View File
@@ -509,23 +509,29 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
# File # File
theItem = NWItem(theProject) theItem = NWItem(theProject)
assert theItem.unpack({ assert theItem.unpack({
"label": "A File", "name": "A File",
"handle": "0000000000003", "itemAttr": {
"parent": "0000000000002", "handle": "0000000000003",
"root": "0000000000001", "parent": "0000000000002",
"order": 1, "root": "0000000000001",
"type": "FILE", "order": 1,
"class": "NOVEL", "type": "FILE",
"layout": "DOCUMENT", "class": "NOVEL",
"expanded": True, "layout": "DOCUMENT",
"status": None, },
"import": None, "metaAttr": {
"heading": "H1", "expanded": True,
"charCount": 100, "heading": "H1",
"wordCount": 20, "charCount": 100,
"paraCount": 2, "wordCount": 20,
"cursorPos": 50, "paraCount": 2,
"active": False, "cursorPos": 50,
},
"nameAttr": {
"status": None,
"import": None,
"active": False,
},
}) is True }) is True
assert theItem.itemName == "A File" assert theItem.itemName == "A File"
@@ -575,23 +581,29 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
# Folder # Folder
theItem = NWItem(theProject) theItem = NWItem(theProject)
assert theItem.unpack({ assert theItem.unpack({
"label": "A Folder", "name": "A Folder",
"handle": "0000000000003", "itemAttr": {
"parent": "0000000000002", "handle": "0000000000003",
"root": "0000000000001", "parent": "0000000000002",
"order": 1, "root": "0000000000001",
"type": "FOLDER", "order": 1,
"class": "NOVEL", "type": "FOLDER",
"layout": "DOCUMENT", "class": "NOVEL",
"expanded": True, "layout": "DOCUMENT",
"status": "", },
"import": "", "metaAttr": {
"heading": "H1", "expanded": True,
"charCount": 100, "heading": "H1",
"wordCount": 20, "charCount": 100,
"paraCount": 2, "wordCount": 20,
"cursorPos": 50, "paraCount": 2,
"active": True, "cursorPos": 50,
},
"nameAttr": {
"status": "",
"import": "",
"active": True,
}
}) is True }) is True
assert theItem.itemName == "A Folder" assert theItem.itemName == "A Folder"
@@ -634,23 +646,29 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
# Root # Root
theItem = NWItem(theProject) theItem = NWItem(theProject)
assert theItem.unpack({ assert theItem.unpack({
"label": "A Novel", "name": "A Novel",
"handle": "0000000000003", "itemAttr": {
"parent": "0000000000002", "handle": "0000000000003",
"root": "0000000000001", "parent": "0000000000002",
"order": 1, "root": "0000000000001",
"type": "ROOT", "order": 1,
"class": "NOVEL", "type": "ROOT",
"layout": "DOCUMENT", "class": "NOVEL",
"expanded": True, "layout": "DOCUMENT",
"status": None, },
"import": None, "metaAttr": {
"heading": "H1", "expanded": True,
"charCount": 100, "heading": "H1",
"wordCount": 20, "charCount": 100,
"paraCount": 2, "wordCount": 20,
"cursorPos": 50, "paraCount": 2,
"active": True, "cursorPos": 50,
},
"nameAttr": {
"status": None,
"import": None,
"active": True,
},
}) is True }) is True
assert theItem.itemName == "A Novel" assert theItem.itemName == "A Novel"
+22 -12
View File
@@ -19,11 +19,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import json
import os import os
import json
import pytest import pytest
import shutil
from shutil import copyfile
from datetime import datetime from datetime import datetime
from mock import causeOSError from mock import causeOSError
@@ -47,6 +47,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, filesDir, fncDir, outDir, refDir
xmlFile = os.path.join(fncDir, "nwProject-1.4.nwx") xmlFile = os.path.join(fncDir, "nwProject-1.4.nwx")
bakFile = os.path.join(fncDir, "nwProject-1.4.bak") bakFile = os.path.join(fncDir, "nwProject-1.4.bak")
outFile = os.path.join(fncDir, "nwProject.nwx") outFile = os.path.join(fncDir, "nwProject.nwx")
tstFile = os.path.join(outDir, "ProjectXML_ReadCurrent.nwx")
xmlReader = ProjectXMLReader(xmlFile) xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION assert xmlReader.state == XMLReadState.NO_ACTION
@@ -125,7 +126,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, filesDir, fncDir, outDir, refDir
content = [] content = []
# Parse a valid, complete file # Parse a valid, complete file
shutil.copy(refFile, xmlFile) copyfile(refFile, xmlFile)
assert xmlReader.read(data, content) is True assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.PARSED_OK assert xmlReader.state == XMLReadState.PARSED_OK
assert xmlReader.xmlRoot == "novelWriterXML" assert xmlReader.xmlRoot == "novelWriterXML"
@@ -231,7 +232,8 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, filesDir, fncDir, outDir, refDir
# Successful save (should be twice) # Successful save (should be twice)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
assert cmpFiles(outFile, xmlFile) copyfile(outFile, tstFile)
assert cmpFiles(tstFile, xmlFile)
# END Test testCoreProjectXML_ReadCurrent # END Test testCoreProjectXML_ReadCurrent
@@ -243,7 +245,7 @@ def testCoreProjectXML_ReadLegacy10(filesDir, fncDir, outDir, refDir, mockRnd):
refFile = os.path.join(filesDir, "nwProject-1.0.nwx") refFile = os.path.join(filesDir, "nwProject-1.0.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.0.nwx") xmlFile = os.path.join(fncDir, "nwProject-1.0.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx") outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile) copyfile(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile) xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION assert xmlReader.state == XMLReadState.NO_ACTION
@@ -369,8 +371,10 @@ def testCoreProjectXML_ReadLegacy10(filesDir, fncDir, outDir, refDir, mockRnd):
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir) xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
testFile = os.path.join(outDir, "projectXML_ReadLegacy10.nwx")
compFile = os.path.join(refDir, "projectXML_ReadLegacy10.nwx") compFile = os.path.join(refDir, "projectXML_ReadLegacy10.nwx")
assert cmpFiles(outFile, compFile) copyfile(outFile, testFile)
assert cmpFiles(testFile, compFile)
# END Test testCoreProjectXML_ReadLegacy10 # END Test testCoreProjectXML_ReadLegacy10
@@ -382,7 +386,7 @@ def testCoreProjectXML_ReadLegacy11(filesDir, fncDir, outDir, refDir, mockRnd):
refFile = os.path.join(filesDir, "nwProject-1.1.nwx") refFile = os.path.join(filesDir, "nwProject-1.1.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.1.nwx") xmlFile = os.path.join(fncDir, "nwProject-1.1.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx") outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile) copyfile(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile) xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION assert xmlReader.state == XMLReadState.NO_ACTION
@@ -508,8 +512,10 @@ def testCoreProjectXML_ReadLegacy11(filesDir, fncDir, outDir, refDir, mockRnd):
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir) xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
testFile = os.path.join(outDir, "projectXML_ReadLegacy11.nwx")
compFile = os.path.join(refDir, "projectXML_ReadLegacy11.nwx") compFile = os.path.join(refDir, "projectXML_ReadLegacy11.nwx")
assert cmpFiles(outFile, compFile) copyfile(outFile, testFile)
assert cmpFiles(testFile, compFile)
# END Test testCoreProjectXML_ReadLegacy11 # END Test testCoreProjectXML_ReadLegacy11
@@ -521,7 +527,7 @@ def testCoreProjectXML_ReadLegacy12(filesDir, fncDir, outDir, refDir, mockRnd):
refFile = os.path.join(filesDir, "nwProject-1.2.nwx") refFile = os.path.join(filesDir, "nwProject-1.2.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.2.nwx") xmlFile = os.path.join(fncDir, "nwProject-1.2.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx") outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile) copyfile(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile) xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION assert xmlReader.state == XMLReadState.NO_ACTION
@@ -650,8 +656,10 @@ def testCoreProjectXML_ReadLegacy12(filesDir, fncDir, outDir, refDir, mockRnd):
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir) xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
testFile = os.path.join(outDir, "projectXML_ReadLegacy12.nwx")
compFile = os.path.join(refDir, "projectXML_ReadLegacy12.nwx") compFile = os.path.join(refDir, "projectXML_ReadLegacy12.nwx")
assert cmpFiles(outFile, compFile) copyfile(outFile, testFile)
assert cmpFiles(testFile, compFile)
# END Test testCoreProjectXML_ReadLegacy12 # END Test testCoreProjectXML_ReadLegacy12
@@ -663,7 +671,7 @@ def testCoreProjectXML_ReadLegacy13(filesDir, fncDir, outDir, refDir, mockRnd):
refFile = os.path.join(filesDir, "nwProject-1.3.nwx") refFile = os.path.join(filesDir, "nwProject-1.3.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.3.nwx") xmlFile = os.path.join(fncDir, "nwProject-1.3.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx") outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile) copyfile(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile) xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION assert xmlReader.state == XMLReadState.NO_ACTION
@@ -792,7 +800,9 @@ def testCoreProjectXML_ReadLegacy13(filesDir, fncDir, outDir, refDir, mockRnd):
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp()) timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir) xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
testFile = os.path.join(outDir, "projectXML_ReadLegacy13.nwx")
compFile = os.path.join(refDir, "projectXML_ReadLegacy13.nwx") compFile = os.path.join(refDir, "projectXML_ReadLegacy13.nwx")
assert cmpFiles(outFile, compFile) copyfile(outFile, testFile)
assert cmpFiles(testFile, compFile)
# END Test testCoreProjectXML_ReadLegacy13 # END Test testCoreProjectXML_ReadLegacy13