/** * REST API: WP_REST_Request class * * @package WordPress * @subpackage REST_API * @since 4.4.0 */ /** * Core class used to implement a REST request object. * * Contains data from the request, to be passed to the callback. * * Note: This implements ArrayAccess, and acts as an array of parameters when * used in that manner. It does not use ArrayObject (as we cannot rely on SPL), * so be aware it may have non-array behaviour in some cases. * * Note: When using features provided by ArrayAccess, be aware that WordPress deliberately * does not distinguish between arguments of the same name for different request methods. * For instance, in a request with `GET id=1` and `POST id=2`, `$request['id']` will equal * 2 (`POST`) not 1 (`GET`). For more precision between request methods, use * WP_REST_Request::get_body_params(), WP_REST_Request::get_url_params(), etc. * * @since 4.4.0 * * @see ArrayAccess */ class WP_REST_Request implements ArrayAccess { /** * HTTP method. * * @since 4.4.0 * @var string */ protected $method = ''; /** * Parameters passed to the request. * * These typically come from the `$_GET`, `$_POST` and `$_FILES` * superglobals when being created from the global scope. * * @since 4.4.0 * @var array Contains GET, POST and FILES keys mapping to arrays of data. */ protected $params; /** * HTTP headers for the request. * * @since 4.4.0 * @var array Map of key to value. Key is always lowercase, as per HTTP specification. */ protected $headers = array(); /** * Body data. * * @since 4.4.0 * @var string Binary data from the request. */ protected $body = null; /** * Route matched for the request. * * @since 4.4.0 * @var string */ protected $route; /** * Attributes (options) for the route that was matched. * * This is the options array used when the route was registered, typically * containing the callback as well as the valid methods for the route. * * @since 4.4.0 * @var array Attributes for the request. */ protected $attributes = array(); /** * Used to determine if the JSON data has been parsed yet. * * Allows lazy-parsing of JSON data where possible. * * @since 4.4.0 * @var bool */ protected $parsed_json = false; /** * Used to determine if the body data has been parsed yet. * * @since 4.4.0 * @var bool */ protected $parsed_body = false; /** * Constructor. * * @since 4.4.0 * * @param string $method Optional. Request method. Default empty. * @param string $route Optional. Request route. Default empty. * @param array $attributes Optional. Request attributes. Default empty array. */ public function __construct( $method = '', $route = '', $attributes = array() ) { $this->params = array( 'URL' => array(), 'GET' => array(), 'POST' => array(), 'FILES' => array(), // See parse_json_params. 'JSON' => null, 'defaults' => array(), ); $this->set_method( $method ); $this->set_route( $route ); $this->set_attributes( $attributes ); } /** * Retrieves the HTTP method for the request. * * @since 4.4.0 * * @return string HTTP method. */ public function get_method() { return $this->method; } /** * Sets HTTP method for the request. * * @since 4.4.0 * * @param string $method HTTP method. */ public function set_method( $method ) { $this->method = strtoupper( $method ); } /** * Retrieves all headers from the request. * * @since 4.4.0 * * @return array Map of key to value. Key is always lowercase, as per HTTP specification. */ public function get_headers() { return $this->headers; } /** * Canonicalizes the header name. * * Ensures that header names are always treated the same regardless of * source. Header names are always case insensitive. * * Note that we treat `-` (dashes) and `_` (underscores) as the same * character, as per header parsing rules in both Apache and nginx. * * @link https://stackoverflow.com/q/18185366 * @link https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#missing-disappearing-http-headers * @link https://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers * * @since 4.4.0 * @static * * @param string $key Header name. * @return string Canonicalized name. */ public static function canonicalize_header_name( $key ) { $key = strtolower( $key ); $key = str_replace( '-', '_', $key ); return $key; } /** * Retrieves the given header from the request. * * If the header has multiple values, they will be concatenated with a comma * as per the HTTP specification. Be aware that some non-compliant headers * (notably cookie headers) cannot be joined this way. * * @since 4.4.0 * * @param string $key Header name, will be canonicalized to lowercase. * @return string|null String value if set, null otherwise. */ public function get_header( $key ) { $key = $this->canonicalize_header_name( $key ); if ( ! isset( $this->headers[ $key ] ) ) { return null; } return implode( ',', $this->headers[ $key ] ); } /** * Retrieves header values from the request. * * @since 4.4.0 * * @param string $key Header name, will be canonicalized to lowercase. * @return array|null List of string values if set, null otherwise. */ public function get_header_as_array( $key ) { $key = $this->canonicalize_header_name( $key ); if ( ! isset( $this->headers[ $key ] ) ) { return null; } return $this->headers[ $key ]; } /** * Sets the header on request. * * @since 4.4.0 * * @param string $key Header name. * @param string $value Header value, or list of values. */ public function set_header( $key, $value ) { $key = $this->canonicalize_header_name( $key ); $value = (array) $value; $this->headers[ $key ] = $value; } /** * Appends a header value for the given header. * * @since 4.4.0 * * @param string $key Header name. * @param string $value Header value, or list of values. */ public function add_header( $key, $value ) { $key = $this->canonicalize_header_name( $key ); $value = (array) $value; if ( ! isset( $this->headers[ $key ] ) ) { $this->headers[ $key ] = array(); } $this->headers[ $key ] = array_merge( $this->headers[ $key ], $value ); } /** * Removes all values for a header. * * @since 4.4.0 * * @param string $key Header name. */ public function remove_header( $key ) { $key = $this->canonicalize_header_name( $key ); unset( $this->headers[ $key ] ); } /** * Sets headers on the request. * * @since 4.4.0 * * @param array $headers Map of header name to value. * @param bool $override If true, replace the request's headers. Otherwise, merge with existing. */ public function set_headers( $headers, $override = true ) { if ( true === $override ) { $this->headers = array(); } foreach ( $headers as $key => $value ) { $this->set_header( $key, $value ); } } /** * Retrieves the content-type of the request. * * @since 4.4.0 * * @return array Map containing 'value' and 'parameters' keys. */ public function get_content_type() { $value = $this->get_header( 'content-type' ); if ( empty( $value ) ) { return null; } $parameters = ''; if ( strpos( $value, ';' ) ) { list( $value, $parameters ) = explode( ';', $value, 2 ); } $value = strtolower( $value ); if ( strpos( $value, '/' ) === false ) { return null; } // Parse type and subtype out. list( $type, $subtype ) = explode( '/', $value, 2 ); $data = compact( 'value', 'type', 'subtype', 'parameters' ); $data = array_map( 'trim', $data ); return $data; } /** * Retrieves the parameter priority order. * * Used when checking parameters in get_param(). * * @since 4.4.0 * * @return array List of types to check, in order of priority. */ protected function get_parameter_order() { $order = array(); $content_type = $this->get_content_type(); if ( $content_type['value'] === 'application/json' ) { $order[] = 'JSON'; } $this->parse_json_params(); // Ensure we parse the body data. $body = $this->get_body(); if ( 'POST' !== $this->method && ! empty( $body ) ) { $this->parse_body_params(); } $accepts_body_data = array( 'POST', 'PUT', 'PATCH', 'DELETE' ); if ( in_array( $this->method, $accepts_body_data ) ) { $order[] = 'POST'; } $order[] = 'GET'; $order[] = 'URL'; $order[] = 'defaults'; /** * Filters the parameter order. * * The order affects which parameters are checked when using get_param() and family. * This acts similarly to PHP's `request_order` setting. * * @since 4.4.0 * * @param array $order { * An array of types to check, in order of priority. * * @param string $type The type to check. * } * @param WP_REST_Request $this The request object. */ return apply_filters( 'rest_request_parameter_order', $order, $this ); } /** * Retrieves a parameter from the request. * * @since 4.4.0 * * @param string $key Parameter name. * @return mixed|null Value if set, null otherwise. */ public function get_param( $key ) { $order = $this->get_parameter_order(); foreach ( $order as $type ) { // Determine if we have the parameter for this type. if ( isset( $this->params[ $type ][ $key ] ) ) { return $this->params[ $type ][ $key ]; } } return null; } /** * Sets a parameter on the request. * * @since 4.4.0 * * @param string $key Parameter name. * @param mixed $value Parameter value. */ public function set_param( $key, $value ) { $order = $this->get_parameter_order(); $this->params[ $order[0] ][ $key ] = $value; } /** * Retrieves merged parameters from the request. * * The equivalent of get_param(), but returns all parameters for the request. * Handles merging all the available values into a single array. * * @since 4.4.0 * * @return array Map of key to value. */ public function get_params() { $order = $this->get_parameter_order(); $order = array_reverse( $order, true ); $params = array(); foreach ( $order as $type ) { // array_merge / the "+" operator will mess up // numeric keys, so instead do a manual foreach. foreach ( (array) $this->params[ $type ] as $key => $value ) { $params[ $key ] = $value; } } return $params; } /** * Retrieves parameters from the route itself. * * These are parsed from the URL using the regex. * * @since 4.4.0 * * @return array Parameter map of key to value. */ public function get_url_params() { return $this->params['URL']; } /** * Sets parameters from the route. * * Typically, this is set after parsing the URL. * * @since 4.4.0 * * @param array $params Parameter map of key to value. */ public function set_url_params( $params ) { $this->params['URL'] = $params; } /** * Retrieves parameters from the query string. * * These are the parameters you'd typically find in `$_GET`. * * @since 4.4.0 * * @return array Parameter map of key to value */ public function get_query_params() { return $this->params['GET']; } /** * Sets parameters from the query string. * * Typically, this is set from `$_GET`. * * @since 4.4.0 * * @param array $params Parameter map of key to value. */ public function set_query_params( $params ) { $this->params['GET'] = $params; } /** * Retrieves parameters from the body. * * These are the parameters you'd typically find in `$_POST`. * * @since 4.4.0 * * @return array Parameter map of key to value. */ public function get_body_params() { return $this->params['POST']; } /** * Sets parameters from the body. * * Typically, this is set from `$_POST`. * * @since 4.4.0 * * @param array $params Parameter map of key to value. */ public function set_body_params( $params ) { $this->params['POST'] = $params; } /** * Retrieves multipart file parameters from the body. * * These are the parameters you'd typically find in `$_FILES`. * * @since 4.4.0 * * @return array Parameter map of key to value */ public function get_file_params() { return $this->params['FILES']; } /** * Sets multipart file parameters from the body. * * Typically, this is set from `$_FILES`. * * @since 4.4.0 * * @param array $params Parameter map of key to value. */ public function set_file_params( $params ) { $this->params['FILES'] = $params; } /** * Retrieves the default parameters. * * These are the parameters set in the route registration. * * @since 4.4.0 * * @return array Parameter map of key to value */ public function get_default_params() { return $this->params['defaults']; } /** * Sets default parameters. * * These are the parameters set in the route registration. * * @since 4.4.0 * * @param array $params Parameter map of key to value. */ public function set_default_params( $params ) { $this->params['defaults'] = $params; } /** * Retrieves the request body content. * * @since 4.4.0 * * @return string Binary data from the request body. */ public function get_body() { return $this->body; } /** * Sets body content. * * @since 4.4.0 * * @param string $data Binary data from the request body. */ public function set_body( $data ) { $this->body = $data; // Enable lazy parsing. $this->parsed_json = false; $this->parsed_body = false; $this->params['JSON'] = null; } /** * Retrieves the parameters from a JSON-formatted body. * * @since 4.4.0 * * @return array Parameter map of key to value. */ public function get_json_params() { // Ensure the parameters have been parsed out. $this->parse_json_params(); return $this->params['JSON']; } /** * Parses the JSON parameters. * * Avoids parsing the JSON data until we need to access it. * * @since 4.4.0 * @since 4.7.0 Returns error instance if value cannot be decoded. * @return true|WP_Error True if the JSON data was passed or no JSON data was provided, WP_Error if invalid JSON was passed. */ protected function parse_json_params() { if ( $this->parsed_json ) { return true; } $this->parsed_json = true; // Check that we actually got JSON. $content_type = $this->get_content_type(); if ( empty( $content_type ) || 'application/json' !== $content_type['value'] ) { return true; } $body = $this->get_body(); if ( empty( $body ) ) { return true; } $params = json_decode( $body, true ); /* * Check for a parsing error. * * Note that due to WP's JSON compatibility functions, json_last_error * might not be defined: https://core.trac.wordpress.org/ticket/27799 */ if ( null === $params && ( ! function_exists( 'json_last_error' ) || JSON_ERROR_NONE !== json_last_error() ) ) { // Ensure subsequent calls receive error instance. $this->parsed_json = false; $error_data = array( 'status' => WP_Http::BAD_REQUEST, ); if ( function_exists( 'json_last_error' ) ) { $error_data['json_error_code'] = json_last_error(); $error_data['json_error_message'] = json_last_error_msg(); } return new WP_Error( 'rest_invalid_json', __( 'Invalid JSON body passed.' ), $error_data ); } $this->params['JSON'] = $params; return true; } /** * Parses the request body parameters. * * Parses out URL-encoded bodies for request methods that aren't supported * natively by PHP. In PHP 5.x, only POST has these parsed automatically. * * @since 4.4.0 */ protected function parse_body_params() { if ( $this->parsed_body ) { return; } $this->parsed_body = true; /* * Check that we got URL-encoded. Treat a missing content-type as * URL-encoded for maximum compatibility. */ $content_type = $this->get_content_type(); if ( ! empty( $content_type ) && 'application/x-www-form-urlencoded' !== $content_type['value'] ) { return; } parse_str( $this->get_body(), $params ); /* * Amazingly, parse_str follows magic quote rules. Sigh. * * NOTE: Do not refactor to use `wp_unslash`. */ if ( get_magic_quotes_gpc() ) { $params = stripslashes_deep( $params ); } /* * Add to the POST parameters stored internally. If a user has already * set these manually (via `set_body_params`), don't override them. */ $this->params['POST'] = array_merge( $params, $this->params['POST'] ); } /** * Retrieves the route that matched the request. * * @since 4.4.0 * * @return string Route matching regex. */ public function get_route() { return $this->route; } /** * Sets the route that matched the request. * * @since 4.4.0 * * @param string $route Route matching regex. */ public function set_route( $route ) { $this->route = $route; } /** * Retrieves the attributes for the request. * * These are the options for the route that was matched. * * @since 4.4.0 * * @return array Attributes for the request. */ public function get_attributes() { return $this->attributes; } /** * Sets the attributes for the request. * * @since 4.4.0 * * @param array $attributes Attributes for the request. */ public function set_attributes( $attributes ) { $this->attributes = $attributes; } /** * Sanitizes (where possible) the params on the request. * * This is primarily based off the sanitize_callback param on each registered * argument. * * @since 4.4.0 * * @return true|WP_Error True if parameters were sanitized, WP_Error if an error occurred during sanitization. */ public function sanitize_params() { $attributes = $this->get_attributes(); // No arguments set, skip sanitizing. if ( empty( $attributes['args'] ) ) { return true; } $order = $this->get_parameter_order(); $invalid_params = array(); foreach ( $order as $type ) { if ( empty( $this->params[ $type ] ) ) { continue; } foreach ( $this->params[ $type ] as $key => $value ) { if ( ! isset( $attributes['args'][ $key ] ) ) { continue; } $param_args = $attributes['args'][ $key ]; // If the arg has a type but no sanitize_callback attribute, default to rest_parse_request_arg. if ( ! array_key_exists( 'sanitize_callback', $param_args ) && ! empty( $param_args['type'] ) ) { $param_args['sanitize_callback'] = 'rest_parse_request_arg'; } // If there's still no sanitize_callback, nothing to do here. if ( empty( $param_args['sanitize_callback'] ) ) { continue; } $sanitized_value = call_user_func( $param_args['sanitize_callback'], $value, $this, $key ); if ( is_wp_error( $sanitized_value ) ) { $invalid_params[ $key ] = $sanitized_value->get_error_message(); } else { $this->params[ $type ][ $key ] = $sanitized_value; } } } if ( $invalid_params ) { return new WP_Error( 'rest_invalid_param', sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), array( 'status' => 400, 'params' => $invalid_params ) ); } return true; } /** * Checks whether this request is valid according to its attributes. * * @since 4.4.0 * * @return bool|WP_Error True if there are no parameters to validate or if all pass validation, * WP_Error if required parameters are missing. */ public function has_valid_params() { // If JSON data was passed, check for errors. $json_error = $this->parse_json_params(); if ( is_wp_error( $json_error ) ) { return $json_error; } $attributes = $this->get_attributes(); $required = array(); // No arguments set, skip validation. if ( empty( $attributes['args'] ) ) { return true; } foreach ( $attributes['args'] as $key => $arg ) { $param = $this->get_param( $key ); if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) { $required[] = $key; } } if ( ! empty( $required ) ) { return new WP_Error( 'rest_missing_callback_param', sprintf( __( 'Missing parameter(s): %s' ), implode( ', ', $required ) ), array( 'status' => 400, 'params' => $required ) ); } /* * Check the validation callbacks for each registered arg. * * This is done after required checking as required checking is cheaper. */ $invalid_params = array(); foreach ( $attributes['args'] as $key => $arg ) { $param = $this->get_param( $key ); if ( null !== $param && ! empty( $arg['validate_callback'] ) ) { $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key ); if ( false === $valid_check ) { $invalid_params[ $key ] = __( 'Invalid parameter.' ); } if ( is_wp_error( $valid_check ) ) { $invalid_params[ $key ] = $valid_check->get_error_message(); } } } if ( $invalid_params ) { return new WP_Error( 'rest_invalid_param', sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), array( 'status' => 400, 'params' => $invalid_params ) ); } return true; } /** * Checks if a parameter is set. * * @since 4.4.0 * * @param string $offset Parameter name. * @return bool Whether the parameter is set. */ public function offsetExists( $offset ) { $order = $this->get_parameter_order(); foreach ( $order as $type ) { if ( isset( $this->params[ $type ][ $offset ] ) ) { return true; } } return false; } /** * Retrieves a parameter from the request. * * @since 4.4.0 * * @param string $offset Parameter name. * @return mixed|null Value if set, null otherwise. */ public function offsetGet( $offset ) { return $this->get_param( $offset ); } /** * Sets a parameter on the request. * * @since 4.4.0 * * @param string $offset Parameter name. * @param mixed $value Parameter value. */ public function offsetSet( $offset, $value ) { $this->set_param( $offset, $value ); } /** * Removes a parameter from the request. * * @since 4.4.0 * * @param string $offset Parameter name. */ public function offsetUnset( $offset ) { $order = $this->get_parameter_order(); // Remove the offset from every group. foreach ( $order as $type ) { unset( $this->params[ $type ][ $offset ] ); } } /** * Retrieves a WP_REST_Request object from a full URL. * * @static * @since 4.5.0 * * @param string $url URL with protocol, domain, path and query args. * @return WP_REST_Request|false WP_REST_Request object on success, false on failure. */ public static function from_url( $url ) { $bits = parse_url( $url ); $query_params = array(); if ( ! empty( $bits['query'] ) ) { wp_parse_str( $bits['query'], $query_params ); } $api_root = rest_url(); if ( get_option( 'permalink_structure' ) && 0 === strpos( $url, $api_root ) ) { // Pretty permalinks on, and URL is under the API root. $api_url_part = substr( $url, strlen( untrailingslashit( $api_root ) ) ); $route = parse_url( $api_url_part, PHP_URL_PATH ); } elseif ( ! empty( $query_params['rest_route'] ) ) { // ?rest_route=... set directly $route = $query_params['rest_route']; unset( $query_params['rest_route'] ); } $request = false; if ( ! empty( $route ) ) { $request = new WP_REST_Request( 'GET', $route ); $request->set_query_params( $query_params ); } /** * Filters the request generated from a URL. * * @since 4.5.0 * * @param WP_REST_Request|false $request Generated request object, or false if URL * could not be parsed. * @param string $url URL the request was generated from. */ return apply_filters( 'rest_request_from_url', $request, $url ); } } L’insoumise | Chloé Dubreuil

L’insoumise

Extrait audio

An de grâce 1348.

La guerre de Succession déchire la Bretagne et oppose le roi de France au monarque d’Angleterre. Le fléau de Dieu, cette Peste Noire qui décimera l’Europe, s’apprête à déferler. Maeve est née fille du vent, soumise à sa seule liberté, mais en ces temps chahutés par les hommes et la Providence, il ne fait pas bon s’affirmer au détriment des lois et de la religion.

Thibault De Quimerc’h, bâtard d’un seigneur breton, nommé lieutenant du bailli, reniera tout ce en quoi il croyait, tout ce devant quoi il s’était incliné par obsession de celle qu’il va devoir pourchasser.

De l’île de Sein à Paris, de Quimper à Rouen jusqu’aux confins d’un territoire que les vikings avaient nommé Vinland, le « pays des pâturages », dans l’actuel Canada, la fuite de Maeve la portera à quêter la paix et l’oubli de ses semblables. Mais quand l’amour cherche à vous confondre, il peut bouleverser bien des destinées…

“La lune était d’un bleu glacé, à ras d’écueils, comme emprise dans le givre des rochers. La sorceresse l’avait invoquée et la lune était venue, si bien venue que les habitants de l’île ne savaient plus s’ils étaient en train de tomber dans son giron ou si c’était elle qui fondait sur eux.”

L’insoumise est une grande fresque aventureuse, de ces romans qui font renaître sous nos yeux un monde oublié, malmené par la superstition, la trahison et la mort. Mais aussi par la la force de vie et la passion qui régissent ses personnages.

 

Chronique Promenades culturelles2

« Forcément, en lisant la quatrième de couverture, je ne pouvais que me frotter les mains, m’installer dans mon fauteuil préféré et oublier tout ce qu’il y avait autour de moi ! Et c’est bien, par ailleurs, ce qu’il s’est passé pendant ces heures de lecture ô combien agréables ! J’ai fait un bond dans le temps, j’ai voyagé, je me suis enrichie culturellement… Le tout en n’ayant pas bougé, si ce n’est mon index qui tournait les pages.

Je suis profondément admirative de l’écriture de Chloé Dubreuil. Elle arrive à m’embarquer, quel que soit le thème, dans l’histoire qu’elle traite et j’adore lorsque cela se conjugue avec la grande Histoire. Sa plume est alerte, on a toujours envie de savoir ce qu’il y aura sur l’autre page. En voyant l’heure tourner, je me disais à chaque fois : « Encore un peu ! », redoutant le moment où il faudrait laisser Maeve vaquer à ses occupations pour retourner moi-même à mon quotidien.

Bref, je pense que vous l’aurez compris : j’ai adoré ce livre ! »

Chronique Le boudoir du livre:

« Après avoir découvert Chloé Dubreuil avec « Moi, Eva Braun », je suis ravie de découvrir son autre roman « L’insoumise » qui va m’entraîner sur les traces de l’Inquisition et de la Peste Noire mais aussi des croyances et des hérésies. J’adore le style d’écriture de l’auteur qui m’emporte avec délices dans l’histoire. Le Moyen-Age n’est pas ma période de prédilection mais j’adore découvrir l’histoire surtout quand c’est à travers des romans bien écrit fourmillants d’informations historiques.

Je pensais que ma lecture allait durer plus longtemps quand j’ai vu la police d’écriture si petite hors il n’en fut rien vu que les chapitres sont courts et l’histoire intense. Un petit bijou d’histoire !

Une histoire qui se met lentement en place, peut-être un peu trop… A presque la fin de l’histoire, j’attends toujours la rencontre de Maeve et Thibault. Malgré cela, le style de l’auteur, les descriptions et le contexte historique font qu’on tourne les pages avec avidité pour en savoir plus sur cette période sombre de l’histoire de France. On a plaisir à suivre l’exode de Maeve et la recherche de celle-ci par Thibault, on espère qu’ils finiront par se rencontrer, s’expliquer et peut-être s’aimer…

Les sujets sont nombreux : la Peste Noire, la misère, la famine, les croyances, l’Inquisition, l’hérésie, les viols, le statut de la femme, les séismes…

On prend plaisir à découvrir cette période de l’histoire, on se laisse bercer par les mots de l’auteur qui savent si bien retranscrire l’histoire de France aux lecteurs.

Un second roman, plein de promesses qui nous fait découvrir ou redécouvrir l’histoire de la France ! »

Chronique Hellobook

« Très belle découverte pour ce roman !

Je n’ai pas l’habitude de lire des romans historiques, et malgré la difficulté que j’ai pu rencontrer, j’ai énormément aimé.

Nous allons suivre Maeve et Thibault en 1348, ce qui fait que nous avons un récit où l’on peut facilement s’immerger dedans. Le vocabulaire est d’époque, j’ai appris beaucoup de mots grâce à ce roman. De plus, Chloé DUBREUIL décrit tellement bien cette époque. On se rend bien compte qu’il y a un énorme travail qui a été fourni et ce n’est qu’un bonheur à lire.

De plus, à travers son récit, elle dénonce de nombreuses choses actuelles. Un d’entre eux m’a marqué : le viol ! Et je trouve ça important, car il ne s’agit pas seulement d’un récit pour divertir, mais aussi pour sensibiliser sur certaines choses.

J’ai beaucoup aimé suivre Maeve, c’est une femme très attachante. Quant à Thibault, au début, j’ai eu du mal à m’attacher à lui, mais plus le récit passe et plus il se révèle. J’ai aimé sa sincérité. De plus, j’ai senti un changement dans le récit. Lorsque c’est Maeve au centre, le récit est plus descriptif, plus doux et quand c’est Thibault, c’est plus rythmé. Je trouve ça vraiment chouette.

Même s’il y avait de nombreux mots que je ne connaissais pas, cela ne m’a pas gêné puisque l’auteure rend fluide le récit et les évènements. Il y a aussi du suspens jusqu’à la fin ! Et j’ai adoré la fin, c’est ce que j’attendais 🙂

Si vous aimez les romans historiques ou que vous souhaitez découvrir ce genre, je vous conseille ce roman ! »

 

Début du roman:

 Ils viennent… Île de Sayn13 février de l’an de grâce 1348 La lune était d’un bleu glacé, à ras d’écueils, comme emprise dans le givre des rochers. La sorceresse l’avait invoquée et la lune était venue, si bien venue que les habitants de l’île ne savaient plus s’ils étaient en train de tomber dans son giron ou si c’était elle qui fondait sur eux. L’astre nocturne affolait, terrifiait et pourtant chacun, en cette nuit d’Imbolc, se vouait à sa puissance. Un vent du nord-ouest faisait osciller les falots suspendus aux cornes de quatre vaches aux flancs maigres. En leur centre, les hommes et les femmes dansaient, s’effleuraient pour mieux se repousser, bouche muette, corps arqué, le regard portant loin au bas du tumulus, sur l’océan déchaîné. Et tous s’épuisaient dans cette Ronde de la Mer qui célébrait les Esprits des Eaux, sanctifiait la manne que la tempête ne manquerait pas d’apporter. Quel navire allait se drosser contre les récifs ? Cette nuit était celle de la lumière, de la purification, de la fertilité ; elle serait celle aussi de l’Ankou, serviteur de la Mort. Vie et mort ne feraient plus qu’une. L’éclat de la lune s’intensifia, elle allait avaler l’île et la mer. Les embruns fouettaient les visages, des remparts ruisselant d’eau se dressaient autour des granits, le raz bouillonnait. L’odeur âcre du varech crevait les cœurs. Les volutes du noroît faisaient claquer les manteaux de grosse bure. Tout n’était plus que furie à une lieue de l’ancien tertre druidique. La vieille Katell repoussa d’une main décharnée la capuche de sa pèlerine ; sa face apparut, creusée d’orbites aux iris du même bleu glacé que l’astre de la nuit. Sous la peau amincie se devinait le dessin des os frileux. Elle était la veuve dite Bandrui, la femme-forte qui appartenait au monde caché, celle dont on se méfiait, mais qu’on vénérait aussi, celle qui pouvait vous jeter un sort si vous lui mentiez ou la trompiez. Celle qui lisait les songes, avait le pouvoir de vous rendre invulnérable, d’évoquer les trépassés. La sorceresse de l’île-des-Sept-Sommeils : Katell la Sage. — Ils viennent ! Son regard dardait les ténèbres océanes, ses bras convulsaient dans la lueur des lanternes. La Ronde s’accéléra, hallucinée. Au clocher du prieuré une volée de cloches sonna lugubrement les matines : la mi-nuit était entamée. — Ils viennent, croassa une nouvelle fois Katell en se figeant soudain. Ses doigts tannés, tavelés, à la peau si fine qu’y transparaissait le réseau des veines, s’agrippèrent violemment à la manche d’une donzelle. Le front cerné d’une couronne d’ajoncs, cette dernière tournoyait, bondissait à l’entour de la vieille femme. Sa fièvre de bacchante empourprait ses pommettes. Une courtepointe de cheveux interminables serpentait entre ses seins sur la cotte nonchalamment lacée, caressait la courbe de ses reins à travers la brune futaine avant de se lover autour de son cou dénudé. Elle avait la beauté sauvage de son île, une blondeur ambrée. Il se dessinait en elle le creuset de toutes les âpretés, de toutes les voluptés. Elle était Maeve, elle était l’ivresse, parce que c’était cela que signifiait son nom. Maeve se figea immédiatement au contact de la main sur sa manche. L’ombre d’un albatros fendit le ciel au-dessus des deux femmes pour venir se poser à leurs pieds. Une plume virevolta avant de se fondre à la lande gelée. Le grand oiseau hua, faisant claquer son bec. Son cri fut couvert par les rugissements du vent. Seuls les mots de la vieille Katell, comme arrimés à un fil invisible, pouvaient avoir pénétré les esprits. De l’autre côté de l’anse, une masse sombre émergea des ténèbres de la mer, parut raser la lune énorme. Une nef dont la voile unique s’effilochait en lambeaux, un navire de cent tonneaux peut-être ; la manne que les habitants attendaient. Elle oscillait désespérément sur les flots, incapable de résister à l’attrait des récifs, à l’appel de la sorceresse. Les lamentations qui s’en échappaient retombaient dans le sourd hourvari des vagues. L’albatros battit des ailes, la Ronde se brisa. Comme brusquement extirpés de leur transe, les corps s’immobilisèrent, les bouches jusqu’ici muettes murmurèrent. Ils étaient de tous âges sous les chapes de laine protégées des embruns par la couche de cire dont celles-ci étaient enduites. Une trentaine de vilains qui n’attendaient plus qu’un ordre à présent. Un craquement formidable fracassa le râle de la terre. Le noroît sifflait.
 — Allez ! chuchota Katell. Débarrassant les vaches des lanternes dont les oscillations avaient servi à attirer le navire en détresse, les manants s’en allèrent afin de récupérer leur trésor. L’albatros s’envola dans leur sillage. La blancheur de givre de la lande se grisa dès qu’ils eurent descendu le tertre. Il n’y avait plus que le bleuté de la lune pour éclairer maintenant la vieille Katell… et Maeve demeurée auprès d’elle. Sa poigne s’éternisait sur le bras de la donzelle. Celle-ci ne chercha pas à s’esquiver. La silhouette d’un jeune pêcheur réapparut à mi-pente du tumulus. Le bonnet de laine rouge qui emboîtait son crâne dominait des traits façonnés à la serpe. Il boitait, mais était grand et large d’épaules sous le mantel qui le couvrait tout entier. La jeune femme lui cria : — Va-t-en, Brann ! Va-t-en avec eux, je vous rejoindrai plus tard… Il sembla hésiter un instant – sans doute avait-il ressenti au cours de la Ronde le désir trouble monter en Maeve, la sève de son désir qui exigeait en cette fête d’Imbolc de renaître à la vie après avoir donné la mort -, mais il connaissait sa cousine, elle ne se rebellerait pas contre la main qui restait plaquée à sa manche. Elle était de la même engeance que Katell : fille du vent et de la mer. Elles commandaient, ils obéissaient. Brann obéit. Était-ce pour montrer qu’il consentait à sa demande ? Il souleva haut sa lanterne où se consumait un moignon de suif puis la rabattit et fit volte-face. La couche d’humus, rigidifiée par le gel, craqua sous ses sabots. Une enfilade de falots s’était engagée dans la langue de terre étroite et basse qui reliait les deux côtés de l’anse. Des bordées d’écume échevelaient les récifs, la population devrait attendre que la tempête se calmât pour approcher le lieu du naufrage. Restait à la vieille Katell de convaincre les Esprits des Eaux de se retirer. Elle ne le fit pas tout de suite pourtant, une ombre endeuillait son regard. — Ils viennent, Maeve. Ses mots se répétaient. Pourquoi ? Le noroît la fit vaciller, elle avait l’air si fragile tout à coup ! La jeune femme l’entoura de ses bras, elle sentit les os sous la peau, huma les relents de peur, prémices de ce qui était à venir : supplice, souffrances. Exil. Maeve se raidit. L’aïeule n’avait jamais eu peur. De rien ni de quiconque.
Mais cette fois était différente, la jeune femme sut que le mal prendrait sous peu possession de l’île. Sa voix crachota : — Par Dieu, qui ? — Des hommes à l’âme tourmentée et qui nous disent plus cruelles que la mort, infectées par l’hérésie de la sorcellerie. — Celle-ci n’existe pas. — Leur ignorance les guide. Ils viennent. Maeve secoua vigoureusement la tête, l’or irisé de sa chevelure balaya sa poitrine. Contrairement à la plupart des habitants de l’île dehors cette nuit, elle ne portait pas de pèlerine pour la protéger du froid, juste une cotte aux manches amples et un surcot de même toile brune, ceinturé par un cordon de cuir entrelacé. Maeve aimait la morsure de l’air dans les replis de sa chair, c’était son plaisir. L’un parmi d’autres. Et personne ne s’élèverait contre ce qu’elle était. — Nous ne les laisserons pas nous offenser, Katell. Qu’ils viennent et ces marauds le regretteront… Sur le visage parcheminé de la vieille femme s’esquissa un drôle de sourire, d’une douceur enfantine, ouvert sur des incisives ébréchées, jaunies par le temps, et qui tranchait sur la dureté des iris d’un bleu de glace. — Tu as raison, ma fille, l’Ankou de la Mer nous protégera. Le halo des lanternes de bois s’éteignait au loin et s’éteignait avec lui l’éclat surnaturel de la lune. L’astre était si proche encore, cadrant l’horizon et ses récifs où un navire s’était éventré. Brisée de corps et de bois. La farandole de falots attendait. Seul le fracas des vagues se faisait entendre à présent. Au sommet du tumulus, deux femmes se détachèrent l’une de l’autre. Hérissées entre terre et ciel, elles allaient soumettre la tempête. Une paire d’ailes blanches les survola. L’île leur appartenait.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Required fields are marked *