The answer is now updated for the date handling in newer biblatex
versions >= 3.6, lots of what had to be done manually before will now be done automatically. Check the edit history for earlier versions.
This is quite a full-on question, but I will try to answer it anyway. This answer mainly deals with the bibliography output. For citations additional modifications and configurations might be necessary, but what needs to be done strongly depends on the used style, there is no universal answer. For numeric
citation styles the example below will of course work without further modification.
Declare new fields, and the new entry types and their fields
First, when declaring the data model, we need to make sure biblatex
actually knows the type of the fields/lists we declare (this is done via the optional argument to \DeclareDatamodelFields
). You can read much more about this in §4.5.3 Data Model Specification, p. 151 of the biblatex
documentation.
There are two main types for entry field: field
and list
. field
s usually hold one value, while list
s can hold more items separated by an and
in the .bib
file (see also §2.2.1 Data Types, p. 13).
I declared the sitekey
and sitetopic
to be literal fields (such as the title
field).
askp
and ansp
are clearly name lists (even though in this context the list will probably only ever hold one item).
A lot of the fields you are asking for seem to revolve about dates, so there are askdate
, ansdate
, askeditdate
, anseditdate
and their datepart
s (which will be created automatically, but they still need to be added to \DeclareDatamodelEntryfields
manually).
Finally, I decided the id
s should be verbatim fields.
\begin{filecontents}{stackexchange.dbx}
\DeclareDatamodelEntrytypes{stackexchange}
\DeclareDatamodelFields[type=field,datatype=literal]{
sitekey,
sitetopic,
}
\DeclareDatamodelFields[type=list,datatype=name]{
askp,
ansp,
}
\DeclareDatamodelFields[type=field, datatype=date, skipout]{
askdate,
ansdate,
askeditdate,
anseditdate}
\DeclareDatamodelFields[type=field, datatype=verbatim]{
askid,
askpid,
anspid,
ansid,
}
\DeclareDatamodelEntryfields[stackexchange]{
sitekey,
sitetopic,
askid,
askp,
askpid,
ansp,
anspid,
ansid,
askyear,
askmonth,
askday,
ansyear,
ansmonth,
ansday,
askedityear,
askeditmonth,
askeditday,
ansedityear,
anseditmonth,
anseditday,
title}
\end{filecontents}
The \DeclareDatamodelEntryfields
just makes those fields relevant to @stackexchange
known to that entry type.
Declare new bibliography strings (if necessary)
We also want to display words like 'asked' and 'answered', instead of hard-coding them, localisation with .lbx
files is the way to go. This is only necessary if you wish to include strings in the output. It is not necessary to include a string for each field you define. The fact that the name of some bibstrings coincides with the name of some fields is purely accidental. There is no requirement to define bibstrings for certain field types.
The most complete way to define new strings is by means of an .lbx
file, because that method allows you to define long and short forms of the strings. You can also define new strings directly in the preamble, but then you can only give one form that is used as short and long version.
Our new localisation file english-stack.lbx
inherits everything from english.lbx
but adds asked
, answered
and edited
as bibstrings.
\begin{filecontents*}{english-stack.lbx}
\ProvidesFile{english-stack.lbx}[2014/05/07 english with additions for stackexchange]
\InheritBibliographyExtras{english}
\NewBibliographyString{asked,answered,edited}
\DeclareBibliographyStrings{%
inherit = {english},
asked = {{asked}{asked}},
answered = {{answered}{answered}},
edited = {{edited}{edited}},
}
\end{filecontents*}
We have to tell biblatex
to use that language definition
\DeclareLanguageMapping{english}{english-stack}
Defining the bibliography output
Then finally, we can go on to define the bibliography driver. The bibliography driver is the main definition that decides how the entry is printed in the bibliography. A bibliography driver typically consists of calls to several bibliography macros as well as calls to punctuation and printing commands.
Field formats
Field formats define the formatting of each printed field. We avoid hard-coding anything and use the macros provided by biblatex
.
So instead of wrapping \printfield{title}
in \mkbibquote
, we define the field format to do so.
We use \setunit
for punctuation and \bibstring
s in lieu of hard-coded words.
\DeclareFieldFormat[stackexchange]{title}{\mkbibquote{#1\isdot}}
\DeclareFieldFormat{askpid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{anspid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{askid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/q/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{ansid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/a/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
As an added bonus, the id
fields now link to the proper stackexchange site.
\newbibmacro*{stackexchangequestion}{%
\printfield{title}%
\setunit{\addspace}%
\printfield{askid}%
}
Bibliography macros
Bibliography macros can be used to compartmentalise the output definitions.
No formatting should be applied to the \printfield
commands, formatting is dealt with by \DeclareFieldFormat
.
\newbibmacro*{stackexchangeask}{%
\bibstring{asked}%
\setunit{\addspace}%
\printaskdate%
\iffieldundef{askedityear}%
{}
{\printtext[parens]{%
\bibstring{edited}%
\setunit{\addspace}%
\printaskeditdate}}%
\setunit{\addspace}%
\bibstring{byauthor}%
\setunit{\addspace}%
\printnames{askp}%
\setunit{\addspace}%
\printfield{askpid}%
}
\newbibmacro*{stackexchangeans}{%
\bibstring{answered}%
\setunit{\addspace}%
\printansdate%
\iffieldundef{ansedityear}
{}
{\printtext[parens]{%
\bibstring{edited}%
\setunit{\addspace}%
\printanseditdate}}%
\setunit{\addspace}%
\bibstring{byauthor}%
\setunit{\addspace}%
\printnames{ansp}%
\setunit{\addspace}%
\printfield{anspid}%
}
\newbibmacro*{stackexchangesite}{%
\printfield{sitetopic}}
Bibliography driver
The driver defines the final output structure. Usually a driver makes heavy use of bibmacros, but it need not do that.
\DeclareBibliographyDriver{stackexchange}{%
\usebibmacro{bibindex}%
\usebibmacro{begentry}%
\usebibmacro{stackexchangequestion}%
\newunit\newblock
\usebibmacro{stackexchangeask}%
\newunit\newblock
\usebibmacro{stackexchangeans}%
\newunit\newblock
\usebibmacro{stackexchangesite}%
\newunit\newblock
\usebibmacro{finentry}}
MWE
\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@stackexchange{se:l3help,
sitetopic = {tex},
title = {What can \textit{I} do to help the \LaTeX3 Project},
askdate = {2012-02-26},
askid = {45838},
askp = {Brent Longorough},
askpid = {344},
ansp = {Frank Mittelbach},
anspid = {10109},
ansdate = {2012-03-01},
ansid = {46427},
}
\end{filecontents*}
\begin{filecontents}{stackexchange.dbx}
\DeclareDatamodelEntrytypes{stackexchange}
\DeclareDatamodelFields[type=field,datatype=literal]{
sitekey,
sitetopic,
}
\DeclareDatamodelFields[type=list,datatype=name]{
askp,
ansp,
}
\DeclareDatamodelFields[type=field, datatype=date, skipout]{
askdate,
ansdate,
askeditdate,
anseditdate}
\DeclareDatamodelFields[type=field, datatype=verbatim]{
askid,
askpid,
anspid,
ansid,
}
\DeclareDatamodelEntryfields[stackexchange]{
sitekey,
sitetopic,
askid,
askp,
askpid,
ansp,
anspid,
ansid,
askyear,
askmonth,
askday,
ansyear,
ansmonth,
ansday,
askedityear,
askeditmonth,
askeditday,
ansedityear,
anseditmonth,
anseditday,
title}
\end{filecontents}
\documentclass[english]{article}
\usepackage{babel}
\usepackage{csquotes}
\usepackage[datamodel=stackexchange,backend=biber]{biblatex}
\usepackage{hyperref}
\addbibresource{\jobname.bib}
\begin{filecontents*}{english-stack.lbx}
\ProvidesFile{english-stack.lbx}[2014/05/07 english with additions for stackexchange]
\InheritBibliographyExtras{english}
\NewBibliographyString{asked,answered,edited}
\DeclareBibliographyStrings{%
inherit = {english},
asked = {{asked}{asked}},
answered = {{answered}{answered}},
edited = {{edited}{edited}},
}
\end{filecontents*}
\DeclareLanguageMapping{english}{english-stack}
\DeclareFieldFormat[stackexchange]{title}{\mkbibquote{#1\isdot}}
\DeclareFieldFormat{askpid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{anspid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/users/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{askid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/q/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\DeclareFieldFormat{ansid}{%
\mkbibparens{\ifhyperref
{\href{http://tex.stackexchange.com/a/#1}{\nolinkurl{#1}}}
{\nolinkurl{#1}}}}
\newbibmacro*{stackexchangequestion}{%
\printfield{title}%
\setunit{\addspace}%
\printfield{askid}%
}
\newbibmacro*{stackexchangeask}{%
\bibstring{asked}%
\setunit{\addspace}%
\printaskdate%
\iffieldundef{askedityear}%
{}
{\printtext[parens]{%
\bibstring{edited}%
\setunit{\addspace}%
\printaskeditdate}}%
\setunit{\addspace}%
\bibstring{byauthor}%
\setunit{\addspace}%
\printnames{askp}%
\setunit{\addspace}%
\printfield{askpid}%
}
\newbibmacro*{stackexchangeans}{%
\bibstring{answered}%
\setunit{\addspace}%
\printansdate%
\iffieldundef{ansedityear}
{}
{\printtext[parens]{%
\bibstring{edited}%
\setunit{\addspace}%
\printanseditdate}}%
\setunit{\addspace}%
\bibstring{byauthor}%
\setunit{\addspace}%
\printnames{ansp}%
\setunit{\addspace}%
\printfield{anspid}%
}
\newbibmacro*{stackexchangesite}{%
\printfield{sitetopic}}
\DeclareBibliographyDriver{stackexchange}{%
\usebibmacro{bibindex}%
\usebibmacro{begentry}%
\usebibmacro{stackexchangequestion}%
\newunit\newblock
\usebibmacro{stackexchangeask}%
\newunit\newblock
\usebibmacro{stackexchangeans}%
\newunit\newblock
\usebibmacro{stackexchangesite}%
\newunit\newblock
\usebibmacro{finentry}}
\begin{document}
\nocite{*}
\cite{se:l3help}
\printbibliography
\end{document}

To allow the use of askdate
as labeldate, so the authoryear
style (and other similar ones) does not print 'n.d.', we can use \DeclareLabeldate
(§4.5.8 Special Fields, p. 176) as follows
\DeclareLabeldate{%
\field{date}
\field{eventdate}
\field{origdate}
\field{askdate}
\field{urldate}
\literal{nodate}
}
There also is \DeclareLabelname
(p. 176) with a similar syntax, if you want to see either askp
or ansp
as the author in authoryear
/authortitle
styles.
\DeclareDatamodel*
commands, which you would then pair with\newbibmacro
s and so forth.:)