Open main menu

Gramps β

Changes

Libhtml

8,363 bytes added, 03:31, 18 September 2015
no edit summary
=== '''Html class ===''' description and user guide.
This page contains a description of and user's guide for the The Html class. This class is useful for the preparation of Html pages and is found in the srcfollowing directory:* [https://github.com/gramps-project/gramps/tree/master/gramps/plugins/lib directory.master/gramps/plugins/lib/]
== Standard XHTML Template ==
When actually writing an XHTML page from Python, you need to keep track of where you are so that you can properly close each element that you open. With a complicated document, this is tricky and fragile. This is what prompted me to write an Html class that can manage the trickiness and hopefully increase the robustness of the result. The idea is to store the page data in a series of nested lists then provide the means to extract them in proper order (basically a insertion-order tree traversal) for output. Let's start with an example. A similar, standard template can be generated with the Html class like this:
1. from libhtml import Html, _XMLNS
2. _LANG = 'xml:lang="en-CA" lang="en-CA"'
4. _META2 = 'http-equiv="Content-Style-Type" content="text/css"'
5. p = Html('html', indent=False, xmlns=html._XMLNS, attr=_LANG)
6. p.addXML()
7. p.addDOCTYPE()
5. Instantiate a new Html object. The first, positional argument is the tag type, which defaults to 'html'. The two keyword arguments are not specifically recognized by the constructor and are passed into the tag that is generated as attributes. For example, if I just say:
>>> print Html('html', xmlns=html._XMLNS, attr=_LANG)
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-CA" lang="en-CA"></html>
>>>
You would do the same thing with other attributes, such as "xml:lang" Practically speaking, there are currently only a handful of keywords that conflict with Python keywords or are syntactically invalid in Python.
 == Specifications Using the Html class ==
