summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-11-03 17:19:06 -0600
committerPatrick Griffis <pgriffis@igalia.com>2020-11-03 17:19:06 -0600
commitb07c7ba4e55fbe29c5511bb9f937005be2208326 (patch)
treece8878875a7fd58304f1afb310c7988a4b2d4174
parent3485d82b7fc4451006f9b5a94fe143efab9b2a9d (diff)
downloadlibsoup-wip/pgriffis/markdown-docs.tar.gz
WIP: Try using markdown for docswip/pgriffis/markdown-docs
-rw-r--r--docs/reference/client-howto.md45
-rw-r--r--docs/reference/client-howto.xml548
-rwxr-xr-xdocs/reference/gtk-markdown-to-docbook.py201
-rw-r--r--docs/reference/meson.build33
4 files changed, 274 insertions, 553 deletions
diff --git a/docs/reference/client-howto.md b/docs/reference/client-howto.md
new file mode 100644
index 00000000..431b667c
--- /dev/null
+++ b/docs/reference/client-howto.md
@@ -0,0 +1,45 @@
+# libsoup Client Basics {#libsoup-client-howto}
+
+This section explains how to use libsoup as an HTTP client using several new APIs introduced in version 2.42.
+If you want to be compatible with older versions of libsoup, consult the documentation for that version.
+
+
+## Creating a SoupSession
+
+The first step in using the client API is to create a #SoupSession.
+The session object encapsulates all of the state that libsoup
+is keeping on behalf of your program; cached HTTP connections,
+authentication information, etc.
+
+When you create the session with soup_session_new_with_options(),
+you can specify various additional options:
+
+- ["max-conns"](#SoupSession:max-conns)
+
+ Allows you to set the maximum total number of connections
+ the session will have open at one time. (Once it reaches
+ this limit, it will either close idle connections, or
+ wait for existing connections to free up before starting
+ new requests.) The default value is `10`.
+
+- ["max-conns-per-host"](#SoupSession:max-conns-per-host)
+
+ Allows you to set the maximum total number of connections
+ the session will have open *to a single host* at one time.
+ The default value is `2`.
+
+- ["user-agent"](#SoupSession:user-agent)
+
+ Allows you to set a User-Agent string that will be sent
+ on all outgoing requests.
+
+Other properties are also available; see the #SoupSession documentation
+for more details.
+
+If you don't need to specify any options, you can just use soup_session_new(),
+which takes no arguments.
+
+## Session features
+
+Additional session functionality is provided as #SoupSessionFeature<!-- -->s,
+which can be added to a session... \ No newline at end of file
diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml
deleted file mode 100644
index d9c558ae..00000000
--- a/docs/reference/client-howto.xml
+++ /dev/null
@@ -1,548 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-<refentry id="libsoup-client-howto">
-<refmeta>
-<refentrytitle>libsoup Client Basics</refentrytitle>
-<manvolnum>3</manvolnum>
-<refmiscinfo>LIBSOUP Library</refmiscinfo>
-</refmeta>
-
-<refnamediv>
-<refname>libsoup Client Basics</refname><refpurpose>Client-side tutorial</refpurpose>
-</refnamediv>
-
-<refsect2>
-<para>
-This section explains how to use <application>libsoup</application> as
-an HTTP client using several new APIs introduced in version 2.42. If
-you want to be compatible with older versions of
-<application>libsoup</application>, consult the documentation for that
-version.
-</para>
-</refsect2>
-
-<refsect2>
-<title>Creating a <type>SoupSession</type></title>
-
-<para>
-The first step in using the client API is to create a <link
-linkend="SoupSession"><type>SoupSession</type></link>. The session object
-encapsulates all of the state that <application>libsoup</application>
-is keeping on behalf of your program; cached HTTP connections,
-authentication information, etc.
-</para>
-
-<para>
-When you create the session with <link
-linkend="soup-session-new-with-options"><function>soup_session_new_with_options</function></link>,
-you can specify various additional options:
-</para>
-
-<variablelist>
- <varlistentry>
- <term><link linkend="SoupSession:max-conns"><literal>"max-conns"</literal></link></term>
- <listitem><para>
- Allows you to set the maximum total number of connections
- the session will have open at one time. (Once it reaches
- this limit, it will either close idle connections, or
- wait for existing connections to free up before starting
- new requests.) The default value is 10.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:max-conns-per-host"><literal>"max-conns-per-host"</literal></link></term>
- <listitem><para>
- Allows you to set the maximum total number of connections
- the session will have open <emphasis>to a single
- host</emphasis> at one time. The default value is 2.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:user-agent"><literal>"user-agent"</literal></link></term>
- <listitem><para>
- Allows you to set a User-Agent string that will be sent
- on all outgoing requests.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:accept-language"><literal>"accept-language"</literal></link>
- and <link linkend="SoupSession:accept-language-auto"><literal>"accept-language-auto"</literal></link></term>
- <listitem><para>
- Allow you to set an Accept-Language header on all outgoing
- requests. <literal>"accept-language"</literal>
- takes a list of language tags to use, while
- <literal>"accept-language-auto"</literal>
- automatically generates the list from the user's locale
- settings.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:http-aliases"><literal>"http-aliases"</literal></link>
- and <link linkend="SoupSession:https-aliases"><literal>"https-aliases"</literal></link></term>
- <listitem><para>
- Allow you to tell the session to recognize additional URI
- schemes as aliases for "<literal>http</literal>" or
- <literal>https</literal>. You can set this if you are
- using URIs with schemes like "<literal>dav</literal>" or
- "<literal>webcal</literal>" (and in particular, you need
- to set this if the server you are talking to might return
- redirects with such a scheme).
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:proxy-resolver"><literal>"proxy-resolver"</literal></link></term>
- <listitem>
- <para>
- <link linkend="SoupSession:proxy-resolver"><literal>"proxy-resolver"</literal></link>
- specifies a <link
- linkend="GProxyResolver"><type>GProxyResolver</type></link>
- to use to determine the HTTP proxies to use. By default,
- this is set to the resolver returned by <link
- linkend="g-proxy-resolver-get-default"><function>g_proxy_resolver_get_default</function></link>,
- so you do not need to set it yourself.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupSession:add-feature"><literal>"add-feature"</literal></link> and <link linkend="SOUP-SESSION-ADD-FEATURE-BY-TYPE:CAPS"><literal>"add-feature-by-type"</literal></link></term>
- <listitem><para>
- These allow you to specify <link
- linkend="SoupSessionFeature"><type>SoupSessionFeature</type></link>s
- (discussed <link linkend="session-features">below</link>)
- to add at construct-time.
- </para></listitem>
- </varlistentry>
-</variablelist>
-
-<para>
-Other properties are also available; see the <link
-linkend="SoupSession"><type>SoupSession</type></link> documentation for
-more details.
-</para>
-
-<para>
-If you don't need to specify any options, you can just use <link
-linkend="soup-session-new"><function>soup_session_new</function></link>,
-which takes no arguments.
-</para>
-
-</refsect2>
-
-<refsect2 id="session-features">
-<title>Session features</title>
-
-<para>
-Additional session functionality is provided as <link
-linkend="SoupSessionFeature"><type>SoupSessionFeature</type></link>s,
-which can be added to a session, via the <link
-linkend="SoupSession:add-feature"><literal>"add-feature"</literal></link>
-and <link
-linkend="SoupSession:add-feature-by-type"><literal>"add-feature-by-type"</literal></link>
-options at session-construction-time, or afterward via the <link
-linkend="soup-session-add-feature"><function>soup_session_add_feature</function></link>
-and <link
-linkend="soup-session-add-feature-by-type"><function>soup_session_add_feature_by_type</function></link>
-functions.
-</para>
-
-<para>
-A <link
-linkend="SoupContentDecoder"><type>SoupContentDecoder</type></link> is
-added for you automatically. This advertises to servers that the
-client supports compression, and automatically decompresses compressed
-responses.
-</para>
-
-<para>
-Some other available features that you can add include:
-</para>
-
-<variablelist>
- <varlistentry>
- <term><link linkend="SoupLogger"><type>SoupLogger</type></link></term>
- <listitem><para>
- A debugging aid, which logs all of libsoup's HTTP traffic
- to <literal>stdout</literal> (or another place you specify).
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <link linkend="SoupCookieJar"><type>SoupCookieJar</type></link>,
- <link linkend="SoupCookieJarText"><type>SoupCookieJarText</type></link>,
- and <link linkend="SoupCookieJarDB"><type>SoupCookieJarDB</type></link>
- </term>
- <listitem><para>
- Support for HTTP cookies. <type>SoupCookieJar</type>
- provides non-persistent cookie storage, while
- <type>SoupCookieJarText</type> uses a text file to keep
- track of cookies between sessions, and
- <type>SoupCookieJarDB</type> uses a
- <application>SQLite</application> database.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><link linkend="SoupContentSniffer"><type>SoupContentSniffer</type></link></term>
- <listitem><para>
- Uses the HTML5 sniffing rules to attempt to
- determine the Content-Type of a response when the
- server does not identify the Content-Type, or appears to
- have provided an incorrect one.
- </para></listitem>
- </varlistentry>
-</variablelist>
-
-<para>
-Use the "add_feature_by_type" property/function to add features that
-don't require any configuration (such as <link
-linkend="SoupContentSniffer"><type>SoupContentSniffer</type></link>),
-and the "add_feature" property/function to add features that must be
-constructed first (such as <link
-linkend="SoupLogger"><type>SoupLogger</type></link>). For example, an
-application might do something like the following:
-</para>
-
-<informalexample><programlisting>
- session = soup_session_new_with_options (
- "add-feature-by-type", SOUP_TYPE_CONTENT_SNIFFER,
- NULL);
-
- if (debug_level) {
- SoupLogger *logger;
-
- logger = soup_logger_new (debug_level, -1);
- soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
- g_object_unref (logger);
- }
-</programlisting></informalexample>
-
-</refsect2>
-
-<refsect2>
-<title>Creating and Sending SoupMessages</title>
-
-<para>
-Once you have a session, you send HTTP requests using <link
-linkend="SoupMessage"><type>SoupMessage</type></link>. In the simplest
-case, you only need to create the message and it's ready to send:
-</para>
-
-<informalexample><programlisting>
- SoupMessage *msg;
-
- msg = soup_message_new ("GET", "http://example.com/");
-</programlisting></informalexample>
-
-<para>
-In more complicated cases, you can use various <link
-linkend="SoupMessage">SoupMessage</link>, <link
-linkend="SoupMessageHeaders">SoupMessageHeaders</link>, and <link
-linkend="SoupMessageBody">SoupMessageBody</link> methods to set the
-request headers and body of the message:
-</para>
-
-<informalexample><programlisting>
- SoupMessage *msg;
-
- msg = soup_message_new ("POST", "http://example.com/form.cgi");
- soup_message_set_request (msg, "application/x-www-form-urlencoded",
- SOUP_MEMORY_COPY, formdata, strlen (formdata));
- soup_message_headers_append (msg->request_headers, "Referer", referring_url);
-</programlisting></informalexample>
-
-<para>
-(Although this is a bad example, because
-<application>libsoup</application> actually has convenience methods
-for dealing with <link linkend="libsoup-3.0-HTML-Form-Support">HTML
-forms</link>.)
-</para>
-
-<para>
-You can also use <link
-linkend="soup-message-set-flags"><function>soup_message_set_flags</function></link>
-to change some default behaviors. For example, by default,
-<type>SoupSession</type> automatically handles responses from the
-server that redirect to another URL. If you would like to handle these
-yourself, you can set the <link linkend="SOUP-MESSAGE-NO-REDIRECT:CAPS"><literal>SOUP_MESSAGE_NO_REDIRECT</literal></link>
-flag.
-</para>
-
-<refsect3>
-<title>Sending a Message Synchronously</title>
-
-<para>
-To send a message and wait for the response, use <link
-linkend="soup-session-send"><function>soup_session_send</function></link>:
-</para>
-
-<informalexample><programlisting>
- GInputStream *stream;
- GError *error = NULL;
-
- stream = soup_session_send (session, msg, cancellable, &amp;error);
-</programlisting></informalexample>
-
-<para>
-At the point when <function>soup_session_send</function> returns, the
-request will have been sent, and the response headers read back in;
-you can examine the message's <structfield>status_code</structfield>,
-<structfield>reason_phrase</structfield>, and
-<structfield>response_headers</structfield> fields to see the response
-metadata. To get the response body, read from the returned <link
-linkend="GInputStream"><type>GInputStream</type></link>, and close it
-when you are done.
-</para>
-
-<para>
-Note that <function>soup_session_send</function> only returns an error
-if a transport-level problem occurs (eg, it could not connect to the
-host, or the request was cancelled). Use the message's
-<structfield>status_code</structfield> field to determine whether the
-request was successful or not at the HTTP level (ie, "<literal>200
-OK</literal>" vs "<literal>401 Bad Request</literal>").
-</para>
-
-<para>
-If you would prefer to have <application>libsoup</application> gather
-the response body for you and then return it all at once, you can use
-the older
-<link linkend="soup-session-send-message"><function>soup_session_send_message</function></link>
-API:
-</para>
-
-<informalexample><programlisting>
- guint status;
-
- status = soup_session_send_message (session, msg);
-</programlisting></informalexample>
-
-<para>
-In this case, the response body will be available in the message's
-<structfield>response_body</structfield> field, and transport-level
-errors will be indicated in the <structfield>status_code</structfield>
-field via special pseudo-HTTP-status codes like <link
-linkend="SOUP-STATUS-CANT-CONNECT:CAPS"><literal>SOUP_STATUS_CANT_CONNECT</literal></link>.
-</para>
-
-</refsect3>
-
-<refsect3>
-<title>Sending a Message Asynchronously</title>
-
-<para>
-To send a message asynchronously, use <link
-linkend="soup-session-send-async"><function>soup_session_send_async</function></link>:
-</para>
-
-<informalexample><programlisting>
-{
- ...
- soup_session_send_async (session, msg, cancellable, my_callback, my_callback_data);
- ...
-}
-
-static void
-my_callback (GObject *object, GAsyncResult *result, gpointer user_data)
-{
- GInputStream *stream;
- GError *error = NULL;
-
- stream = soup_session_send_finish (SOUP_SESSION (object), result, &amp;error);
- ...
-}
-</programlisting></informalexample>
-
-<para>
-The message will be added to the session's queue, and eventually (when
-control is returned back to the main loop), it will be sent and the
-response will be read. When the message has been sent, and its
-headers received, the callback will be invoked, in the standard
-<link linkend="GAsyncReadyCallback"><type>GAsyncReadyCallback</type></link>
-style.
-</para>
-
-<para>
-As with synchronous sending, there is also an alternate API, <link
-linkend="soup-session-queue-message"><function>soup_session_queue_message</function></link>,
-in which your callback is not invoked until the response has been
-completely read:
-</para>
-
-<informalexample><programlisting>
-{
- ...
- soup_session_queue_message (session, msg, my_callback, my_callback_data);
- ...
-}
-
-static void
-my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- /* msg->response_body contains the response */
-}
-</programlisting></informalexample>
-
-<para>
-<link
-linkend="soup-session-queue-message"><function>soup_session_queue_message</function></link>
-is slightly unusual in that it steals a reference to the message
-object, and unrefs it after the last callback is invoked on it. So
-when using this API, you should not unref the message yourself.
-</para>
-
-</refsect3>
-
-</refsect2>
-
-<refsect2>
-<title>Processing the Response</title>
-
-<para>
-Once you have received the initial response from the server,
-synchronously or asynchronously, streaming or not, you can look at the
-response fields in the <literal>SoupMessage</literal> to decide what
-to do next. The <structfield>status_code</structfield> and
-<structfield>reason_phrase</structfield> fields contain the numeric
-status and textual status response from the server.
-<structfield>response_headers</structfield> contains the response
-headers, which you can investigate using <link
-linkend="soup-message-headers-get-list"><function>soup_message_headers_get_list</function></link>
-and <link
-linkend="soup-message-headers-foreach"><function>soup_message_headers_foreach</function></link>.
-</para>
-
-<para>
-<link
-linkend="SoupMessageHeaders"><type>SoupMessageHeaders</type></link>
-automatically parses several important headers in
-<structfield>response_headers</structfield> for you and provides
-specialized accessors for them. Eg, <link
-linkend="soup-message-headers-get-content-type"><function>soup_message_headers_get_content_type</function></link>.
-There are several generic methods such as <link
-linkend="soup-header-parse-param-list"><function>soup_header_parse_param_list</function></link>
-(for parsing an attribute-list-type header) and <link
-linkend="soup-header-contains"><function>soup_header_contains</function></link>
-(for quickly testing if a list-type header contains a particular
-token). These handle the various syntactical oddities of parsing HTTP
-headers much better than functions like
-<function>g_strsplit</function> or <function>strstr</function>.
-</para>
-
-</refsect2>
-
-<refsect2>
-<title>Handling Authentication</title>
-
-<para>
-<type>SoupSession</type> handles most of the details of HTTP
-authentication for you. If it receives a 401 ("Unauthorized") or 407
-("Proxy Authentication Required") response, the session will emit the
-<link linkend="SoupSession-authenticate">authenticate</link> signal,
-providing you with a <link
-linkend="SoupAuth"><type>SoupAuth</type></link> object indicating the
-authentication type ("Basic", "Digest", or "NTLM") and the realm name
-provided by the server. If you have a username and password available
-(or can generate one), call <link
-linkend="soup-auth-authenticate"><function>soup_auth_authenticate</function></link>
-to give the information to libsoup. The session will automatically
-requeue the message and try it again with that authentication
-information. (If you don't call
-<function>soup_auth_authenticate</function>, the session will just
-return the message to the application with its 401 or 407 status.)
-</para>
-
-<para>
-If the server doesn't accept the username and password provided, the
-session will emit <link
-linkend="SoupSession-authenticate">authenticate</link> again, with the
-<literal>retrying</literal> parameter set to <literal>TRUE</literal>. This lets the
-application know that the information it provided earlier was
-incorrect, and gives it a chance to try again. If this
-username/password pair also doesn't work, the session will contine to
-emit <literal>authenticate</literal> again and again until the
-provided username/password successfully authenticates, or until the
-signal handler fails to call <link
-linkend="soup-auth-authenticate"><function>soup_auth_authenticate</function></link>,
-at which point <application>libsoup</application> will allow the
-message to fail (with status 401 or 407).
-</para>
-
-<para>
-If you need to handle authentication asynchronously (eg, to pop up a
-password dialog without recursively entering the main loop), you can
-do that as well. Just call <link
-linkend="soup-session-pause-message"><function>soup_session_pause_message</function></link>
-on the message before returning from the signal handler, and
-<function>g_object_ref</function> the <type>SoupAuth</type>. Then,
-later on, after calling <function>soup_auth_authenticate</function>
-(or deciding not to), call <link
-linkend="soup-session-unpause-message"><function>soup_session_unpause_message</function></link>
-to resume the paused message.
-</para>
-
-<para>
-By default, NTLM authentication is not enabled. To add NTLM support to
-a session, call:
-</para>
-
-<informalexample><programlisting>
- soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM);
-</programlisting></informalexample>
-
-<para>
-(You can also disable Basic or Digest authentication by calling <link
-linkend="soup-session-remove-feature-by-type"><function>soup_session_remove_feature_by_type</function></link>
-on <link linkend="SOUP-TYPE-AUTH-BASIC:CAPS"><literal>SOUP_TYPE_AUTH_BASIC</literal></link>
-or <link linkend="SOUP-TYPE-AUTH-DIGEST:CAPS"><literal>SOUP_TYPE_AUTH_DIGEST</literal></link>.)
-</para>
-
-</refsect2>
-
-<refsect2>
-<title>Multi-threaded usage</title>
-
-<para>
-A <link linkend="SoupSession"><type>SoupSession</type></link> can be
-used from multiple threads. However, if you are using the async APIs,
-then each thread you use the session from must have its own
-thread-default <link linkend="GMainContext"><type>GMainContext</type></link>.
-</para>
-
-<para>
-<link linkend="SoupMessage"><type>SoupMessage</type></link> is
-<emphasis>not</emphasis> thread-safe, so once you send a message on
-the session, you must not interact with it from any thread other than
-the one where it was sent.
-</para>
-
-</refsect2>
-
-<refsect2>
-<title>Sample Programs</title>
-
-<para>
-A few sample programs are available in the
-<application>libsoup</application> sources, in the
-<literal>examples</literal> directory:
-</para>
-
-<itemizedlist>
- <listitem><para>
- <emphasis role="bold"><literal>get</literal></emphasis> is a simple command-line
- HTTP GET utility using the asynchronous API.
- </para></listitem>
-
- <listitem><para>
- <emphasis role="bold"><literal>simple-proxy</literal></emphasis> uses both the
- client and server APIs to create a simple (and not very
- RFC-compliant) proxy server.
- </para></listitem>
-</itemizedlist>
-
-<para>
-More complicated examples are available in GNOME git.
-</para>
-
-</refsect2>
-
-</refentry>
diff --git a/docs/reference/gtk-markdown-to-docbook.py b/docs/reference/gtk-markdown-to-docbook.py
new file mode 100755
index 00000000..25274116
--- /dev/null
+++ b/docs/reference/gtk-markdown-to-docbook.py
@@ -0,0 +1,201 @@
+#!/usr/bin/python3
+#
+# Call pandoc to convert markdown to docbook, then expand gtk-doc
+# abbreviations (|[ ]|, function(), #object, %constant, etc)
+
+# Upstream: https://gitlab.gnome.org/GNOME/gtk/-/blob/master/docs/reference/gtk/gtk-markdown-to-docbook
+
+import sys
+import re
+import tempfile
+import os.path
+import subprocess
+
+# The following code is taken from gtk-doc
+
+def ExpandAbbreviations(symbol, text):
+ # Hack!
+ # Strip xlink namespace from hrefs since pandoc insists on
+ # inserting them, and namespace setup doesn't transfer across
+ # xi:include.
+ # Yay for XML!
+ text = re.sub('xlink:href', 'href', text)
+
+ # Convert '@param()'
+ text = re.sub(r'(\A|[^\\])\@(\w+((\.|->)\w+)*)\s*\(\)', r'\1<parameter>\2()</parameter>', text)
+
+ # Convert 'function()' or 'macro()'.
+ # if there is abc_*_def() we don't want to make a link to _def()
+ # FIXME: also handle abc(def(....)) : but that would need to be done recursively :/
+ def f1(m):
+ return m.group(1) + MakeXRef(m.group(2), tagify(m.group(2) + "()", "function"))
+ text = re.sub(r'([^\*.\w])(\w+)\s*\(\)', f1, text)
+ # handle #Object.func()
+ text = re.sub(r'(\A|[^\\])#([\w\-:\.]+[\w]+)\s*\(\)', f1, text)
+
+ # Convert '@param', but not '\@param'.
+ text = re.sub(r'(\A|[^\\])\@(\w+((\.|->)\w+)*)', r'\1<parameter>\2</parameter>', text)
+ text = re.sub(r'/\\\@', r'\@', text)
+
+ # Convert '%constant', but not '\%constant'.
+ # Also allow negative numbers, e.g. %-1.
+ def f2(m):
+ return m.group(1) + MakeXRef(m.group(2), tagify(m.group(2), "literal"))
+
+ text = re.sub(r'(\A|[^\\])\%(-?\w+)', f2, text)
+ text = re.sub(r'\\\%', r'\%', text)
+
+ # Convert '#symbol', but not '\#symbol'.
+
+ # Only convert #foo after a space to avoid interfering with
+ # fragment identifiers in urls
+ def f3(m):
+ return m.group(1) + MakeHashXRef(m.group(2), "type")
+
+ text = re.sub(r'(\A|[ ])#([\w\-:\.]+[\w]+)', f3, text)
+ text = re.sub(r'\\#', '#', text)
+
+ return text
+
+# Standard C preprocessor directives, which we ignore for '#' abbreviations.
+PreProcessorDirectives = {
+ 'assert', 'define', 'elif', 'else', 'endif', 'error', 'if', 'ifdef', 'ifndef',
+ 'include', 'line', 'pragma', 'unassert', 'undef', 'warning'
+}
+
+def MakeHashXRef(symbol, tag):
+ text = symbol
+
+ # Check for things like '#include', '#define', and skip them.
+ if symbol in PreProcessorDirectives:
+ return "#%s" % symbol
+
+ # Get rid of special suffixes ('-struct','-enum').
+ text = re.sub(r'-struct$', '', text)
+ text = re.sub(r'-enum$', '', text)
+
+ # If the symbol is in the form "Object::signal", then change the symbol to
+ # "Object-signal" and use "signal" as the text.
+ if '::' in symbol:
+ o, s = symbol.split('::', 1)
+ symbol = '%s-%s' % (o, s)
+ text = u'“' + s + u'”'
+
+ # If the symbol is in the form "Object:property", then change the symbol to
+ # "Object--property" and use "property" as the text.
+ if ':' in symbol:
+ o, p = symbol.split(':', 1)
+ symbol = '%s--%s' % (o, p)
+ text = u'“' + p + u'”'
+
+ if tag != '':
+ text = tagify(text, tag)
+
+ return MakeXRef(symbol, text)
+
+def MakeXRef(symbol, text=None):
+ """This returns a cross-reference link to the given symbol.
+
+ Though it doesn't try to do this for a few standard C types that it knows
+ won't be in the documentation.
+
+ Args:
+ symbol (str): the symbol to try to create a XRef to.
+ text (str): text to put inside the XRef, defaults to symbol
+
+ Returns:
+ str: a docbook link
+ """
+ symbol = symbol.strip()
+ if not text:
+ text = symbol
+
+ # Get rid of special suffixes ('-struct','-enum').
+ text = re.sub(r'-struct$', '', text)
+ text = re.sub(r'-enum$', '', text)
+
+ if ' ' in symbol:
+ return text
+
+ symbol_id = CreateValidSGMLID(symbol)
+ return "<link linkend=\"%s\">%s</link>" % (symbol_id, text)
+
+def CreateValidSGMLID(xml_id):
+ """Creates a valid SGML 'id' from the given string.
+
+ According to http://www.w3.org/TR/html4/types.html#type-id "ID and NAME
+ tokens must begin with a letter ([A-Za-z]) and may be followed by any number
+ of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"),
+ and periods (".")."
+
+ When creating SGML IDS, we append ":CAPS" to all all-caps identifiers to
+ prevent name clashes (SGML ids are case-insensitive). (It basically never is
+ the case that mixed-case identifiers would collide.)
+
+ Args:
+ id (str): The text to be converted into a valid SGML id.
+
+ Returns:
+ str: The converted id.
+ """
+
+ # Special case, '_' would end up as '' so we use 'gettext-macro' instead.
+ if xml_id == '_':
+ return "gettext-macro"
+
+ xml_id = re.sub(r'[,;]', '', xml_id)
+ xml_id = re.sub(r'[_ ]', '-', xml_id)
+ xml_id = re.sub(r'^-+', '', xml_id)
+ xml_id = xml_id.replace('::', '-')
+ xml_id = xml_id.replace(':', '--')
+
+ # Append ":CAPS" to all all-caps identifiers
+ # FIXME: there are some inconsistencies here, we have index files containing e.g. TRUE--CAPS
+ if xml_id.isupper() and not xml_id.endswith('-CAPS'):
+ xml_id += ':CAPS'
+
+ return xml_id
+
+def tagify(text, elem):
+ # Adds a tag around some text.
+ # e.g tagify("Text", "literal") => "<literal>Text</literal>".
+ return '<' + elem + '>' + text + '</' + elem + '>'
+
+# End of gtk-doc excerpts
+
+MarkdownExtensions = {
+ '-auto_identifiers', # we use explicit identifiers where needed
+ '+header_attributes', # for explicit identifiers
+ '+blank_before_header', # helps with gtk-doc #Object abbreviations
+ '+compact_definition_lists', # to replace <variablelist>
+ '+pipe_tables',
+ '+backtick_code_blocks', # to replace |[ ]|
+ '+fenced_code_attributes', # to add language annotations
+ '-raw_html', # to escape literal tags like <child> in input
+ '+startnum', # to have interrupted lists in the q&a part
+}
+
+def ConvertToDocbook(infile, outfile):
+ basename = os.path.basename(infile)
+ if basename.startswith('section'):
+ division='section'
+ else:
+ division='chapter'
+ input_format = "markdown" + "".join(MarkdownExtensions)
+ output_format = "docbook4"
+ subprocess.check_call(["pandoc", infile, "-o", outfile,
+ "--from=" + input_format,
+ "--to=" + output_format,
+ "--top-level-division=" + division])
+
+def ExpandGtkDocAbbreviations(infile, outfile):
+ contents = open(infile, 'r', encoding='utf-8').read()
+ with open(outfile, 'w', encoding='utf-8') as out:
+ out.write(ExpandAbbreviations("file", contents))
+
+
+if __name__ == '__main__':
+ tmp = tempfile.mktemp()
+ ConvertToDocbook(sys.argv[1], tmp)
+ ExpandGtkDocAbbreviations(tmp, sys.argv[2])
+ os.remove(tmp)
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index a7463352..f528bedd 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -1,3 +1,5 @@
+fs = import('fs')
+
ignore_headers = [
'gconstructor.h',
'soup.h',
@@ -48,6 +50,31 @@ scan_args = [
glib_prefix = glib_dep.get_pkgconfig_variable('prefix')
glib_docpath = glib_prefix / 'share' / 'gtk-doc' / 'html'
+content_files = [
+ 'build-howto.xml',
+ 'server-howto.xml',
+]
+
+expand_content_md_files = [
+ 'client-howto.md',
+]
+
+# Needed for gtk-markdown-to-docbook.py
+pandoc = find_program('pandoc', required: true)
+expand_md = find_program('gtk-markdown-to-docbook.py')
+expand_md_targets = []
+foreach t : expand_content_md_files
+ content_files += custom_target(t,
+ input : [ t ],
+ output : [ fs.replace_suffix(t, '.xml') ],
+ command : [ expand_md, '@INPUT@', '@OUTPUT@'],
+ # At least in meson 0.55.3 this target wouldn't build even though its
+ # listed in the content_files
+ build_by_default : true,
+ )
+endforeach
+
+
gnome.gtkdoc('libsoup-3.0',
main_xml : 'libsoup-3.0-docs.xml',
src_dir : srcdir,
@@ -63,9 +90,5 @@ gnome.gtkdoc('libsoup-3.0',
],
dependencies : libsoup_dep,
install : true,
- content_files: [
- 'build-howto.xml',
- 'client-howto.xml',
- 'server-howto.xml'
- ]
+ content_files : content_files,
)