Comment je valide et convertit des documents HTML trop chargés ou provenant de Microsoft Word en HTML valide et simplifié

Description

Cette procédure est faite optimiser la conversion document word en html, spécialement ceux qui sont généré avec beaucoup de «tagsoup» en en simplifier a sa plus simple expression html. Valide.

Sauter à la Procédure

Exemple

Avant
<h2 class="Standard" dir="ltr" lang="fr-FR" style="margin-top: 0; margin-bottom: 0; text-align: center;" xml:lang="fr-FR">
  <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">TERMS AND CONDITIONS OF 1</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">‐</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">YEAR OR 30</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">‐</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">DAY ACCESS AND USE</span>
</h2>

<span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">OF THE SERVICE BY SUBSCRIBERS</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">SECTION 1</span> <span lang="en-CA" style="font-weight: bold; font-size: 16.0px;" xml:lang="en-CA">PURPOSE OF THE SERVICE</span>
Après
<h2>TERMS AND CONDITIONS OF 1 ‐ YEAR OR 30 ‐ DAY ACCESS AND USE</h2>

<span>OF THE SERVICE BY SUBSCRIBERS SECTION 1 PURPOSE OF THE SERVICE</span> 

 

Inspiration et pistes

  1. Convertir de format document en ligne de commandeDe Word2000 vers HTML, voir UNOCONV http://dag.wieers.com/home-made/unoconv/#download

 

 

 

Procédure 

Version abstraite

  1. Utiliser Open Office (ou peu importe) pour exporter le document en HTML

* Purifier via HTMLTidy
* Nettoyer les attributs inutiles avec la classe htmLawed 

Use cases

Document texte seulement

  • Pas de formulaire, ni images, etc
  • Idéal pour un document légal, par exemple.

Étapes concrètes:

  1. A partir du fichier HTML généré exemple: Fichier appelé “1.1.2.en.html”

* Extraire le fichier htmLawed.zip
 
cd ~
mkdir htmlawed
mv htmLawed.zip htmlawed/
cd htmlawed
unzip htmLawed.zip

Passer au travers de la classe htmLawed

require('htmLawed.php');
$config = array('safe'=>1,'elements'=>'a,em,strong,p,ul,li,ol,h1,h2,h3,h4,h5,div,tr,td,table','deny_attribute'=>'* -title -href');
$out = htmLawed(file_get_contents('in.html'), $config);
echo $out;

Rouler le script. Déplacer le fichier a utiliser, puis exécuter le script pour en générer dans out.html

cp ~/1.1.2.en.tidy.html in.html
php cleanup.php &gt; out.html</pre>

Rouler Tidy. Normaliser le fichier “1.1.2.en.html”, Nettoyer les balises, minuscules, etc

tidy --drop-font-tags 1 --logical-emphasis 1 --clean 1 --merge-spans 1 --show-body-only 1 --output-xhtml 1 --word-2000 1 --indent "auto" --char-encoding "utf8" --indent-spaces "2" --wrap "90" 1.1.2.en.html &gt; 1.1.2.en.tidy.html

tada!

Précautions

Ordre d’exécution des tâches

Remarque:

J’ai essayé de passer Tidy avant htmLawed et j’ai réalisé que le nettoyage de htmLawed est assez drastique et que Tidy rend le code plus propre. Sans oublier que htmLawed peut générer des balises vides que Tidy va éliminer.

Références

  1. Options Tidy
  2. htmLawed Documentation a PHP Html purification Class
    1. original documentation
    2. Example settings

Ma critique sur l’intégration du site a25.com

Dans la série “Revue de code en Intégration web” qui se veut une série de remarques pour améliorer le résultat final du site je commence avec ce premier site.

Le site a25.com est un service web qui sert a amasser les paiements dus pour l’usage du pont de l’Autoroute 25. Une caméra capture les plaques d’immatriculation et envoit une enveloppe réclamant son dû.

 

Quoi que très fonctionnel comme service, j’ai pas pu m’empêcher de regarder le code HTML envoyé aux visiteurs et remarquer ces détails.

Ce qui m’a frappé et incité a faire ces remarques est la mention “Optimisé pour Internet Explorer“. J’ai tout de suite eu un flashback des années 2000.

 

Mes observations

Remarque Je suis conscient que la réalisation du site a pu être fait a la sauvette et qu’il y a peut être eu à faire plusieurs coins ronds, c’est malheureusement monaie courrante dans l’industrie du web. Le choix technologique imposé par la politique plutôt que l’expérience de celui réalisant le site peut aussi affecter la qualité. Pour contre-carrer les argumentaires vides, pourquoi ne pas s’armer en explications. Le but est constructif après tout :)

 

Annonce pour support spécifique Internet Explorer

Nous sommes en 2012. Le HTML5 est supporté et possible depuis 2009… même sous IE6.

Les conventions de navigation et la fonte du contenu par défaut est beaucoup trop petite, plus petite que la moyenne des sites

 

Données tableau en image

Votre page tarifs donne des données tabulaire en image

Quoi que très jolie image, des données alignées par des colones, un tableau est là pour ordonner des données par colones et rangées. La synthèse peut très mal se faire sur une image.

Je pourrai sortir l’argument de l’Accessibilité et vous allez me dire, un mal-voyant ne peut pas conduire. Peu importe. Une image c’est pour décorer.

 

Changement de pages en AJAX et URLs

