1
0
Fork 0
mirror of https://github.com/Oreolek/gamebookformat.git synced 2024-05-08 20:18:19 +03:00

Require -x to use tags not in a builtin hardcoded list.

This commit is contained in:
Pelle Nilsson 2014-12-22 15:54:09 +01:00
parent 2176aef22f
commit f1fd536995
5 changed files with 63 additions and 7 deletions

View file

@ -0,0 +1 @@
-x

View file

@ -70,8 +70,9 @@ def format_gamebook(inputfilenames,
shuffle, shuffle,
includetags, includetags,
excludetags, excludetags,
mapfilenames): mapfilenames,
output_format = make_output(outputfilename, templatedirs) allow_unknown_tags):
output_format = make_output(outputfilename, allow_unknown_tags, templatedirs)
book = sections.Book(make_bookid(outputfilename), includetags, excludetags) book = sections.Book(make_bookid(outputfilename), includetags, excludetags)
for inputfilename in inputfilenames: for inputfilename in inputfilenames:
parse_file_to_book(open(inputfilename, 'r'), output_format.name, book) parse_file_to_book(open(inputfilename, 'r'), output_format.name, book)
@ -153,11 +154,12 @@ def add_section_to_book(book, name, text, intro_section=False,
if number: if number:
book.force_section_nr(name, number) book.force_section_nr(name, number)
def make_output(outputfilename, templatedirs): def make_output(outputfilename, allow_unknown_tags, templatedirs):
for of in OUTPUT_FORMATS: for of in OUTPUT_FORMATS:
extension = of['extension'] extension = of['extension']
if outputfilename.endswith('.' + extension): if outputfilename.endswith('.' + extension):
return OutputFormat(templates.Templates(templatedirs, extension), return OutputFormat(templates.Templates(templatedirs, extension),
allow_unknown_tags,
of['quote'], extension.upper()) of['quote'], extension.upper())
raise Exception("Unsupported or unknown output format for %s." raise Exception("Unsupported or unknown output format for %s."
% outputfilename) % outputfilename)
@ -220,6 +222,8 @@ if __name__ == '__main__':
help='do not shuffle sections') help='do not shuffle sections')
ap.add_argument('-m', '--map-file', metavar='F', dest='mapfiles', ap.add_argument('-m', '--map-file', metavar='F', dest='mapfiles',
action='append', help='number map file') action='append', help='number map file')
ap.add_argument('-x', '--allow-unknown', action='store_true',
dest='allow_unknown_tags')
args = ap.parse_args() args = ap.parse_args()
templatedirs = ['templates', templatedirs = ['templates',
os.path.join(os.path.dirname(sys.argv[0]), 'templates')] os.path.join(os.path.dirname(sys.argv[0]), 'templates')]
@ -237,4 +241,5 @@ if __name__ == '__main__':
args.shuffle, args.shuffle,
args.includetags or [], args.includetags or [],
args.excludetags or [], args.excludetags or [],
args.mapfiles or []) args.mapfiles or [],
args.allow_unknown_tags)

View file