The Html class extends the built-in "list" class and so any methods you can use on a list will work with Html as well. The methods described below are those that have been specially enhanced to support the generation of HTML documents:
Html(tag='html', [arg1,...argn,]
attr='',
indent=FalseTrue,
inline=False,
close=True,
;indent
:Indent this object with respect to its parent, if parent exists. Default = True. Note that the indentation is cumulative. That is, the indentation of this object will be the sum of its indentation and that of its parent, if the parent is indented. This is useful for producing human-readable output though it should have no effect on browsers rendering the page.  :Options: :;indent=True (Default)::Indent the contents of this object with respect to its parent. :;indent=False::Do not indent the contents of this object with respect to its parent:;indent=None::Reset base indentation to the beginning of the line for this object and its children. Note that child objects will continue to obey the indentation specified when they are instantiated, but since they are relative to their parent, their indentation will be relative to the beginning of the line.
;inline
:Instruct the write() method to output the tag and all its contents (including any nested elements) as one string. Default is False which means call the output method once for the beginning and ending tags and once for each element contained therein, including sub-elements.
 
:Options:
 
:;inline=False (Default)
::Do not write this object and its children as a single string.
:;inline=True
::Write this element and all its contents (including any nested elements) as one string.
;close
:This element should be closed normally (e.g. <tag>...</tag>). Default is True.
 
:Options:
 
:;close=True (default)
::Close this element normally (e.g. <tag>...</tag>)
:;close=False
::Do not close this element normally. Use "self-close" instead (e.g. <tag.../>). Note that this is automatic for all tags that are defined in the standard to be self-closing.
;keyword1=arg1...
=== Extending your Html objects ===
The Html class overloads the typical list methods append(), extend(), "+" and "+=" to enable you to easily build up your page. All of the following examples are validuses of Html objects. Try them in an interactive Python session and use <object>.write() to view the results:
page foo = Html(indent=False) bar = Html('head') page foobar = foo + bar bar += Html('headmeta') page bar.extend('meta',bob="your uncle") bar.append('useless text in header') opa = Html('body') page foobar += opa opa = page opa + Html('div', id="my div", class_="my class") page.append("a random string) page opa += [ 'text beginning', Html('a','imbedded href',href="http://w3c.org"), "text following" ] p = Html('p')+ ['the quality of mercy is not strained','it falleth as the gentle dew from heaven'] '''Note:''' The Html class does not implement list operations by index (e.g. list[1]) or slice (e.g. list[1:2]). Use these at your own risk as they may cause unpredictable results.
Of course, if you like you can add preformatted tags:
page += '<&lt;ul><&gt;&lt;li>&gt;one<&lt;/li><&gt;&lt;li>&gt;two<&lt;/li><&gt;&lt;/ul>&gt;'
since the object derives from list, but then you are responsible for properly closing your tags.
ButHowever, if the tag argument begins with a "<", the constructor assumes that it is a preformatted tag:
page += Html('<title>My Title</title>')
newtitle = Html('title','new title')
head.remove(title)
page -=- head
The Html class also overloads the list method replace() allowing you to replace elements. For example:
The Html class adds a new method, write() which is to be used when you are ready to output your finished page. If called with no parameters, it simply prints the contents of the page on your terminal. If called with an argument, that argument must be the name of a function that is to receive the data to be output. For example:
page.write(lambda data:sys.stdout.write(data + "\n")
Building standard DOCTYPE and XML declarations:
You can use these to build your own DOCTYPE statements. The last one is useful when starting a new document:
page = Html(xmlns=_XMLNS) ''Note:'' You must explicitly import these constants from the libhtml module. For example:  from libhtml import _XMLMS === Using the Html class as a context manager === As of Python version 2.5, a new statement has been added to enable you to program within a given context. The "with" statement accomplishes this for you. The Html class supports being used in the "with" statement. That means that you can write code like:  with Html('table') as table: with Html('tbody') as tbody: table += tbody with Html('tr') as trow: tbody += trow with Html('td') as tcell: trow += tcell tcell += 'foobar' which has the advantage that the indentation structure of your program will match the indentation structure of the htmlfile produced by the write() method. Note: If you want to use the "with" statement in programs that may run under Python version 2.5, you must include the following as the first executable statement of your module:  from __future__ import with_statement == Recommended approach == The Html class is versatile and there are many ways to use it to produce an HTML page. You can make your life easier, however, if you organize your work as described in this section. === Use Html._XMLNSpage to begin a new page === The Html.page function takes care of the HTML boilerplate that is needed for every valid HTML page. Start off like this:  page, head, body = Html.page(title="My title')
You will then have three Html objects to use for the rest of your work. (Insert your own title text as desired.)
=== The Html.page function Add additional tags to the header ===
The Html class also contains several static functions, including HtmlMany pages require additional tags to be added to the <head> .page, which is useful when starting a new page object.. </head> section. It takes just three parametersThese can easily be added like this:
head += Html('meta', name="author", content="Bill Shakespeare") head += Html('link', media="screen" href="../my.css" type="text/css" rel="stylesheet" === Build up the page body by divisions === Try to design the body of your document as a logical arrangement of divisions that refer to CSS styles. Instantiate each division separately:  div1 = Html('div', id="first_division", class_='div1class') div2 = Html('div', id="second_division", class_='div2class') When you have designed your divisions, add them to the page body:  body += div1 body += div2 Or, if you have man divisions, you can add them all at once like this:  body += [div1, div2] '''Note:''' by adding them as a list, the divisions are siblings within the body.  === Add content to your divisions === If you are adding content that is more or less fixed, just add it directly:  div1 += Html('p','division 1 content') div2 += Html('p','division 2 content') If you are adding content that you will need to build up, first instantiate a new object and add it to your division:  table1 = Html('table') div1 += table === Write out your completed page === When all content has been added to your page, write it out:  page.write(myoutputmethod()) == Static Methods == The Html class contains several static methods which perform simple operations that are needed for most HTML pages. === Html.head === Html.head generates a HTML <head>...</head> object, with <meta.../> statements required by the XHTML standard. It takes three parameters: ;title :Specifies the title that is to appear in the browser titlebar. It is inserted inside the tags <head><title>...</title></head>. Default is "Title". ;encoding :Specifies the encoding to be used in the page. Default is "utf-8". ;lang:Specifies a language code for the content of the page. Default is "en". Html.head returns an Html object reference to the newly-built object. === Html.html === Html.html generates a basic HTML <html...></html> object with standard attributes. It takes two parameters: ;xmlns:a string containing the URL to the XML namespace definition. Default is "http://www.w3.org/1999/xhtml" ;lang:Specifies a language code for the content of the page. Default is "en". Html.html returns an Html object reference to the newly-built object. === Html.doctype === Html.doctype builds and returns a string containing a standard DOCTYPE statement. It takes three parameters: ;name:name of this DOCTYPE. Default is "html" which matches the XHTML standard. ;public:characterization of this DOCTYPE. Default is "PUBLIC" which matches the XHTML standard. ;external_id:external id of this DOCTYPE. Default is   '"-//W3C//DTD XHTML 1.0 Strict//EN"\n' \ '\t"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"' which matches the XHTML standard. '''Note:''' the external id may be overridden with any of the constants defined by the Html class as described earlier. === Html.xmldecl === Html.xmldecl builds a standard XML declaration which should be the first line in an HTML document according to the standard. It takes three parameters: ;version:version number. Defaults to "1.0";encoding:encoding method. Detauls to "UTF-8";standalone:characterization of this declaration. Defaults to "no" === Html.page === Html.page is useful when starting a new page object. It uses the previously-defined static methods and builds three Html objects representing the whole document (that is, the entire page), the <head> section and the <body> section. Html.page takes three parameters: ;title:Specifies the title that is to appear in the browser titlebar. It is inserted inside the tags <head><title>...</title></head>. Default is "Title". ;encoding:Specifies the encoding to be used in the page. Default is "utf-8". ;lang :Specifies a language code for the content of the page. Default is "en".
Html.page returns three object references:
;page :reference to page object, which contains head and body objects ;head :reference to head object ;body :reference to body object == Properties == The Html class exposes three properties which correspond to the three sections of a standard HTML tagset and can be used to manipulate them: ;tag:returns a reference to the tag defined for this object ;attr:returns a reference to the attributes inside the opening tag, if any. ;inside:returns a reference to the contents of the tagset as a list -- that is, whatever exists between the opening and closing tags. ==== Examples ==== *Retrieve the tag name of an Html object: >>> html = Html('html') >>> html ['<html>', '</html>'] >>> html.tag 'html' >>>  *Change the tag name: >>> html.tag = 'tail' >>> html ['<tail>', '</tail>'] >>>  *Retrieve the tag attributes: >>> a = Html('a', href='http://cnn.org') >>> a ['<a href="http://cnn.org">', '</a>'] >>> a.attr 'href="http://cnn.org"' >>> *Change the tag attributes: >>> a.attr 'href="http://gramps-project.org"' >>> *Extend the tag attributes: >>> a.attr += ' id="myhref"' >>> a.attr 'href="http://gramps-project.org" id="myhref"' >>> *Delete the tag attributes: >>> del a.attr >>> a.attr '' >>> *Retrieve whatever is inside a tag: >>> p = Html('p','This is a paragraph') >>> p.inside ['This is a paragraph'] >>>  *Change whatever is inside a tag: >>> p.inside = "This is a better paragraph" >>> p.inside ['This is a better paragraph'] >>>  *Extend whatever is inside a tag: >>> p.inside += ["THIS IS THE BEST PARAGRAPH!"] >>> p.inside ['This is a better paragraph', 'THIS IS THE BEST PARAGRAPH!'] >>>  *Delete whatever is inside a tag: >>> del p.inside >>> p.inside [] >>> p  [[Category:Developers/General]]