Les pages changent sous en AJAX (exemple #joindre dans l’adresse) plutot qu’un URL unique par contenu avec adressage de langue au URL.

Si vous voulez réellement faire un changement à la AJAX, vous pouvez simplement capturer le clic sur certains liens (par usage d’une classe qui décrit le fonctionnement) puis un court bloc jQuery pourrait s’occuper de capturer le clic et changer le DOM via un $.ajax

Le pire n’est pas que si votre visiteur n’utilise pas javascript pour des prétextes de sécurité. Mais aussi le SEO, vous perdez du contenu et ce sont pourtant des pages légitimes avec contenus qui vaudraient la peine d’être indexés et augumenteraient la qualité du point de vue SEO.

J’insiste sur ce fait car c’est du contenu référence. Un cas acceptable serait si ce serait du contenu en relation au temps (comme twitter par exemple) ou une vue spécifique a un utilisateur dans une application web.

 

Le SEO. Je l’ai dit

D’accord, le SEO sert a optimiser la trouvabilité d’un document parmi plusieurs. Chaque partie d’un URI a son utilité. Jonas Jacek le décrit bien dans son billet à ce sujet.

Je ne suis pas un expert du SEO, mais regardons plus loin que cet argument. peut etre la valeut du mot dans le URL ou simplement un mauvais usage detourné.

Un URI dans ses composantes represente chaque element a son role. e.g. http://host/corps/du/uri?query=value#anchor alors le document pour me contacter serait dans le corps du url.

Le #hash dans le URL est normalement la pour representer un anchor (partie) dans UN document (parmi plusieurs) pas une page complete. Le Javascript supporte le history avec le #hash. Mais encore. Il degrade sans JS. Cool. Un hash est pour un anchor.

Pourquoi donc ne pas faire <div onclick="javascript:window.location=http://foo.bar/">Hola!</div>?. Parce que le <a /> sert a faire un lien. Meme chose pour un anchor.

 

Fichiers attachés utilisé pour toutes les “sauces”

Vos fichiers attachés sont des fichiers PDF plutot que d’être vers d’autres pages, encore perte de contenu cohérent et un signe d’echec d’usage d’un site web (un PDF est bon sur le web pour des formulaires ou on nécécessite impression et signature)

Les fichiers attachés ont des noms sous forme de phrases avec caractères spéciaux, nous ne sommes plus a l’époque du 8.3 (exemple de nom à l’époque: MONFIC~1.BMP) mais quand même.

Un fichier avec un nom résumé de deux trois mots ne nuit pas. Investissez plutôt du temps sur les méta données avant conversion au PDF et éviter d’avoir une tonne de fichiers au titre “Document Microsoft Word”.

 

CSS sur-spécifique avec utilisation de #ID inutile

Les fichiers CSS et Javascript ne sont pas minifiés et/ou combinés, vous pourriez sauver du temps de chargement

Mais à mon opinion, la structure CSS démontre un certain manque de maîtrise de la structure en intégration de votre développeur web. Je ne suis pas parfait moi même, j’ai fait mon lot d’erreur, mais j’aimerai vous mettre au courrant qu’il y a beaucoup d’ouvrages et documentation sur les pratiques d’aujourd’hui que votre site pourrait profiter. La facilité de rendre votre site fonctionnel pour le mobile n’est qu’un parmi tant d’autres avantages.

Avez-vous déjà entendu parler de OOCSS ou SMACSS?

Fin

Voilà, c’est mon premier billet dans la série de “Revue de code en Intégration web”. J’espère que vous trouverez inspirant

What is Cloud computing when it is related to web application

During the discussion, the contributor persisted on knowing what would be considered and thresholds to use some kind of push-button-scaling.

Knowing his context, a unzipped install CMS with a buch of plugins I felt the urge to explain that there is not always need to get a bigger server capacity. Here is an overview of what I mean when I talk about cloud computing and continuous integration.

The E-Mail

Let’s talk about cloud! 

I mean in the web application hosting realm. Not the storage (Google Drive, Dropbox) or software as a service (Salesforce, Basecamp).

Let’s talk about a use case before and my own experience.

My former company Evocatio Solutions technologiques manage a pretty large site at the domain uda.ca.

The use-case on my recent experience

This is a complete business management web application that manages an union who represents french speaking artists in north america (mostly residents of Canada). We built a complete web application that manages many aspects an artist needs to represent themselves and be found. A big part of it is a 140 tables worth of artist description listing details as small a hair length and types of musical instruments to voice tones. It also manages renewal, communication with agencies, portfolios, and management of contracts with managers and more.

Not to forget the very heavy databases queries we generate to search, for example: <example>An asian woman with white hair playing yuku lélé who can pilot helicopter AND ride motorcycle …</example>

Yes. Database queries get very big, very quickly. Not only in the search engine I described, but through all the features.

That, to my opinion, is heavy. Also considering that that Artist’s Union has several thousand members.

This information is on top of my head, please do not take this into real numbers, I did not look the latest deployment needs.  But for the server side, it only uses a simple Virtual machine with 4Gb of RAM give or take.

That is my point about expanding hosting without optimizing stuff around.

What your web application has to consider then

Amazon and other Cloud service is about mostly about automated server deployment.

But the powerful offering of “scale tour application” with computing cubes that automatically scales requires more than just nodes.

It requires the code (here again) to support:

  • multiple databases hosts and types support (Cassandra, Solr, MySQL) specialized for the type of data to store
  • User upload files replication
  • Database/Keystore (CouchDB, Mongo)

All spanable on multiple hosts by a mere change of one configuration file.

The code itself should:

  • Be deployable by a simple phing/ant/nant task
  • Hosted on a NAS mount that you could create an other machine and use when time of computing need happens

All this (for some parts) is what is called Continuous integration (Wikipedia) some deployment strategies (also here and this blog post too), and most of the time. It’s not just the continuity and automation that matters, but the underlying deployment mechanism can be provided by third parties, like Heroku and many others.

Some steps you can look for if you feel your web application is slow

It all started by a discussion thread in a mailing list. A guy who developed a shopping cart and payment gateway using a CMS.

My first reflex, before thinking of scaling the server I thought I should give some pointers on things that can hog the site, before going to think to scaling solutions.

That was all before continuing talking on the cloud that I answered later that I answered later on that blog post.

The thread started as follows:

> (…) I have a Magento modified into a e-commerce site (…) that
> me and my client feels slow, my client has asked about Amazon hosting. They
> do everything else, CDN, the works, shouldn’t their hosting
> be superior?
>
> What would be worth for a test drive, I’d say, if you think
> your site’s performance issues can be addressed by
> throwing CPU, memory, storage, etc (…)

My answer

I doubt that you need bigger hosting for a e-commerce site.

Not for the “first  thing to improve performance” action point though.

Unless your site has to provide (real) HEAVY traffic. Non stop.

It is most likely something somewhere down the execution of the web application that requires to be looked at.

Performance slowing factors

Some common explanations for slow execution time could be basically due because of one or many of the following:

  1. Network latendy
  2. Process communication problem (connection, zombie process, etc)
  3. Application architecture
  4. Hardware/Software performance

Now talking about application architecture.  This one can be a real can of worms!

Some Application architecture bottlenecks

I currently seriously doubt the order here should matter. But this is the ones that pop into my mind at first.

  1. Web service/database queries/files access across network … packetloss could also be a cause
  2. Database queries processing that could require some well picked indexes
  3. Heavy queries and frequent read write or some sleep() hidden here and there to wait other result set
  4. No http/view caching
  5. No code caching/precompiled code at all (can be config, whatever that can be pre-compiled and served into basic arrays of calculated data frequently used)
  6. No memcached/keystore service
  7. No read-only data store

An analogy

So. To my opinion, if you are using a “unpack to install” web based software such as WordPress, then add plusings without testing and looking if all of them works well together.

You are likely to be trying to make a Cheetah kitten into a humanoid Android.

As in,  you can install a lot of metal patches. Doesn’t mean it will have a full AI system and be self sustainable.

That is to illustrate, what it is lie, you should look to alternatives. At least with something closer to a droid :)

