def validate_fileinfo(self, relfn, info): # layout is mandatory if 'layout' not in info: raise UrubuError(undef_info_error.format('File', relfn, 'layout')) layout = info['layout'] # modification date, always available t = os.path.getmtime(relfn) info['mdate'] = datetime.date.fromtimestamp(t) # first run a validator if it exist if layout in self.validators: self.validators[layout](info) # a validator may add/modify attributes layout = info['layout'] if layout is None: return if layout not in self.layouts: self.layouts.append(layout) # title if 'title' not in info: raise UrubuError(undef_info_error.format('File', relfn, 'title')) # date if 'date' in info: if not isinstance(info['date'], datetime.date): raise UrubuError(date_error.format(relfn)) # tags if 'tags' in info: # TODO: make sure it's a list of strings if isinstance(info['tags'], str): info['tags'] = [info['tags']]
def validate_sitereflink(self, id, info): if 'title' not in info: raise UrubuError( undef_meta_error.format('Site reflink', id, 'title')) if 'url' not in info: raise UrubuError(undef_meta_error.format('Site reflink', id, 'url'))
def validate_sitereflink(self, id, info): if 'title' not in info: raise UrubuError(_error.undef_reflink_key, fn=id, msg=id + ': title') if 'url' not in info: raise UrubuError(_error.undef_reflink_key, fn='_site.yml', msg=id + ': url')
def resolve_ref(self, ref, info): """Resolve a reference.""" reflinks = self.site['reflinks'] ref = ref.lower() path = os.path.normpath(os.path.join(info['fn'], ref)) indexfn = info['indexfn'] id = make_id(get_components(path, hasext=False)) if ref in reflinks: if (ref != id) and (id in reflinks): raise UrubuError(_error.ambig_ref, msg=ref, fn=indexfn) id = ref elif not id in reflinks: raise UrubuError(_error.undef_ref, msg=ref, fn=indexfn) return reflinks[id]
def convert(self): for info in self.filelist: fn = info['fn'] with open(fn, encoding='utf-8-sig') as inf: src = skip_yamlfm(inf) self.md.this = info # first process as a template try: templ = self.env.from_string(src) src = templ.render(this=info, site=self.site) except: exc, msg, tb = sys.exc_info() raise UrubuError(str(exc), msg=msg, fn=fn) self.md.toc = '' info['body'] = self.md.convert(src) info['toc'] = '' if hasattr(self.md, 'toc'): # filter out empty tocs, 35 is the magic length if len(self.md.toc) > 35: info['toc'] = self.md.toc # markdown support in keys mdkeys = [key for key in info if key[-3:] == '.md'] for mdkey in mdkeys: key = mdkey[:-3] info[key] = self.md.convert(info[mdkey]) self.md.reset() for info in self.navlist: # markdown support in keys mdkeys = [key for key in info if key[-3:] == '.md'] for mdkey in mdkeys: key = mdkey[:-3] info[key] = self.md.convert(info[mdkey]) self.md.reset()
def add_reflink(self, id, info): """Add a valid reflink to the site reflinks.""" id = id.lower() if id in self.site['reflinks']: cFile = self.site['reflinks'][id] errmsg = "id '{ID}' in {FN} conflicts with {CFN}".\ format(ID=id, FN=info['fn'], CFN=cFile['fn']) raise UrubuError(_error.ambig_refid, msg=errmsg) self.site['reflinks'][id] = info
def validate_navinfo(self, relfn, info): if ('content' not in info) and ('order' not in info): # exception: tag folder doesn't require content atribute # set it to empty list align with normal folders if info['id'] == tagid: info['content'] = [] else: raise UrubuError(undef_content_error.format(relfn)) require_key('content', info, list, relfn)
def handleMatch(self, m): try: ref = m.group(9) except IndexError: ref = None shortref = False if not ref: # if we got something like "[Google][]" or "[Google]" # we'll use "google" as the id ref = m.group(2) shortref = True # Clean up linebreaks in ref ref = self.NEWLINE_CLEANUP_RE.sub(' ', ref) text = m.group(2) id = ref.lower() if id in self.markdown.references: href, title = self.markdown.references[id] else: anchor = None if '#' in ref: ref, anchor = ref.split('#', 1) this = self.markdown.this if not posixpath.isabs(ref): # treat empty ref as reference to current page if not ref: ref = this['components'][-1] rootrelpath = '/' + '/'.join(this['components'][:-1]) id = posixpath.normpath(posixpath.join(rootrelpath, ref)) id = id.lower() else: id = ref.lower() ref = ref.lower() if ref in self.markdown.site['reflinks']: if (ref != id) and (id in self.markdown.site['reflinks']): raise UrubuError(_error.ambig_ref_md, msg=ref, fn=this['fn']) id = ref if id in self.markdown.site['reflinks']: item = self.markdown.site['reflinks'][id] href, title = item['url'], item['title'] if shortref: text = title if anchor is not None: text = anchor if anchor is not None: anchor = toc.slugify(anchor, '-') href = '%s#%s' % (href, anchor) anchorref = '%s#%s' % (id, anchor) self.markdown.this['_anchorrefs'].add(anchorref) else: # ignore undefined refs urubu_warn(_warning.undef_ref_md, msg=ref, fn=this['fn']) return None return self.makeTag(href, title, text)
def pred(item): itemcomps = item['components'] if len(itemcomps) == len(navcomps) + 1 and \ itemcomps[:-1] == navcomps and \ itemcomps[-1] != 'index' and \ item['layout'] is not None: if key not in item: raise UrubuError(_error.undef_key, msg=key, fn=item['fn']) return True return False
def handleMatch(self, m, data): text, index, handled = self.getText(data, m.end(0)) if not handled: return None, None, None ref, end, shortref, handled = self.evalRef(data, index, text) if not handled: return None, None, None # Clean up linebreaks in ref ref = self.NEWLINE_CLEANUP_RE.sub(' ', ref) id = ref.lower() if id in self.md.references: href, title = self.md.references[id] else: anchor = None if '#' in ref: ref, anchor = ref.split('#', 1) this = self.md.this if not posixpath.isabs(ref): # treat empty ref as reference to current page if not ref: ref = this['components'][-1] rootrelpath = '/' + '/'.join(this['components'][:-1]) id = posixpath.normpath(posixpath.join(rootrelpath, ref)) id = id.lower() else: id = ref.lower() ref = ref.lower() if ref in self.md.site['reflinks']: if (ref != id) and (id in self.md.site['reflinks']): raise UrubuError(_error.ambig_ref_md, msg=ref, fn=this['fn']) id = ref if id in self.md.site['reflinks']: item = self.md.site['reflinks'][id] href, title = item['url'], item['title'] if shortref: text = title if anchor is not None: text = anchor if anchor is not None: anchor = toc.slugify(anchor, '-') href = '%s#%s' % (href, anchor) anchorref = '%s#%s' % (id, anchor) self.md.this['_anchorrefs'].add(anchorref) else: # ignore undefined refs urubu_warn(_warning.undef_ref_md, msg=ref, fn=this['fn']) return None, None, None return self.makeTag(href, title, text), m.start(0), end
def validate_fileinfo(self, info): fn = info['fn'] # layout is mandatory if 'layout' not in info: raise UrubuError(_error.undef_info, msg='layout', fn=fn) if 'layout' is None: return layout = info['layout'] # modification date, always available t = os.path.getmtime(fn) info['mdate'] = datetime.date.fromtimestamp(t) # first run a validator if it exist if layout in self.validators: self.validators[layout](info) # a validator may add/modify attributes layout = info['layout'] if layout is None: return if layout not in self.layouts: self.layouts.append(layout) # title if 'title' not in info: raise UrubuError(_error.undef_info, msg='title', fn=fn) # Support integer titles by converting to string # this matters for the json dump for search # test type explicitly to avoid problems with unicode titles... if isinstance(info['title'], int): info['title'] = str(info['title']) # date if 'date' in info: if not isinstance(info['date'], datetime.date): raise UrubuError(_error.date_format, fn=fn) # tags if 'tags' in info: # TODO: make sure it's a list of strings if isinstance(info['tags'], str): info['tags'] = [info['tags']]
def get_contentinfo(self): """Get info from the markdown content files.""" pattern = '*.md' ignore_patterns = self.get_ignore_patterns() for path, dirnames, filenames in os.walk(self.cwd): relpath = get_relpath(path, self.cwd) if any(fnmatch.fnmatch(relpath, ip) for ip in ignore_patterns): continue content_found = index_found = False for fn in filenames: if fnmatch.fnmatch(fn, pattern): # normalize to convert ./foo into foo # to avoid problems with ignore_patterns matching relfn = os.path.normpath(os.path.join(relpath, fn)) if any( fnmatch.fnmatch(relfn, ip) for ip in ignore_patterns): continue meta = readers.get_yamlfm(relfn) if meta is None: urubu_warn(_warning.no_yamlfm, fn=relfn) continue fileinfo = self.make_fileinfo(relfn, meta) self.filelist.append(fileinfo) self.process_info(fileinfo, self.site) # validate after file info has been added so it can be used self.validate_fileinfo(fileinfo) self.add_reflink(fileinfo['id'], fileinfo) if fn == 'index.md': index_found = True # start from fileinfo of index file navinfo = self.make_navinfo(relpath, fileinfo) self.navlist.append(navinfo) self.validate_navinfo(navinfo) self.add_reflink(navinfo['id'], navinfo) # add nav info to tag map self.add_info_to_tagmap(navinfo) else: content_found = True # add id for non-index files to tag tags self.add_info_to_tagmap(fileinfo) # a folder with content but no index is an error if content_found and not index_found: raise UrubuError(_error.no_index, msg='', fn=relpath)
def handleMatch(self, m): try: ref = m.group(9).lower() except IndexError: ref = None shortref = False if not ref: # if we got something like "[Google][]" or "[Google]" # we'll use "google" as the id ref = m.group(2).lower() shortref = True text = m.group(2) # Clean up linebreaks in ref ref = self.NEWLINE_CLEANUP_RE.sub(' ', ref) if ref in self.markdown.references: href, title = self.markdown.references[ref] else: this = self.markdown.this if not posixpath.isabs(ref): rootrelpath = '/' + '/'.join(this['components'][:-1]) id = posixpath.normpath(posixpath.join(rootrelpath, ref)) id = id.lower() else: id = ref anchor = None if '#' in id and id not in self.markdown.site['reflinks']: id, anchor = id.split('#', 1) if ref in self.markdown.site['reflinks']: if (ref != id) and (id in self.markdown.site['reflinks']): raise UrubuError(ambig_ref_error.format(ref, this['fn'])) id = ref if id in self.markdown.site['reflinks']: item = self.markdown.site['reflinks'][id] href, title = item['url'], item['title'] if shortref: text = title if anchor is not None: href = '%s#%s' % (href, anchor) else: # ignore undefined refs warn(undef_ref_warning.format(ref, this['fn']), UrubuWarning) return None return self.makeTag(href, title, text)
def add_reflink(self, id, info): """Add a valid reflink to the site reflinks.""" id = id.lower() if id in self.site['reflinks']: raise UrubuError(_error.ambig_refid, msg=id) self.site['reflinks'][id] = info