@@ -71,7 +71,7 @@
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."¶
- This Internet-Draft will expire on August 9, 2024.¶
+ This Internet-Draft will expire on August 22, 2024.
¶
diff --git a/xml2rfc/data/xml2rfc.css b/xml2rfc/data/xml2rfc.css
index 1347b9c3..6196bda1 100644
--- a/xml2rfc/data/xml2rfc.css
+++ b/xml2rfc/data/xml2rfc.css
@@ -424,6 +424,10 @@ nav.toc li {
margin-bottom: 1.25em;
}
+.refSubseries {
+ margin-bottom: 1.25em;
+}
+
.references .ascii {
margin-bottom: 0.25em;
}
diff --git a/xml2rfc/writers/base.py b/xml2rfc/writers/base.py
index 6500d44c..85beea0c 100644
--- a/xml2rfc/writers/base.py
+++ b/xml2rfc/writers/base.py
@@ -31,6 +31,12 @@
from xml2rfc.utils import namespaces, find_duplicate_ids, slugify
+SUBSERIES = {
+ 'STD': 'Internet Standard',
+ 'BCP': 'Best Current Practice',
+ 'FYI': 'For Your Information',
+}
+
DEADLY_ERRORS = [
'Element svg has extra content: script',
'Did not expect element script there',
@@ -73,6 +79,7 @@
'image_svg': False,
'indent': 2,
'info': False,
+ 'info_base_url': 'https://www.rfc-editor.org/info/',
'inline_version_info': True,
'legacy': False,
'legacy_date_format': False,
diff --git a/xml2rfc/writers/html.py b/xml2rfc/writers/html.py
index 1e59e429..1327b491 100644
--- a/xml2rfc/writers/html.py
+++ b/xml2rfc/writers/html.py
@@ -29,7 +29,7 @@
pass
from xml2rfc import log, strings
-from xml2rfc.writers.base import default_options, BaseV3Writer, RfcWriterError
+from xml2rfc.writers.base import default_options, BaseV3Writer, RfcWriterError, SUBSERIES
from xml2rfc.uniscripts import is_script
from xml2rfc.util.date import extract_date, augment_date, format_date, format_date_iso, get_expiry_date
from xml2rfc.util.name import ( full_author_name_expansion, short_author_role,
@@ -2158,18 +2158,14 @@ def render_reference(self, h, x):
self.render(inner, c)
for ctag in ('title', 'refcontent', 'stream', 'seriesInfo', 'date', ):
for c in x.iterdescendants(ctag):
- if p.tag == 'referencegroup' and c.tag == 'seriesInfo' and c.get('name') == 'DOI':
- # Don't render DOI within a reference group
- continue
if len(inner):
inner[-1].tail = ', '
self.render(inner, c)
- if p.tag != 'referencegroup':
- target = x.get('target')
- if len(inner):
- inner[-1].tail = ', '
- if target:
- inner.append( build.span('<', build.a(target, href=target), '>') )
+ target = x.get('target')
+ if len(inner):
+ inner[-1].tail = ', '
+ if target:
+ inner.append( build.span('<', build.a(target, href=target), '>') )
if len(inner):
inner[-1].tail = '. '
for ctag in ('annotation', ):
@@ -2200,13 +2196,29 @@ def render_reference(self, h, x):
def render_referencegroup(self, h, x):
dt = add.dt(h, x, '[%s]'%x.get('derivedAnchor'))
dd = add.dd(h, None)
+ target = x.get('target')
+ subseries = False
# workaround for weasyprint's unwillingness to break between
and
# : add an extra that is very prone to page breaks. See CSS.
add.dd(h, None, classes='break')
+ for series in x.xpath('.//seriesInfo'):
+ if series.get('name') in SUBSERIES.keys():
+ text = f"{SUBSERIES[series.get('name')]} {series.get('value')}"
+ subdiv = build.div(text, classes='refInstance')
+ if target:
+ subdiv.text += ', '
+ subdiv.append(build.span('<', build.a(target, href=target), '>'))
+ subdiv[0].tail = '.'
+ else:
+ subdiv.text += '.'
+ subdiv.append(build.br())
+ subdiv.append(build.span(f"At the time of writing, this {series.get('name')} comprises the following:"))
+ dd.append(subdiv)
+ subseries = True
+ break
for c in x.getchildren():
self.render(dd, c)
- target = x.get('target')
- if target:
+ if target and not subseries:
dd.append( build.span('<', build.a(target, href=target), '>') )
return dt, dd
diff --git a/xml2rfc/writers/preptool.py b/xml2rfc/writers/preptool.py
index 4722d721..1ac33a6f 100644
--- a/xml2rfc/writers/preptool.py
+++ b/xml2rfc/writers/preptool.py
@@ -263,6 +263,7 @@ def prep(self):
'.//boilerplate;insert_copyright_notice()', # 5.4.2.3. "Copyright Notice" Insertion
'.//boilerplate//section', # 5.2.7. Section "toc" attribute
'.//reference;insert_target()', # 5.4.3. "target" Insertion
+ './/referencegroup;insert_target()', # "target" Insertion
'.//reference;insert_work_in_progress()',
'.//reference;sort_series_info()', # sort
'.//name;insert_slugified_name()', # 5.4.4. Slugification
@@ -1216,6 +1217,24 @@ def series_order(s):
front.insert(pos, s)
pos += 1
+ def referencegroup_insert_target(self, e, p):
+ target_pattern = {
+ "BCP": os.path.join(self.options.info_base_url, 'bcp{value}'),
+ "STD": os.path.join(self.options.info_base_url, 'std{value}'),
+ "FYI": os.path.join(self.options.info_base_url, 'fyi{value}'),
+ }
+
+ if not e.get('target'):
+ for c in e.xpath('.//seriesInfo'):
+ series_name = c.get('name')
+ if series_name in target_pattern.keys():
+ series_value=c.get('value')
+ if series_value:
+ e.set('target', target_pattern[series_name].format(value=series_value))
+ break
+ else:
+ self.err(c, 'Expected a value= attribute value for , but found none' % (series_name, ))
+
#
# 5.4.4. Slugification
#
diff --git a/xml2rfc/writers/text.py b/xml2rfc/writers/text.py
index f83d9633..dcd4a055 100644
--- a/xml2rfc/writers/text.py
+++ b/xml2rfc/writers/text.py
@@ -22,7 +22,7 @@
from xml2rfc import strings
-from xml2rfc.writers.base import default_options, BaseV3Writer, RfcWriterError
+from xml2rfc.writers.base import default_options, BaseV3Writer, RfcWriterError, SUBSERIES
from xml2rfc import utils
from xml2rfc.uniscripts import is_script
from xml2rfc.util.date import extract_date, augment_date, get_expiry_date, format_date
@@ -2728,16 +2728,12 @@ def render_reference(self, e, width, **kwargs):
elements = []
for ctag in ('title', 'refcontent', 'stream', 'seriesInfo', 'date',):
for c in e.iterdescendants(ctag):
- if p.tag == 'referencegroup' and c.tag == 'seriesInfo' and c.get('name') == 'DOI':
- # Don't render DOI within a reference group
- continue
elements.append(c)
- if p.tag != 'referencegroup':
- target = e.get('target')
- if target:
- url = self.element('refcontent')
- url.text = '<%s>' % target
- elements.append(url)
+ target = e.get('target')
+ if target:
+ url = self.element('refcontent')
+ url.text = '<%s>' % target
+ elements.append(url)
set_joiners(kwargs, {
None: Joiner(', ', 0, 0, False, False),
'annotation': Joiner(' ', 0, 0, False, False),
@@ -2793,10 +2789,33 @@ def render_referencegroup(self, e, width, **kwargs):
label = self.refname_mapping[e.get('anchor')]
label = ('[%s]' % label).ljust(11)
lines = []
+ target = e.get('target')
+ subseries = False
+ for series in e.xpath('.//seriesInfo'):
+ if series.get('name') in SUBSERIES.keys():
+ kwargs['joiners'].update({
+ None: Joiner(', ', 11, 0, False, False),
+ 't': Joiner('\n', 11, 0, False, False),
+ })
+ text = f"{SUBSERIES[series.get('name')]} {series.get('value')}"
+ if target:
+ url = self.element('refcontent')
+ url.text = f'<{target}>.'
+ text = self.tjoin(text, url, width, **kwargs)
+ else:
+ text += '.'
+ subseries_width = width - 11
+ text = fill(text, width=subseries_width, fix_sentence_endings=False, keep_url=True, **kwargs).lstrip(stripspace)
+ text = indent(text, 11, 0)
+ lines = mklines(text, e)
+ t = self.element('t')
+ t.text = f"At the time of writing, this {series.get('name')} comprises the following:"
+ lines = self.ljoin(lines, t, width, **kwargs)
+ subseries = True
+ break
for c in e.getchildren():
lines = self.ljoin(lines, c, width, **kwargs)
- target = e.get('target')
- if target:
+ if target and not subseries:
t = self.element('t')
t.text = '<%s>' % target
lines = self.ljoin(lines, t, width, **kwargs)