Seriously enough.

My professionnal recommendation would be to work with each “application architecture buttolenecks” proposal list before “going cloud”

My answer to People asking whether they should or not use a framework on their programming language

I think that whatever we do when it is related to programming, the main objective is that the piece of functionality is to be used.   Unless of what you are doing is a tool for developers, or a programming language.  To my opinion, you should be concentrated in the functionality itself. Wathever the reason of your application, it is to be used. Otherwise it’s waste. Isn’t it?

This is not because it is NOT a good thing to do.  Just that there is a lot of good framework and libraries out there.  Why diluting the efforts when you could contribute and make something good with your own goodness.

Here is what I answered

The question

Am I the only one not beaing lover of PHP frameworks, asked in a PHP Developers group on LinkedIn.

My answer:

Flame wars. again.

I read an article by Derek Strobe on his blog, discussing  the Not Invented Here mentality and I actually think the same.

Why not focussing on: getting the best you can get and/or not-reinvent-the-weel.

What is the important, build the developer tool, or build the fatures the client pays us for.

Framework or whatever programmer use, should only help us for at least those two:

  1. Have a standard that you are not the only one to know (documentation, and or can suck. sorry.).
  2. Do the features the client wants, with the thing that makes you shine most.
  3. Educate the client for the features, not the tool. You are the expert, that’s why they hire us.

For me, framework or not. Building a framework for myself, it would suck. I prefer to abide by the framework structure to it’s best recommended. And contribute to the documentation (or features) in return.

Using a framework, it’s name, version or not use one. It all comes back to the structure the code you have to work with (from either source, legacy, framework, current)

If you have a method with more than 10 lines… it’s procedural in a class. Like halloween.

A last thing about: I did my framework, and I still think it’s the best.

Nobody will make me really believe that it’s better than a more than dozen people contributing to quality and psr-0 compliant classes re-usable libraries.

That’s what happened with Symfony 2 for me.

I dare you to to find a fully fledged structure **in PHP** that already implements: AOP, Event listeners, Namespaces (like Java import), Closures, Dependency Injection, and close to the root of the language.

One last thing, if you want to distribute:

You should also look at Composer. A way to distribute your package.

Project manifest: Content management publishing platform to implement Accessibility, Semantic markup, and ease web publishing

This is my own manifest on how I think today’s CMS should be architectured. I need to find a proper name on the idea and/or possibly join one of the project that exists. If you understand french, I created the equivalent post on that page.

Layers:

  1. Data extraction layer, takes from…  xml, rss, github, wordpress database, drupal database, REST service and pass to layer 2
  2. Data filtering, normalization and serialization. Providing adapters for normalization, caching, and expose a gateway for third layer
  3. Content transportation layer of normalized/serialized content transport mechanism
  4. (need to coin term here)  “Container”  providing:
    1. Placeholders for content coming from layer 3
    2. Automated creation of HTML blocks and patterns following semantic markup and accessibility principles
    3. Logicless templating for easy usage for integrators who do not need to learn programming

Advantages on that approach

I truly think that with such mechanism, we could adapt content in a semantic manner and be able to abstract content edition, theme.

Much is here to say about it. I am leaving this as it is now and I’ll update relations and ideas as I spend time on it. Contact me if you have questions.

Nouveau projet: Refonte de mon site en conservant WordPress comme back-office, mais Symfony2/Doctrine2/Twig pour générer les vues

J’ai décidé de refaire mon site web. J’aime bien utiliser le backend de WordPress mais je n’aime pas utiliser ce qui y est fourni coté code pour faire le “frontend” d’un site web.

Il s’agit d’une première élaboration brute des concepts qui motivent mon choix d’implémentation.

Je suis en plein effort d’élaboration des requis et si vous voulez voir le pendant rédigé en anglais, j’ai publié ici.

But ultime des fonctionnalités

  • Utiliser l’administration de WordPress pour gerer le contenu
  • Avoir la latitude de Symfony2/Twig/Doctrine2 pour gerer le contenu e le code
  • Aggreger le contenu provenant de d’autres sources (marqué favoris de Google reader, Tweets, status divers de d’autres services: forrst, github, geeklist, etc)
  • Creer une libraire de macros Twig qui genere du HTML selon les formats de Schema.org
  • Contribuer a un outil qui pourraitservir aux webmestres qui desirent utiliser WordPress mais qui veulent ce que Twig/Doctrine offre.

Fonctionnalités prévues

  • Extraire, purifier/harmoniser le html, et convertir les billets de blog en format markdown (version cachée)
  • Utilisation des billets format markdown comme cache
  • Conversion markdown a html pour consultation
  • Commit-push des billets format markdown dans repository git configurable
  • Processus Migration données WordPress (galleries, commentaires) vers version markdown
  • Suite de macros reutilisable au format schema.org qui n’est pas lié a la base de donné
  • Conversion de format markdown avec annotations des medias, publication, lien canonical, etc)

Lignes guides d’un CMS idéal

  • Le contenu doit être libéré de son système de conteneur.
  • Le contenu doit être le plus vanille possible, le plus près possible du texte brut.
  • annotation dans le contenu (titre, lien, gras, italique) doit être écrit dans un format texte SEULEMENT (markdown, reStructured, Textile). Permet l’édition sans avoir a maîtriser toutes les nuances du balisage (markup html) qui est requis pour l’accessibilité, ou la sémantique
  • Les éléments de contenus sont des blocs de HTML distincts du contenur qui l’affiche. Dans le sens que la page et le style doit être aussi flexible que possible et que l’intégrateur ne soit pas emêtré dans des syntaxes abstraites
  • Le système doit permettre d’utiliser plusieurs fournisseurs de contenu (une base de donnée WordPress, Drupal, un repository Git, etc)
  • Le système doit permettre de comprendre l’entité de contenu et générer automatiquement le bloc HTML sémantique approprié pour être affiché dans son conteneur

Le Code

J’utilise présentement mon implémentation en lisant la base de donnée WordPress de mon site, et utiliser Symfony2/Doctrine2/Twig pour le “frontend”. On peut voir la différence de vitesse d’exécution et le look entre beta.renoirboulannger.com, à l’inverse de la version hébergée sur le domaine non “beta”.

Fork me on GitHub