@ -2,14 +2,41 @@ import os
import os.path import os.path
import sys import sys
# Hardcoded list of tags allowed without -x flag.
BUILTIN_TAGS = ['add',
'atleast',
'b',
'collect',
'cost',
'count',
'dec',
'drop',
'found',
'has',
'hasnot',
'img',
'inc',
'init',
'lessthan',
'min',
'morethan',
'random',
'set',
'take',
'trade',
'xor']
NOT_BUILTIN_TAG_MESSAGE = "Unknown tag %s not allowed without -x flag."
COUNTER_CREATE_TAG = 'count' COUNTER_CREATE_TAG = 'count'
COUNTER_USE_TAGS = set(['set', 'inc', 'dec', 'min', COUNTER_USE_TAGS = set(['set', 'inc', 'dec', 'min',
'lessthan', 'morethan', 'atleast']) 'lessthan', 'morethan', 'atleast'])
class OutputFormat (object): class OutputFormat (object):
"Handles book output. Big FIXME required to make sense." "Handles book output. Big FIXME required to make sense."
def __init__(self, templates, quote, name): def __init__(self, templates, allow_unknown_tags, quote, name):
self.templates = templates self.templates = templates
self.allow_unknown_tags = allow_unknown_tags
self.format_quote = quote self.format_quote = quote
self.name = name self.name = name
self.counter_names = {} self.counter_names = {}
@ -112,6 +139,8 @@ class OutputFormat (object):
tag = section.text[tag_start+1:tag_end].strip() tag = section.text[tag_start+1:tag_end].strip()
tagparts = tag.split() tagparts = tag.split()
tagname = tagparts[0] tagname = tagparts[0]
if not self.allow_unknown_tags and tagname not in BUILTIN_TAGS:
raise Exception(NOT_BUILTIN_TAG_MESSAGE % tagname)
end_tag_start = section.text.find('[', tag_end) end_tag_start = section.text.find('[', tag_end)
if (not end_tag_start > tag_end if (not end_tag_start > tag_end
and section.text[end_tag_start].startswith('[/' + tagname and section.text[end_tag_start].startswith('[/' + tagname

View file

@ -19,6 +19,7 @@ gamebook on paper or a screen (or for debugging it).
: -o D, --option D add template override options dir : -o D, --option D add template override options dir
: -S, --no-shuffle do not shuffle sections : -S, --no-shuffle do not shuffle sections
: -m F, --map-file F number map file : -m F, --map-file F number map file
: -x, --allow_unknown allow unknown tags
** Supported Output Formats ** Supported Output Formats
| Name | Extension | Description | | Name | Extension | Description |
@ -56,6 +57,26 @@ todo (or substitute whatever other tag(s) you are interested in).
| static | html | Remove script link from HTML output. | | static | html | Remove script link from HTML output. |
| twine2 | html | Generate story that can be imported to [[http://twinery.org/2/#stories][Twine 2]] | | twine2 | html | Generate story that can be imported to [[http://twinery.org/2/#stories][Twine 2]] |
** Adding Custom Templates
Any of the built-in templates can be overridden easily. New
tags can be added that can generate any output you need for
different file formats. However to add a tag that is not
included in the default distribution the command-line
flat *-x* is required to tell gamebookformat that you
know what you are doing. Otherwise when an unknown
tag is encountered you get an ugly error message.
The reason for making it moderately difficult to add
a new tag is that all the builtin tags have been
choosen to work reasonably well in anything from
static printed gamebooks to dynamic digital app
gamebooks. Anyone thinking of adding a new tag
should think twice about how having that tag might
mean that some output formats are not longer useful.
Sticking to the default tags and not overriding them
to do bad things ensures that your gamebooks are
still readable and playable in all supported
output formats. (The process of adding new templates and new output
formats really should be better documented.)
** Styles and Scripts ** Styles and Scripts
Generated *html* files use the included *gamebookformat.css* for Generated *html* files use the included *gamebookformat.css* for
styling and *gamebookformat.js* for scripting (except with the styling and *gamebookformat.js* for scripting (except with the

View file

@ -20,10 +20,10 @@ class TestOutputFormat(TestCase):
pass pass
def test_create(self): def test_create(self):
of = output.OutputFormat(FakeTemplates({}), "TEST", str) of = output.OutputFormat(FakeTemplates({}), "TEST", False, str)
def test_format_begin(self): def test_format_begin(self):
of = output.OutputFormat(FakeTemplates({'begin' : 'b %(max)d'}), "TEST", str) of = output.OutputFormat(FakeTemplates({'begin' : 'b %(max)d'}), "TEST", False, str)
self.assertEqual(of.format_begin({'max' : 2}), 'b 2') self.assertEqual(of.format_begin({'max' : 2}), 'b 2')
class TestReferenceFormatter(TestCase): class TestReferenceFormatter(TestCase):