1313import saneyaml
1414import re
1515
16- from frontmatter import detect_format
17- from frontmatter import handlers
18- from frontmatter import Post as FrontmatterPost
19- from frontmatter .default_handlers import BaseHandler
20- from frontmatter .util import u
2116
22- from licensedcode .tokenize import query_lines
17+ DEFAULT_POST_TEMPLATE = """\
18+ {start_delimiter}
19+ {metadata}
20+ {end_delimiter}
2321
22+ {content}
23+ """
2424
2525
26- class SaneYAMLHandler ( BaseHandler ) :
26+ class SaneYAMLHandler :
2727 """
2828 Load and export YAML metadata. .
2929
30- This is similar to the frontmatter.default_handlers.YAMLHandler but
31- is using nexB/saneyaml instead of pyyaml.
30+ This is similar to the original frontmatter.default_handlers.YAMLHandler
31+ but is using nexB/saneyaml instead of pyyaml.
3232 """
3333 FM_BOUNDARY = re .compile (r"^-{3,}\s*$" , re .MULTILINE )
3434 START_DELIMITER = END_DELIMITER = "---"
3535
36+ def __init__ (self ):
37+ self .FM_BOUNDARY = self .FM_BOUNDARY
38+ self .START_DELIMITER = self .START_DELIMITER
39+ self .END_DELIMITER = self .END_DELIMITER
40+
41+ def detect (self , text ):
42+ """
43+ Decide whether this handler can parse the given ``text``,
44+ and return True or False.
45+ """
46+ if self .FM_BOUNDARY .match (text ):
47+ return True
48+ return False
49+
50+ def split (self , text ):
51+ """
52+ Split text into frontmatter and content
53+ """
54+ _ , fm , content = self .FM_BOUNDARY .split (text , 2 )
55+ return fm , content
56+
57+ def format (self , content , metadata , ** kwargs ):
58+ """
59+ Turn a post into a string, used in ``frontmatter.dumps``
60+ """
61+ start_delimiter = kwargs .pop ("start_delimiter" , self .START_DELIMITER )
62+ end_delimiter = kwargs .pop ("end_delimiter" , self .END_DELIMITER )
63+
64+ metadata = self .export (metadata , ** kwargs )
65+
66+ return DEFAULT_POST_TEMPLATE .format (
67+ metadata = metadata ,
68+ content = content ,
69+ start_delimiter = start_delimiter ,
70+ end_delimiter = end_delimiter ,
71+ ).strip ()
72+
3673 def load (self , fm , ** kwargs ):
3774 """
3875 Parse YAML front matter.
@@ -44,42 +81,34 @@ def export(self, metadata, **kwargs):
4481 Export metadata as YAML.
4582 """
4683 metadata = saneyaml .dump (metadata , indent = 4 , encoding = 'utf-8' , ** kwargs ).strip ()
47- return u (metadata ) # ensure unicode
84+ return return_unicode (metadata ) # ensure unicode
4885
4986
50- def get_rule_text (location = None , text = None ):
51- """
52- Return the rule ``text`` prepared for indexing.
53- ###############
54- # IMPORTANT: we use the same process as used to load query text for symmetry
55- ###############
56- """
57- numbered_lines = query_lines (location = location , query_string = text , plain_text = True )
58- return '\n ' .join (l .strip () for _ , l in numbered_lines )
87+ def return_unicode (text , encoding = "utf-8" ):
88+ "Return unicode text, no matter what"
89+
90+ if isinstance (text , bytes ):
91+ text = text .decode (encoding )
5992
93+ # it's already unicode
94+ text = text .replace ("\r \n " , "\n " )
95+ return text
6096
61- def parse_frontmatter (text , encoding = "utf-8" , handler = None , ** defaults ):
97+
98+ def parse_frontmatter (text , encoding = "utf-8" , handler = SaneYAMLHandler (), ** defaults ):
6299 """
63100 Parse text with frontmatter, return metadata and content.
64101 Pass in optional metadata defaults as keyword args.
65102
66103 If frontmatter is not found, returns an empty metadata dictionary
67104 (or defaults) and original text content.
68-
69- This is similar to the frontmatter.parse but is using `get_rule_text`
70- to use the same process as loading quary text for symmetry.
71105 """
72106 # ensure unicode first
73- text = u (text , encoding ). strip ( )
107+ text = return_unicode (text , encoding )
74108
75109 # metadata starts with defaults
76110 metadata = defaults .copy ()
77111
78- # this will only run if a handler hasn't been set higher up
79- handler = handler or detect_format (text , handlers )
80- if handler is None :
81- return metadata , text
82-
83112 # split on the delimiters
84113 try :
85114 fm , content = handler .split (text )
@@ -92,57 +121,27 @@ def parse_frontmatter(text, encoding="utf-8", handler=None, **defaults):
92121 if isinstance (fm , dict ):
93122 metadata .update (fm )
94123
95- text = get_rule_text ( text = content )
124+ return content , metadata
96125
97- return metadata , text
98126
99-
100- def loads_frontmatter (text , encoding = "utf-8" , handler = None , ** defaults ):
127+ def load_frontmatter (fd , encoding = "utf-8" , ** defaults ):
101128 """
102- Parse text (binary or unicode) and return a :py:class:`post <frontmatter.Post>`.
103-
104- This is similar to the frontmatter.loads but is using the `parse`
105- function defined above.
106- """
107- text = u (text , encoding )
108- handler = handler or detect_format (text , handlers )
109- metadata , content = parse_frontmatter (text , encoding , handler , ** defaults )
110- return FrontmatterPost (content , handler , ** metadata )
111-
112-
113- def load_frontmatter (fd , encoding = "utf-8" , handler = None , ** defaults ):
114- """
115- Load and parse a file-like object or filename,
116- return a :py:class:`post <frontmatter.Post>`.
117-
118- This is similar to the frontmatter.load but is using the `loads`
119- function defined above.
129+ Load and parse a file-like object or filename, and return
130+ `content` and `metadata` with the text and the frontmatter metadata.
120131 """
121132 if hasattr (fd , "read" ):
122133 text = fd .read ()
123134
124135 else :
125136 with codecs .open (fd , "r" , encoding ) as f :
126137 text = f .read ()
127-
128- handler = handler or detect_format (text , handlers )
129- return loads_frontmatter (text , encoding , handler , ** defaults )
138+
139+ text = return_unicode (text , encoding )
140+ return parse_frontmatter (text , encoding , ** defaults )
130141
131142
132- def dumps_frontmatter (post , handler = None , ** kwargs ):
143+ def dumps_frontmatter (content , metadata , handler = SaneYAMLHandler () , ** kwargs ):
133144 """
134- Serialize a :py:class:`post <frontmatter.Post>` to a string and return text.
135- This always returns unicode text, which can then be encoded.
136-
137- Passing ``handler`` will change how metadata is turned into text. A handler
138- passed as an argument will override ``post.handler``, with
139- :py:class:`SaneYAMLHandler <frontmatter.SaneYAMLHandler>` used as
140- a default.
141-
142- This is similar to the frontmatter.dumps but is using the `SaneYAMLHandler`
143- defined above as default instead of frontmatter.default_handlers.YAMLHandler.
145+ Create a string and return the text from `content` and `metadata`.
144146 """
145- if handler is None :
146- handler = getattr (post , "handler" , None ) or SaneYAMLHandler ()
147-
148- return handler .format (post , ** kwargs )
147+ return handler .format (content , metadata , ** kwargs )
0 commit comments