Résumé d’une discussion et notes sur ce que j’aurai aimé comprendre plus rapidement lors de mon apprentissage Symfony2 et Doctrine2

Durant les derniers mois j’ai lu et relu la documentation de Symfony2 et voici quelques éléments qui ont attiré mon attention et que j’aimerai partager avec vous.

L’un des concepts architecturaux clé faisant que Symfony2 se démarque des autres frameworks PHP est l’usage des concepts de la programmation orienté aspect (AOP).

L’idée directrice de la programmation orienté aspect est d’éviter au maximum dépendances fonctionnelles communes (appelé dépendances transversales). Ces fonctionnalités fréquentes comme l’accès a la base de donnée, par exemple. La manière de séparer ces besoins est de notamment utiliser les commentaires des classes et d’y ajouter des fonctionnalités avant ou apreès les méthodes. C’est ce qu’on appelle des Intercepteurs et des Pointcut.

Ce type d’architecture demande une capacité de compilation de code supporté par le langage de programmation.

Nous savons que PHP n’est pas un langage compilé. Il y a des alternatives, mais ce n’est pas comme ce qui peut être fait avec AspectJ et Spring AOP, pour Java, et ce qu’il existe pour le C#.

Pourtant, depuis peu, avec l’avènement de l’implémentation des normes PSR-x, et des librairies de génération de code. C’est maintenant possible.

Beaucoup de changements sont a venir dans le monde des CMS et pour beaucoup d’autres projets.

Le mouvement est tellement fort que les communautés de d’autres projets libres s’impliquent: Ce projet s’appelle le “PHP Framework Interoperability group” Il y a notamment le projet Magento, Drupal, Joomla!, MidgardTypo3 (Flow3), voir la liste des groupes et du draft sur github.

Donc, ces choses que j’ai beaucoup apprécié lors de ma découverte de Symfony2.

Conversion des entités et éviter requêtes à la base de donnée

Comme la documentation le décrit, le travail d’une méthode de contrôleur est de convertir la requête qui lui a été demandée d’exécuter (via le routing). L’utilisation des patterns AOP vient permettre de maigrir énormément.

Au lieu d’utiliser manuellement les Exception, le render, et les appels à Doctrine faits “à bras” dans le corps de la méthode comme suit.

namespace PSS\Bundle\BlogBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 
/**
 * Blog Controller
 **/
class BlogController extends Controller
{
 
    /**
     * @Route("/{slug}")
     */
    public function showAction($slug)
    {
        $entityManager = $this-&gt;get('doctrine.orm.entity_manager');
        try {
            $post = $entityManager
                -&gt;getRepository('PSS\Bundle\BlogBundle\Entity\Post')
                -&gt;findPublishedPostOrPage($slug);
        } catch (\Doctrine\ORM\NoResultException $exception) {
            throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('Page Not Found');
 
        }
 
        return $this-&gt;render('PSSBlogBundle:Blog:show.html.twig', array('post' =&gt; $post));
    }
}

On peut sauver des lignes de code et utiliser les @annotation pour définir le Template qui sera utilisé, va aller chercher l’entrée dans la base de donnée pour nous (via le @ParamConverter), retourner une Exception si elle existe pas.

Vous pouvez voir plus en détails l’implémentation dans Dans mon exemple pris de mon fork du bundle PSSBlogBundle qui sert a lire la base de donnée WordPress de mon site, et utiliser Symfony2/Doctrine2/Twig pour le devant de mon site (beta.renoirboulannger.com, à l’inverse de la version hébergée sur le domaine non “beta”).

&lt; ?php
namespace PSS\Bundle\BlogBundle\Controller;
 
// Symfony/Doctrine internal
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
// Entities
use PSS\Bundle\BlogBundle\Entity\Post;
use PSS\Bundle\BlogBundle\Entity\Term;
 
/**
 * Base Blog Controller
 *
 * @Route("/blog")
 */
class BlogController extends Controller
{
    /**
     * @Route("/{year}/{month}/{slug}")
     * @Template()
     */
    public function showAction(Post $post, Request $request)
    {
        return array(
            'post' =&gt; $post-&gt;onlyIfPublished(),
            'comment_form' =&gt; $this-&gt;comment($request,$post)
        );
    }
}

Ok, toutes les lignes de codes sauvés sont devenues des lignes use au haut de la page. Mais tout ceci a le mérite d’être très explicite. La magie se passe principalement dans l’annotation @Route qui fait la relation avec l’entité Post et va ajuster la requête de recherche dans le PostRepository et limiter sa recherche au colones slug, year, et month. Ces colones peuvent ne pas exister mais simplement être des méthodes. C’est la magie de Doctrine2 et totalement hors du sujet de ce billet.

Autres annotations d’intérêt

@Route

Cette annotation permet de contrôler les requis que l’adresse doit remplir pour être utilisée. Elle nous permet de spécifier quelle propriétée est liée a l’entitée déclarée dans la déclaration de la méthode du contrôleur.

@Template

Le @Template annotation sur un controleur sert a remplacer les appels a render avec nom de template et va suivre la convention du nom logique, exemple: AcmeBlogBundle:Blog:show qui va aller chercher le fichier de template dans le dossier Acme/BlogBundle/Resources/Blog/show.html.twig.

Il est bien de remarquer ici que par défaut l’engin de templating est Twig et la sortie est HTML. Mais tout peut être configuré. Puis j’aimerai ajouter l’emphase que le système peut permettre de fournir les requis de sortie sous format JSON et nous n’aurions qu’a créer un fichier au même nom mais insérer json à la place de html, exemple:

Donc, plus tard dans le projet, il sera faccile d’ajuster l’attribut “_format” puis dire si header is xmlhttprequest accept`applcation/json, utilise le template au meme nom mais …json.twig et avoir les memes controlleurs repondre html ET JSON :) la methode su controlleur qui a un @Template s’attend a cwe que tu donne un array cle valeur que tu peut utiliser dans ton template.

@Observe

Celle ci est ma découverte de la semaine avec @Inject. Au lieu de déclarer dans un fichier services.yml, il est possible de déclarer directement dans la méthode de la classe l’événement qu’elle est addressée à traiter.

On peut voir dans cette réponse sur StackOverflow comment on peut ajuster le TimeZone sans avoir a modifier d’autres fichiers dans le projet.

Mes autres références

Mon fil delicious delicious avec tags: symfony2 et very-helpful vous donnera ma sélection de références que j’ai apprécié.

Pour comprendre plus

Quelques autres références et billets qui m’ont inspiré et aidé a comprendre.

Des billets inspirants:

Outils à considérer

Crash course about how DNS works and the things you should know about it

I often come with conversations with people and hear them asking how DNS works for hosting their domains. Most of the time, there is plenty of ressources about this. Nevertheless. I felt like I could try to make a nice answer in less than 200 words.

What is DNS?

Just to have everybody on equal grounds, here is some describing facts about domain name resolution that drives the World wide web.

  • Oldest DNS service is the “hosts” file listing basically IP address and name
  • DNS is all about converting “name” into IP address;
  • Registrar is a provider that takes care to register your specification of DNS servers to the ROOT servers

Essentials to know about DNS configuration

Now, the configuration of it. Configuration made of simple flat text files. Format seems cryptic at first but its very straight to the point.

  • Each file is also called a “zone file”
  • A Zone can be created from any DNS server. It is really used ONLY if you specify them at the registrar
  • Entries in a zone represent a subdomain (A,CNAME), a configuration (TXT), or other peers (NS) one per line
  • Each name must end by a dot. Otherwise it gets to be represented as a subdomain of the current zone file name

Some examples

Rougly. The A, and CNAME entries are the essentials to know about.

CNAME is an alias to a A

    domainname.com. IN A 1.1.1.1
    www IN CNAME domainname.com.
    other.domainname.com. IN A 2.2.2.2

Explanations:

  • Both names www.domainname.com and domainname.com in the address bar wil get same IP but you only have to change the A entry
  • Domain entry always end with a dot. Otherwise (like the case of the “www entry) it gets terminated by the zone name (the SOA (Start Of Authority) declaration) not shown.
  • Most important is also the MX and NS entries.  MX is the mail servers and NS the other new DNS servers. Just make sure it follows through

Hope this helps clarify

A quick overview on the advantages to architect you HTML in an “Object Oriented” approach

I am reading quite a few comments on mailing lists about how they’d like to improve the markup but show what we were doing many years ago. Ahem. When we were NOT yet doing HTML5.

I would like to remind that OOCSS as far as I recall is to use CSS selectors in an Object Oriented approach.

Nicole Sullivan, who coined the term made it pretty clear.

Separate CSS effects and assemble afterward.

Namely, separating:

  • Structure and Skin
  • Container and Content

Just think of things for their use, more than the specifics:

  • helper link beside input
  • placeholder where form buttons are
  • Region where there is call to action
  • Label is beside input/label over input
  • Error message in any case possible

With the following requirement:

All this and more are the benefits of imementing OOCSS

I recommend to have a look at markup libraries such as Twitter bootstrap, jQuery UI Bootstrap (jQuery UI, writing Twitter Bootstrap markup), Kickstrap, Zurb Foundation, Pea.rs, and others. I have a list on my delicious account tagged as css+framework

As an example of this concept, I wrote a plugin to create a form confirmation window using only two class names.

References

Choosing a framework, how I personally define what is “hot” about them, an evaluation process (part 1)

This post is all about what I think should be used to define quality in your choice of programming framework tool-set. This post is the first one of a collection of (unknown for now) number of posts.

This week, I had to bring to a team of people what I consider a good PHP framework and why I am sold. I am aware that I may sound blinded with my choice, but this post is about explaining my own guidelines about my choice. I work with them since many years and that made me try many in the PHP ecosystem.

Everything goes with PHP Sauce

Things can get messy with PHP, that’s why we have to be very cautious on how we structure and consider recommendations from other good programmers.

Since we know that PHP can be a “sauce where everything goes”. Structure is crucial. There is many frameworks, many libraries, and to be able to build solutions that will solve more usefull and important matters, we need to agree on how to collaborate.

I do not claim to be a guru, I have done stuff and thanks to people I mention here, I feel I am getting better at the craft and I thought my reflection process was worth sharing.

 

 

Continue reading “Choosing a framework, how I personally define what is “hot” about them, an evaluation process (part 1)”

How I managed to make work Guzzle REST client library under Symfony 2.0.x as a bundle [Snipet]

Warning This is not a cut and paste solution. But some notes I want to share on how I did and what I’d like to cover and remember when I will continue working with that aspect on my current projects.

The problem i had was mostly that i had to see where to mix-and-match things between this wonderful library and Symfony2. I discovered after searching here that it’s not that complicated, you just need to get through the learning curve of reading the code AND the documentation.

I am posting here the hilight of what I have been struggling with and will re-read soon about how to use it and implement in into Symfony2.

Things I wished I understood faster

  • How to inject the configuration from symfony without hardcoding paths in my Managers/Controllers
  • Why do the XML configuration file has nodes like <client> in the main project file, but it’s not what triggers the Command. Answer: Use ServiceDescription::factory($xmlFileFullPath) from the Client class. Yes, it has <client> nodes… NO, they are not the same as in the client definition file xml (guzzleclients.xml).
  • How to extend a DynamicCommand from the ServiceDescription

The Gist

Improvement paths

Actually, now that I went through all this, A simple yaml annotation with a simple service definition with @MyBlogBundle/Resources/config/serviceDescription.clientName.xml could had done the job.

Trying to find templating engine library of markup generating schema.org/RDFa content

I am currently working on a project that I am going to publish on github.

It’s roughly a library of templating engine macros and blocks to send collections of data (similar to a JSON format) and it builds the HTML favouring HTML+RDFa with abstraction of the CSS schema for implementation using this “framework of things”.

My question is mostly if any of you guys had been aware of already made such libraries.

What I am working on:

The main idea is to be able to exchange content, take from external source, cache in a “serialized” but text only (readable) way, then generate the html in the shema you want.

If you want to see in detail the big picture I want to attain using what I am searching, I suggest you look on the project manifest here.

Where I am at:

My current implementation is made in Twig using Symfony2/Doctrine2 with a WordPress database.

For the moment I have my site beta.renoirboulanger.com/ (not stable yet) which implements partly the first and the third part, you can see the code of the first part in this github repo branch, you can see how I am architecturing in this Wiki page.

So far, for the third part, I have only a few patterns using schema.org/BlogPosting and schema.org/UserComments and I am abstracting the css vocabulary out of it and making sure the templating library is as DRY as possible.

When I will have more than an incomplete BlogPosting+UserComments macros I will open the project on github.

Your input

As I said, I am mostly wondering if you have knowledge of any such implementation of set of macros that represents html in micro formats, be it in Python Django templating language, Mustach, Hogan, or anything.

Thanks!

Mon souhait pour bien écrire sur le web: Lettre ouverte à Druide

Bonjour

Je suis un développeur web et je regarde sur le web s’il existe un service qui me permettrait de faire valider mon texte. Plusieurs gens dans le monde du marketing ne jurent que par vos produits. Mais je ne vois pas d’offre de la sorte autre que WebElixir.

Selon moi, plusieurs développeurs web aimeraient avoir accès a votre service pour ajouter votre outil au processus d’édition leur contenus.

De façon interactive.

Mon point de vue

J’aimerai pouvoir avoir un accès a un service REST avec token OAuth pour envoyer mon texte, et le recevoir révisé.

Je suis un développeur PHP qui utilise Symfony2 et ce qui suit est basé sur les outils que j’utilise en PHP.  Soyez assuré qu’il existe une alternative pour les autres langages du web tel que le .NET, Python et Ruby car les concepts que j’apporte ici sont monnaie courrante d’une technologie web à l’autre.

Potentiel

  • pouvoir avoir une aide directement dans une fenêtre d’édition de l’administration d’un site géré par WordPress (l’un des CMS les plus utilisés au monde).
  • Outil de publication de Tweet avec vérification de syntaxe pour widget de portail d’entreprise
  • Décentraliser l’architecture (WebElixir à sûrement un API via http?)
  • Outil allégé pour téléphones intelligents (seulement supporter le pastebin qui sert d’entrée de texte)
  • Connectivité aux API de iOS, et Android
  • Les services web sont offerts pour presque tout (TwitterFacebookEvernote, Solr (Lucene, index de recherche),  et beaucoup d’autres)

Ébauche préliminaire d’une solution

 

Avez-vous de quoi de similaire? (Autre que WebElixir?)

 

Merci de m’avoir lu.


Réponse reçue de Druide Informatique

Bonjour Monsieur Renoir,

Nous n’avons rien de similaire à ce que vous mentionnez dans votre message, ni d’API pour développer sur la base de WebElixir.

Toutefois, nous vous remercions de votre commentaire. Au fil du temps, nos produits ne cessent de s’améliorer, et ce sont en grande partie les remarques et suggestions de ses utilisateurs qui orientent notre travail.

Les commentaires comme le vôtre sont dument notés et font tous l’objet d’une analyse diligente. Il est ainsi possible que l’amélioration que vous suggérez, ainsi que plusieurs autres, fasse un jour partie d’une version ou d’une édition future d’Antidote ou de WebElixir.

Nos salutations les plus sincères.

(…)

How to implement a CollectionType Form field with AJAX “add new” embedded form with re-usable markup using Symfony2 and Twitter Bootstrap

I wanted to create a re-usable piece of code that makes me able to “add new” input field and makes the relationship with the other entity.

I did only find some very specific (and not re-usable) examples, so I gave my try on this question. Hope you find it usefull.

Here is how I did it, in some generic manner.

In generic, I mean, Any collection that I add to the form just need to follow the Form template loop (in a macro, for example) and that’s all!

Using which convention

Form Type class

The form template

Trick here is that I would have had used the original {{ form_widget(form }} but I needed to add some specific to the view form and I could not make it shorter.

And I tried to edit only the targeted field and found out it was a bit complex

My notes on Snipt.net

I created a Snipt to use on my Sublime Text 2 editor installation. In case you want to use it:

References

I wrote a complete answer, hoping to add some value on StackOverflow, here is some other paths I read about it.

    Résumé de mes essais avec composer sous Symfony 2.0.x et un manifeste composer.json pour vos propres tests

    Ce soir j’ai pris le temps d’essayer de configurer une distribution Symfony 2.0.x sous Composer. Je ne suis pas certain encore si j’ai totalement réussi. J’aimerai votre avis sur ma proposition de fichier composer.json.

    Statut mis à jour

    Je suis retourné avec le fichier deps à cause que je n’ai pas réussi a avoir toutes mes dépendances fonctionnelles dans un délai raisonnable (trois soirs). J’essaierai à nouveau plus tard.

    Résultat

    En ce moment je n’arrive pas a faire fonctionner JmsDiExtraBundle ni la nouvelle version de MopaBootstrapBundle notamment pour le mopa/bootstrap-sandbox-bundle. Je mettrai ce billet a jour lorsque j’aurai terminé mes essais.

    Résultat escompté

    Avoir un manifeste complet pour Symfony 2.0.x que je pourrai utiliser avec mes bundles préférés:

    • jms/security-extra-bundle
    • jms/di-extra-bundle
    • jms/serializer-bundle
    • gedmo/doctrine-extensions
    • stof/doctrine-extensions-bundle
    • knplabs/knp-components
    • mopa/bootstrap-bundle
    • knplabs/knp-paginator-bundle
    • polishsymfonycommunity/blog-bundle

    Composer.json file

    {
        "description": "This bundle is meant to run latest 2.0.x Symfony-standard distribution, based on Composer.",
        "keywords": ["symfony2"],
        "type": "symfony-bundle",
        "license": "MIT",
        "authors": [{
            "name" : "Renoir Boulanger",
            "email" : "[email protected]"
        }],
         "autoload": {
            "psr-0": { "": "src/" }
        },
        "require": {
            "php": ">=5.3",
            "symfony/symfony": "2.0.*",
     
            "twig/twig": "1.6.*",
            "doctrine/orm": "2.1.7",
            "doctrine/common": "2.1.4",
            "doctrine/dbal":   "2.1.7",
            "swiftmailer/swiftmailer": ">=4.1.7",
            "monolog/monolog": "1.0.*",
     
            "symfony/assetic-bundle": ">=1.0.1",
            "sensio/distribution-bundle": "2.0.*",
            "sensio/framework-extra-bundle": ">=2.0",
            "sensio/generator-bundle": "2.0.*",
     
            "jms/metadata": ">=1.1.0",
            "jms/security-extra-bundle": "1.0.x",
            "jms/di-extra-bundle": ">=1.0.0",
            "jms/serializer-bundle": "master",
     
            "gedmo/doctrine-extensions": "v2.2.2",
            "stof/doctrine-extensions-bundle": "1.0.2",
            "liip/imagine-bundle": "master",
     
            "knplabs/knp-components": "1.1.*",
            "mopa/bootstrap-bundle": "2.0.*",
     
            "knplabs/knp-paginator-bundle": "dev-master",
            "knplabs/knp-menu-bundle": "dev-master",
            "mopa/bootstrap-sandbox-bundle": "2.0.x-dev",
            "liip/theme-bundle": "dev-master"
        },
        "config": {
            "bin-dir": "bin"
        },
        "extra": {
            "symfony-app-dir": "app",
            "symfony-web-dir": "web"
        }
    }

    Confirm form before submitting using Twitter Bootstrap in a Modal window [Snippet]

    Idea

    Have you ever wanted to create a way to confirm input before actually submitting the form. Automatically.

    My snippet’s goal is exactly for that purpose. The idea is that it reads the form inputs and labels, and generates a modal window (like a lightbox) and asks confirmation. This project is a contribution I do to Twitter Bootstrap and jQuery-bootstrap-scripting (“dialog2”) to add on any form using Twitter Bootstrap form markup convention the capability to create a confirmation modal window.

    The concept is that some forms needs to have some confirmation and requires more than “are you sure”, but also what you are submitting.

    How it works

    When the pages load, it executes in this order the following:

    • Whether there is a form[data-behavior=confirm], and modify the form default submit button to replace it with a link (idea being that if there is no javascript enabled, you can still submit!)
    • on a Click action on the newly created a.confirm-toggle, it fires up some html manipulation and creates a modal window using jQuery Bootstrap Scriptin’s Dialog2 plugin

    Word of advice

    I have to warn you though. The solution is not yet complete. It works well with input[type=text] and some select. But I need to add more field types as time goes. That’s why I created this Fiddle to give room for improvement. Feel free to collaborate. When the solution will be strong enough, i’ll contribute it to both projects in their respective syntax (dialog2 doesnt initialize the same way as Bootstrap’s modal()

    Known limitations

    • Works only with select and input[type=text], and breaks bad with radio and checkbox
    • Works only with ONE form in the page, for now.
    • ¨

    The code

    You can play with this Fiddle in the meantime i make it ready-er

    The javascript

     
        /**
         * Use form's content into a confirmation modal
         *
         * Using: http://nikku.github.com/jquery-bootstrap-scripting/
         * Requires: Twitter Bootstrap, dialog2
         *
         * @author: Renoir Boulanger
         */
        if ($('form[data-behavior=confirm]').length >= 1) {
     
            console.log('run.js: document ready : Applying confirmation, ' + $('form[data-behavior=confirm]').length + ' times');
     
            $('form[data-behavior=confirm] select').click(function() {
                var dataValue = $(this).find(':selected').text();
                $(this).attr('data-value', dataValue);
     
                // Debug console
                console.log('Adding data-value at: ' + dataValue);
            });
     
            $('form[data-behavior=confirm] .confirm-toggle').replaceWith('<input id="confirm-submit" type="submit" class="is-hidden"/>' + '<a href="#" class="confirm-toggle btn btn-primary">Continue</a>');
     
            /**
             *  Since we know javascript is executed so far, lets handle it with the confirmation.
             *
             *  That way, no javascript-enabled browsing user will be able to use the form. #progressiveEnhancement
             *
             *  Do the work.
             */
            $('form[data-behavior=confirm] .confirm-toggle').click(function(event) {
                event.preventDefault();
     
                // Get form content
                var form = $('form[data-behavior=confirm]').clone().attr('id', 'cloned'); //.appendTo('body');
                var i = 0;
                form.find(':input:not([type=hidden])').each(function() {
                    var field = $(this);
     
     
                    if (field.is('select')) {
                        fieldValue = $(this).attr('data-value');
                        if (fieldValue === undefined) {
                            fieldValue = field.find(':selected').html();
     
                            // Debug console
                            console.log('fieldValue was undefined, setting to : ' + fieldValue);
                        }
     
                        // Debug console
                        console.log('fieldValue is : ' + fieldValue);
                    } else {
                        fieldValue = field.val();
                    }
     
                    // Remove undefined field (they are useless)
                    if (fieldValue === '') {
                        field.parent().parent().addClass('empty-field-resolved');
                    }
     
                    // Debug console
                    console.log('Field ' + i + ' :' + fieldValue + ' for #' + field.attr('id'));
     
                    // Wrap fieldValue in a tag, Tested in IE7!!
                    field.after($('<span class="value">' + fieldValue + '</span>'));
     
                    // Remove the field itself, we only want to see the resulting
                    field.remove();
     
                    i++;
                });
     
                // Work stuff out for modal window, copying content, and building modal into the DOM
                var decorate = $("<div id=\"modal-placeholder\"><div class=\"modal-builder\"></div></div>");
                var buildup = decorate.find(".modal-builder").html(form);
     
                buildup.appendTo('body');
     
                // Debug console
                console.log('Appending #modal-placeholder in body, ready to call dialog2()');
     
                // Remove not needed anymore stuff
                $('.modal-builder .help-block, .modal-builder .input-append, .modal-builder .form-actions').remove();
     
                $('.modal-builder').dialog2({
                    title: "Are you sure?",
                    id: "confirm-modal",
                    modalClass: "modal-wide fade in",
                    closeOnOverlayClick: false,
                    closeOnEscape: false,
                    initialLoadText: "Loading in progress...",
                    buttons: {
                        Confirm: {
                            primary: true,
                            click: function() {
                                // Debug
                                console.log('Inside dialog2() clicked Confirm');
     
                                $('#confirm-submit').click();
                            }
                        },
                        "Forgot something": {
                            click: function() {
                                // Debug
                                console.log('Inside dialog2() clicked cancel');
     
                                $(this).dialog2("close");
                                $('.modal').remove();
                                return false;
                            }
                        }
                    }
                });
                // Do my own cleanup. Remove potentially bogus nodes
                $('#modal-placeholder, .modal-header .close, .control-group.empty-field-resolved').remove();
            });
        }

    The CSS

    Minimally…

    .modal-wide {
      overflow:visible;
      width: 650px;
    }
     
    .modal-builder .control-label {
          padding:0 !important;
          font-weight:bold;
    }
     
     /* In case you use a span.required-star
      * with title="required field", I don't want to
      * have them in modal
      **/
    .modal-builder  .required-star {
        display:none;
    }
     
    .modal-builder .hide-in-confirm {
      display:none !important;
    }

    Tell me in the comments if you want the LESS block I created

    The Form

    Always using Twitter Bootstrap markup, A form minimally needs

    What is really required here is

    • Form tag has data-behavior="confirm" attribute
    • Form submit button has at least the class name confirm-toggle

    Just use any combination of Twitter Bootstrap Form patterns

    <form class="form-horizontal" method="post">
    <fieldset>
    <div class="control-group hidden-in-confirm">
    <!-- This block will be hidden -->
                <label class="control-label" for="input01">Text input</label>
    <div class="controls">
    <input id="input01" class="input-xlarge" type="text" />
     
    In addition to freeform text, any HTML5 text-based input appears like so.</div>
    </div>
    <!-- ... the form ... -->
    <div class="form-actions">
                <button class="btn">Cancel</button>
    <input class="btn btn-primary confirm-toggle" type="submit" value="Continue" /></div></fieldset>
    </form>

    Possible enhancements paths

    My solution fit for what I needed. A two parameters to add confirm in a modal using the project’s markup. Sadly I read after doing it that there is some plugins I could have considered such as the Form plugin

    .

    End word

    I am going to prepare this post and propose a pull request to the jQuery Bootstrap Scripting AND Bootstrap project in a day or two.

    Ressources

    • http://nikku.github.com/jquery-bootstrap-scripting/#
    • http://twitter.github.com/bootstrap/base-css.html#forms

    Les diapositives de ma présentation au HTML5Mtl “Comment entretenir et utiliser une architecture modulaire et réutilisable CSS” est publié

    Vous pouvez les trouver ici: Comment entretenir et utiliser une architecture modulaire et réutilisable CSS.

    La présentation a eu lieu pendant la rencontre d’Avril du HTML5Mtl. Le groupe HTML5Mtl est un sous-projet du W3Québec pour promouvoir la nouvelle norme du W3c. Le HTML5.

    Mon expérience sur le sujet est assez forte car depuis 2010 je ne fais que ça, du HTML5. En fait, j’y décrit un sommaire de mes recherches faites dans la dernière année chez Evocatio.

    Sommaire de la présentatin

    Avec le temps, j’ai envie d’être optimal sur tout ce qui touche le projet, et rendre réutilisable:

    • structurer le code de Front-end
    • structurer le code Back-end
    • le processus de déploiement

    Avec tout ça, il y a des avantages qui me semblent très intéressants:

    • le processus de conception (wireframes en html) permet de valider toute modification CSS si on brise quelque chose d’autre ailleurs dans l’application
    • les programmeurs n’ont pas a inventer de markup html, ils pigent dans le “style-guide”
    • au fil du temps, on se retrouve avec le même HTML, et du CSS spécifiquee au projet

    Expérience passée

    C’était ma 2ème occasion de présenter devant des gens. La première a été durant un devCamp de Microsoft sur le sujet “How to manage big scale HTML/CSS project“. Le même sujet mais avec beaucoup plus de matière.

    Finalement

    Je crois que je devrais ajouter du contenu et améliorer sa structure. Je compte ajuster ma présentation avec:

    • Exemples concrêts pour chaque premeière introduction d’un concept
    • Référence cohérente comme hyperlien pour chaque mention
    • Ajuster le “ce que j’assume” au début de la présentation, et m’assurer que l’audience sait de quoi je parle
    • Donner plus de raisons sur ce que je considère une mauvaise pratique

    Vous voulez que je présente?

    Je suis disponible pour faire présentation dans votre école, université, groupe. Laissez-moi le savoir.

    Feuille de style pour imprimante pour les pages de documentation de Doctrine2 et Symfony2

    Je suis en train d’étudier activement Symfony2 et Doctrine2 car j’ai fait le saut du coté développement applicatif a temps plein.

    Mon apprentissage va très bien et j’ai appris beaucoup sur les meilleurs pratiques et je ne me vois plus dutout faire de php sans le Dependency Injection, les pratiques de namespacing et fonctions lambda de PHP 5.3.

    Alors, pour étudier, j’ai décidé d’imprimer les pages de la documentation. Malheureusement il y a beaucoup de perte d’espace pour du contenu de navigation et temporel qui se ramasse dans mes PDF.

    J’ai converti en PDF plus de cent documents, puis, finalement j’ai repassé les imprimer en ajustant certaines règles CSS.

    Je partage ici le CSS que j’ai élaboré pour pouvoir imprimer les documents sans avoir de perte d’espace pour le lecteur tablette.

    Comment utiliser

    Pour appliquer mon impression, j’ai simplement crée ces blocs CSS, puis inséré ces derniers dans chaque document via l’inspecteur de Google Chrome, puis imprimé.

    J’ai aussi contacté les auteurss des sites respectifs pour leur proposer d’y insérer mes règles.

    Je pense ne pas être le seul a avoir eu besoin d’imprimer leur documentation.

    f

    Documentation Doctrine2

    Je me suis basé sur les pages de cette section.

    J’ai aussi ajusté le fait que les blocs de configuration alternatifs (yml, php, xml) soient tous visible. En imprimé si on veut comparer la syntaxe, on n’a pas javascript pour activer les tabs.

    @media print {
      #footer,
      .footer_popout,
      #nav.cls,
      #content .sphinxsidebar,
      #content .related,
      body a[href~="github"] {
         display:none !important;
      }
      #content .bodywrapper {
          margin:0;
      }
      #content .bodywrapper .body {
          max-width:initial;
      }
      #content {
          font-size:120%;
      }
      #content div.body h1,
      #content div.body h2,
      #content div.body h3,
      #content div.body h4,
      #content div.body h5,
      #content div.body h6 {
          background:none;
      }
    }

    Documentation Symfony2

    Sur toutes les sous pages de la documentation.

    @media print {
      #content_wrapper .box_download.clear_fix,
      #content_wrapper .main_menu.clear_fix,
      #content_wrapper .main_content .column_01,
      #content_wrapper .main_content .column_02 .navigation,
      #content_wrapper .box_relative_content,
      #content_wrapper .footer .box_menu_footer.clear_fix,
      #content_wrapper .footer h2 img,
      #sln {
          display:none !important;
      }
      #content_wrapper .main_content .column_02 {
          width: 100%;
          padding:0;
          font-size:120%;
      }
      #content_wrapper .footer {
          background-color: #FFF;
      }
      #content_wrapper .footer h2 {
          color: #444;
      }
      #content_wrapper .footer h2:before {
          content: "Symfony";
      }
      #content_wrapper .highlight-jinja {
          font-weight:bold;
          font-size:130%;
          width: 100% !important;
      }
      #content_wrapper .highlight-jinja .hilight {
          background:none;
          border:1px solid #444;
      }
      #content_wrapper .highlight-jinja .hilight:before {
          content: "Code block";
      }
      #content_wrapper .configuration-block.jsactive.clearfix {
     
      }
      #content_wrapper .configuration-block.jsactive ul {
            height:initial !important;
      }
      #content_wrapper .configuration-block.jsactive ul.simple {
            overflow:hidden;
            height:initial !important;
      }
      #content_wrapper div.jsactive div div,
      #content_wrapper div.jsactive div {
            position: relative !important;
      }
      #content_wrapper .configuration-block.jsactive ul.simple li {
            float: none;
      }
      #content_wrapper .configuration-block.jsactive ul.simple li &gt; div{
            display: block !important;
            width: 100% !important;
      }
    }