दृश्य और HTML टैब के बीच स्वतंत्र रूप से स्विच करें


21

इसलिए यह प्रश्न कई बार विभिन्न झंडों के नीचे उठाया गया है, हालाँकि मैं इस मुद्दे के एक अंतिम समाधान के लिए एक एकीकृत धागा प्रस्तुत करना चाहता हूँ।

वर्डप्रेस में, डिफ़ॉल्ट रूप से, जब TinyMCE में HTML और विज़ुअल संपादकों के बीच आगे-पीछे स्विच किया जाता है, तो कुछ टैग्स को सामग्री से निकाल दिया जाता है, और अन्य अजीब कार्यक्षमता होती है। अधिक कुशल HTML कोड लिखने के लिए दो ज्ञात वर्कअराउंड wp_auto_p फ़ंक्शन को फ़िल्टर का उपयोग करके हटाने और TinyMCE एडवांस को स्थापित करने और "स्टॉप रिमूवल पी एंड ब्रा टैग्स" विकल्प को सक्षम करने के लिए उपयोग कर रहे हैं।

यह केवल इतना अच्छा काम करता है, दुर्भाग्य से।

उदाहरण के लिए, निम्न उदाहरण लें:

<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin.  First, download the zip file using the button above.  After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client.  After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre>
&lt;script type=&quot;text/javascript&quot; src=&quot;/path/to/jquery.easycolumns.js&quot;&gt;&lt;/script&gt;
</pre>

यदि मैं इस कोड को HTML संपादक में टाइप करता हूं, जिसमें पहले से ही सक्षम ऊपर सूचीबद्ध दोनों विकल्प हैं, तो जब मैं दो अलग-अलग संपादकों के बीच स्विच करता हूं, तो कुछ भी नहीं होता है, जो अपेक्षित है। दुर्भाग्य से, बचत करते समय, कोड स्वचालित रूप से इस में परिवर्तित हो जाता है:

<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin.  First, download the zip file using the button above.  After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client.  After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre>
<script type="text/javascript" src="/path/to/jquery.easycolumns.js"></script>
</pre>

जैसा कि आप देख सकते हैं, पूर्व टैग के अंदर की सभी इकाइयाँ वास्तविक HTML वर्णों में परिवर्तित हो जाती हैं। फिर, अगर मैं फिर से उसी पोस्ट को सहेजता हूं, तो मुझे निम्न जैसा कुछ मिलता है:

<h2>How does it work?</h2>
<p>In order to use jQuery Easy Columns, you must install it as you would any other jQuery plugin.  First, download the zip file using the button above.  After downloading the file, extract it to a location of your choice, and move the extracted folder to your server using your favorite FTP client.  After moving the plugin to your server (and of course calling the jQuery source into your document), call it in on your site using the following snippet of code:</p>
<pre><br />
<script type="text/javascript" src="/path/to/jquery.easycolumns.js"></script><br />
</pre>

ध्यान दें कि Wordpress वास्तव में पोस्ट में br टैग्स को इंजेक्ट करेगा। कहने की जरूरत नहीं है, जब इस पोस्ट को कुछ बार अपडेट किया गया है, जब इसे फ्रंटेंड पर देखा गया है, तो डिस्प्ले कहीं भी डिस्प्ले के पास नहीं है।

मुझे लगता है कि सभी जोड़ा "स्वरूपण कार्यक्षमता" से छुटकारा पाने का एकमात्र तरीका दृश्य संपादक को मेरी प्रोफ़ाइल के माध्यम से अक्षम करना है।

मेरे लिए यह एक अच्छा समाधान है, मैं एक पेशेवर वेब डेवलपर हूं। मेरे ग्राहकों के लिए, यह समाधान सुरुचिपूर्ण से दूर है। मेरे ग्राहक, अधिकांश भाग के लिए, दृश्य संपादक का उपयोग करेंगे। मेरे बहुत से क्लाइंट बहुत ही तकनीक के जानकार नहीं हैं, और कभी-कभी लेआउट के टूटने पर मुझे उनके पोस्ट को ठीक करने की आवश्यकता होती है। यह मुझे दृश्य संपादक का उपयोग करने के लिए सीमित करता है, क्योंकि मैं लेआउट को तोड़ने के डर के बिना HTML संपादक में नहीं बदल सकता।

मुख्य रूप से, (और मुझे लगता है कि एक बड़ा समुदाय है जो इस उत्तर से लाभान्वित हो सकता है), निम्नलिखित को सुनिश्चित करने के लिए मैं कौन से स्पष्ट कदम उठा सकता हूं:

  1. दृश्य या HTML संपादक से कोई पोस्ट संपादित की जा सकती है।
  2. दो टैब के बीच स्विच करने पर किसी भी तरह से पोस्ट की सामग्री को संशोधित नहीं किया जाता है।
  3. HTML संपादक से किसी पोस्ट को सहेजते समय, कोई अतिरिक्त सामग्री नहीं जोड़ी जाती है।
  4. HTML संपादक से किसी पोस्ट को सहेजते समय, कोई भी इकाइयाँ परिवर्तित नहीं होती हैं।
  5. बोनस: HTML संपादक से किसी पोस्ट को सहेजते समय, कोई भी कोड (उदाहरण के लिए HTML) जो एक पूर्व टैग के अंदर लिपटा होता है और पहले से ही संस्थाओं में परिवर्तित नहीं होता है, स्वचालित रूप से संस्थाओं में परिवर्तित हो जाएगा।

अनिवार्य रूप से, यदि हम तृतीय पक्ष प्लगइन के उपयोग के माध्यम से टाइनीएमसीई में उपर्युक्त व्यवहार बना सकते हैं, तो हम टिनीएमसीई के उपयोग के माध्यम से झूठे स्वरूपण के बारे में अन्य सभी प्रश्नों को समाप्त कर सकते हैं। मुझे लगता है कि कई लोग इससे लाभान्वित हो सकते हैं।

यह सिर्फ तर्कसंगत लगता है कि WYSIWIG संपादक से एक निश्चित कार्यक्षमता की अपेक्षा की जाती है, और यह इसके खिलाफ जाता है। सभी तर्क और कारण के अनुसार, स्वरूपण कार्यों में निर्मित वर्डप्रेस अपने वर्तमान सेटअप के साथ बहुत बेकार हैं। यह मुझे लगता है कि अगर वे इन प्रारूपण विकल्पों का उपयोग करना चाहते हैं, तो उनका सबसे अच्छा दांव एक संपादक या दूसरे को सक्षम करना होगा, दोनों को नहीं।

और कृपया: समस्या का समाधान और अन्य WYSIWIG संपादकों के डाउनलोड के साथ इस धागे का जवाब न दें जो समस्या को 'ठीक' करते हैं। यह वर्डप्रेस कोर के साथ एक अंतर्निहित समस्या है (हालांकि वास्तव में एक बग नहीं है) जिसे ठीक करने की आवश्यकता है।

संपादित करें : ठीक है, मैं इस पर काम कर रहा हूं और मैं सोच रहा हूं कि रिवर्स इंजीनियरिंग इस मुद्दे को हल करने का सबसे अच्छा तरीका होगा। तो अभी के लिए, मैंने wpautop को अक्षम कर दिया है (जो सिर्फ स्पष्टता के लिए एक फ़ंक्शन है जो पाठ प्रदर्शित होने से पहले p और br टैग जोड़ने के लिए "the_content" फिल्टर में हुक करता है , न कि जब पाठ सहेजा जाता है। मुझे लगता है कि कुछ भ्रम मौजूद है। जैसा कि यह फ़ंक्शन संचालित करता है। संपादक टैब के बीच स्विच करने पर आपके द्वारा होने वाले परिवर्तनों के लिए wpautop जिम्मेदार नहीं है। यह पूरी तरह से अलग है।

वैसे भी, मैंने wpautop को अक्षम कर दिया है, जैसा कि आप HTML संपादक का उपयोग करते समय अच्छा अभ्यास करते हैं। उस बिंदु से, मैंने विज़ुअल एडिटर को पहले HTML इकाई त्रुटियों के साथ शुरू करने के लिए अक्षम कर दिया है जो किसी पोस्ट को सहेजते समय मौजूद हैं। एक सी। बावोटा की मदद के लिए, मुझे साइट के सामने के छोर पर प्रदर्शित करने से पहले HTML संपादक में किसी भी टैग को उनके समकक्ष संस्थाओं में बदलने के लिए एक स्निपेट मिला (क्रेडिट: http://bavotasan.com/2012/convert -पर-टैग-सामग्री-से-HTML- संस्थाओं-में-वर्डप्रेस / )।

#add_filter( 'the_content', 'pre_content_filter', 0 );
/**
 * Converts pre tag contents to HTML entities 
 *
 * This function is attached to the 'the_content' filter hook.
 *
 * @author c.bavota
 */

function pre_content_filter( $content ) {
        return preg_replace_callback( '|<pre.*>(.*)</pre|isU' , 'convert_pre_entities', $content );
}


function convert_pre_entities( $matches ) {
        return str_replace( $matches[1], htmlentities($matches[1] ), $matches[0] );
}

add_filter( 'the_content', 'pre_content_filter', 10, 2 ); 

यह प्रभावी रूप से वर्डप्रेस के साथ मुद्दों को समाप्त करता है, इसे बचाने के लिए सभी संस्थाओं को टैग में सहेजकर टैग में बदल देता है। अब, आप HTML एडिटर का उपयोग कर सकते हैं, और अपने आप को इकाई रूपांतरण किए बिना "पूर्व" टैग के बीच मानक कोड लिख सकते हैं। यह वर्डप्रेस में इकाई रूपांतरण के साथ सभी मुद्दों का ख्याल रखता है, और सुनिश्चित करता है कि सामने के छोर पर सब कुछ सही ढंग से प्रदर्शित होता है। अब, हमें यह पता लगाने की आवश्यकता है कि टैब के बीच आगे और पीछे क्लिक करने पर अनुभव किए गए व्यवहार को संशोधित करने के लिए क्या हुक करना है। अभी, ऐसा प्रतीत होता है कि HTML से विज़ुअल टैब में जाने पर, HTML टैब की सामग्री की व्याख्या जावास्क्रिप्ट या किसी ऐसी चीज़ से की जाती है, जो सामग्री की तरह दिखना चाहिए। यह टैग (जो HTML टैब में गैर इकाई रूप में प्रदर्शित होते हैं) को प्रदर्शित होने के बजाय संसाधित किया जाता है। फिर, जब HTML टैब पर वापस जाते हैं, तो यह दिखाई देगा कि TinyMCE वर्तमान डेटा को पास करता है। इसका मतलब है कि जब आप वापस स्विच करते हैं, तो आप अपनी HTML संरचना खो देते हैं। हमें विंडो में लोड करने से पहले टिनीएमसीई को पूर्व टैग में सब कुछ बदलने के लिए इसे समान संस्थाओं के रूप में बताने का एक तरीका जानने की आवश्यकता है (अनिवार्य रूप से हमने फ्रंटएंड पर जो कुछ किया था उसका बैकएंड संस्करण लेकिन php और हुक के बजाय टिनिम्स और जावास्क्रिप्ट के साथ), ताकि यह संसाधित के बजाय प्रदर्शित हो। सुझाव? इसे विंडो में लोड करने से पहले समतुल्य इकाइयाँ (अनिवार्य रूप से बैकएंड पर हमने जो भी किया था उसका बैकएंड संस्करण लेकिन php और हुक के बजाय टिनिम्स और जावास्क्रिप्ट के साथ), ताकि यह संसाधित के बजाय प्रदर्शित हो। सुझाव? इसे विंडो में लोड करने से पहले समतुल्य इकाइयाँ (अनिवार्य रूप से बैकएंड पर हमने जो भी किया था उसका बैकएंड संस्करण लेकिन php और हुक के बजाय टिनिम्स और जावास्क्रिप्ट के साथ), ताकि यह संसाधित के बजाय प्रदर्शित हो। सुझाव?

संपादित करें 2 :

कुछ और शोधों के बाद, प्री टैग में एंटिटीज को परिवर्तित करने पर जब वे प्रदर्शित होते हैं तो प्री टैग के भीतर सामग्री के लिए ठीक काम करता है, लेकिन कहते हैं कि मेरे पास एक ब्लॉग पोस्ट है जैसे कि एक लाइन।

"अगला, हमें अपनी HTML फ़ाइल में इस पंक्ति को जोड़ना होगा: <p> हैलो, वर्ल्ड! </ P>"

इस पंक्ति को देखते हुए, आप बता सकते हैं कि कोड को साइट पर प्रदर्शित किया जाना है, और पार्स नहीं किया गया है, हालांकि जब पोस्ट सहेजा जाता है, तो ये इकाइयां अगले पोस्ट एडिट लोड पर डिकोड हो जाती हैं, और प्रत्येक बाद में सहेजे जाने से बच जाते हैं कच्चे HTML टैग्स के रूप में, जिसके कारण उन्हें फ्रंट एंड पर पार्स किया जाता है। एकमात्र उपाय जो मैं अब तक सोच सकता हूं कि "कोड" टैग के लिए समान कोड में लिखना होगा जैसा कि मैं पूर्व के लिए उपयोग कर रहा हूं, और फिर बस "कोड" टैग में छोटे एक लाइनर लपेटें, और में बड़े टुकड़े "प्री" टैग। किसी के पास कोई अन्य विचार है?


2
अच्छा लेख। उस TinyMCE ने मुझे सिरदर्द के अलावा कुछ नहीं दिया। मैंने हाल ही में इसे CKEditor के लिए बदल दिया है, हालांकि यह कहना बहुत जल्द है कि यह कैसे हो रहा है। एक समस्या जिसका आपने अपनी पोस्ट में उल्लेख नहीं किया है वह है वर्ड से पेस्ट करते समय अतिरिक्त cr **।
18

मैंने थोड़ी देर के लिए अपनी स्वयं की साइट पर CKeditor का उपयोग किया यह सोचने के लिए कि मुझे यह समाधान चाहिए था, लेकिन दुर्भाग्य से यहाँ पर मुद्दा Wordpress के हाथ से है और यह TinyMCE से प्राप्त डेटा के हैंडलिंग और प्रारूपण के साथ है, न कि खुद TinyMCE से। वांछित प्रभाव पैदा करने के लिए सही समय पर Wordpress में हुक करने का एक तरीका होना चाहिए। लेकिन परवाह किए बिना CKeditor निश्चित रूप से एक अच्छा प्लगइन है, बस वही नहीं जो मैं ढूंढ रहा हूं।
थॉट स्पेस डिजाइन

1
इसके अलावा, आप TinyMCE के "किचन सिंक" में "शब्द से पेस्ट" सुविधा के बारे में जानते हैं? वर्ड से पेस्ट करते समय "अतिरिक्त बकवास" के साथ अपने मुद्दे का ध्यान रखना चाहिए।
थॉट स्पेस डिजाइन

7
बहुत बढ़िया सवाल। इसे मसाला देने के लिए: मैं 200 के इनाम के साथ समाधान को पुरस्कृत करूंगा । मैं तब तक प्रतीक्षा करूंगा जब तक कि वास्तव में कोई जवाब न हो, इसलिए इनाम बहुत जल्दी समाप्त नहीं होता है।
FUXIA

जवाबों:


5

ठीक है, इसलिए मैंने पहले ही इस सवाल को एक टन अपडेट कर दिया है और यह अतिभारित होना शुरू हो रहा है, इसलिए मुझे लगा कि मैं इसे एक उत्तर के रूप में लिखूंगा भले ही यह पूर्ण न हो।

@ Bueltge के उत्तर से हटाते हुए, मैं वास्तव में वापस गया और प्रश्न में उनकी पिछली पोस्ट को पाया। उस पोस्ट में, एक प्लगइन सूचीबद्ध था जिसे मैंने पहले कभी नहीं देखा है: "संरक्षित HTML संपादक मार्कअप"। इस प्लगइन को थोड़ी देर में अपडेट नहीं किया गया है, लेकिन मैंने अभी WP 3.6.1 के साथ इसका परीक्षण किया है और यह पूरी तरह कार्यात्मक है। यह प्लगइन स्वचालित रूप से wpautop का ख्याल रखता है, दृश्य संपादक के भीतर br और p टैग डालने के लिए एक एकीकृत प्रारूप प्रदान करता है, और टैब के बीच स्विच करने पर आपके मार्कअप को संरक्षित करता है।

अपने स्वयं के प्रयोजनों के लिए, मैंने अपनी कार्यक्षमता के साथ इस प्लगइन का विस्तार किया: किसी भी HTML टैग का स्वचालित रूपांतरण "<कोड>" टैग के भीतर उनकी संबंधित संस्थाओं को बचाने के लिए। इसका मतलब है कि आप टेक्स्ट टैब के भीतर कोड टैग में मानक HTML कोड लिख सकते हैं, और फिर इसे सहेज सकते हैं, और पूर्व टैग के सभी सामान साइट के सामने के छोर और दृश्य संपादक पर उचित प्रदर्शन के लिए संस्थाओं में बदल देंगे। यह सबसे सुरुचिपूर्ण समाधान नहीं है जो मैंने अभी तक पाया है, लेकिन यह काम करने लगता है। प्लगइन को सक्रिय करने के बाद अपने कार्यों के लिए इस लाइन को जोड़ें।

function code_content_conversion_filter( $content ) {
        return preg_replace_callback( '|<code.*>(.*)</code|isU' , 'convert_entities', $content );
}

function convert_entities( $matches ) {
        return str_replace( $matches[1], htmlspecialchars($matches[1], ENT_QUOTES | ENT_HTML5, 'UTF-8', FALSE ), $matches[0] );
}

add_filter( 'content_save_pre', 'code_content_conversion_filter', 0);

अब, कोड टैग के बीच में किसी भी मान्य HTML को टाइप करें, और जब आप सहेजते हैं, जब संपादक वापस पॉप अप करता है, तो वे सभी संस्थाओं में परिवर्तित हो जाएंगे। इससे आप कोड जल्दी लिख सकते हैं। अब, केवल एक चीज जो अभी भी एक मुद्दा है, यदि आपके पास एक नेस्टेड कोड टैग और HTML में "पूर्व" फ़ील्ड है, और आप विज़ुअल टैब पर जाते हैं और कोड में एक नई लाइन डालने की कोशिश करते हैं, एक ब्रा टैग HTML में आपके कोड टैग में अंतःक्षिप्त हो जाता है। TinyMCE में इसे अक्षम करने का विकल्प होना चाहिए। भले ही, जब तक आप टेक्स्ट टैब से अपने पूर्व क्षेत्रों को संपादित करते हैं, तब तक आप बेझिझक टैब के बीच स्वतंत्र रूप से स्विच कर सकते हैं, किसी भी टैब के तहत कोई भी सामग्री जोड़ सकते हैं, या तो टैब से बचा सकते हैं, और गड़बड़ स्वरूपण के बारे में चिंता करने की ज़रूरत नहीं है!

यह वास्तव में मेरे प्रारंभिक प्रश्न के सभी 5 बिंदुओं को हल करता है। बिंदु 2 अभी भी थोड़ा परतदार है, लेकिन मैं अधिकांश लोगों के उद्देश्यों के लिए विश्वास करता हूं, इस मुद्दे का ध्यान रखता है। मैं कुछ बिंदु पर इस प्लगइन के माध्यम से बहने और आवश्यक भागों को निकालने की योजना बना रहा हूं, इसे अपने खोज के साथ जोड़ रहा हूं, और इसे सार्वजनिक डाउनलोड पर रीपैकेजिंग कर रहा हूं। यहाँ मेरा लक्ष्य एक सरल एक क्लिक इंस्टॉल प्लगइन बनाना है जो अपेक्षा के अनुरूप है।

आशा है कि यह हर किसी की मदद करता है!


3

सबसे पहले, मुझे लगता है कि WP संस्करण 3.5 के बाद से इस समस्या को हल किया गया था; टिकट 19666 trac में देखें । लेकिन टिनीएमसीई में एक हुक होता है जो हमें संपादक के अंदर की सामग्री को बदलने का मौका देता है और आपको फ्रंटएंड पर आउटपुट पर पार्स नहीं करना चाहिए।

एक छोटा स्रोत स्क्रिप्ट। मेरे पास वर्तमान WP संस्करण के साथ इसका कोई परीक्षण नहीं है, एक ग्राहक के लिए एक पुराना समाधान था।

प्लगइन के माध्यम से इस स्रोत को जोड़ें और मार्कअप बढ़ाएं। एचटीएमएल-टैग के लिए फ़ंक्शन की जाँच करें <preऔर यदि मौजूद है, तो मार्कअप के साथ बदल दिया जाएगा।

add_filter( 'tiny_mce_before_init', 'fb_correction_content_tiny_mce' );

function fb_correction_content_tiny_mce( $init ) {

    $init['setup'] = "function(ed) {
        ed.onBeforeSetContent.add( function(ed, o) {

            if ( o.content.indexOf('<pre') != -1 ) {
                o.content = o.content.replace(
                    /<pre[^>]*>[\\s\\S]+?<\\/pre>/g,
                    function(a) {
                        return a.replace(/(\\r\\n|\\n)/g, '<br />');
                    }
                );
            }
        } );
    }";

    return $init;
}

3.5 में हल किया गया समस्या समान समस्या नहीं है। मेरे पास समस्या यह नहीं है कि विज़ुअल से HTML पर स्विच करते समय लाइन ब्रेक छीन लिए गए हैं, यह है कि मेरे सभी टैग, यहां तक ​​कि पूर्व टैग में भी, स्रोत HTML के रूप में व्याख्या किए जाते हैं और प्रदर्शित नहीं होते हैं क्योंकि वे संस्थाओं के रूप में एन्कोडेड नहीं हैं। HTML पैनल में। क्या यह फ़ंक्शन TinyMCE के व्यवहार को संशोधित करेगा ताकि संसाधित के बजाय पूर्व में HTML प्रदर्शित हो?
थॉट स्पेस डिजाइन

एक छोटे से परीक्षण में यह काम करता है, संस्थाओं को html से दृश्य पर स्विच किया जाएगा, वापस भी और सामग्री को बचाने के साथ।
बुलेटी

मैं यह सुनिश्चित करने के लिए आज बाद में परीक्षण करूंगा कि यह वही है जो मैं देख रहा हूं।
थॉट स्पेस डिजाइन

ठीक है, आपके उत्तर की प्रतीक्षा करें और शायद यह मदद करता है। मैंने प्रश्न पर आपके उदाहरण से स्रोत के साथ इसका परीक्षण किया है। अगर मैं इसे सही नहीं समझता, तो कृपया इसे यहाँ बढ़ाएँ।
bueltge

मेरा जवाब देखिए ...
थॉट स्पेस डिजाइन

0

मुझे ओपी के समान एक समस्या थी, लेकिन मेरे लिए इसे ध्यान <h1>में रखते हुए एक मुद्दा था <div>। पाठ और दृश्य टैब के बीच स्विच करते समय मैं यही रखना चाहता था: h1 in div और div अंदर

हर बार जब मैंने टैब स्विच किया तो <h1>गायब हो गया। मैंने बहुत खोज की, और वर्डप्रेस 4.7.3 के लिए मुझे पता चला कि वहाँ बहुत सारे पुराने फिक्स हैं। संस्करण 3 से 4 तक TinyMCE का मेयर अपग्रेड था। v.3 के लिए समाधान v.4 के लिए काम नहीं करता था। अधिक googling और TinyMCE संस्करण 4 मूल दस्तावेज पढ़ने के बाद मैं विशेष रूप से अपने मामले के समाधान के साथ आया:

  1. उन्नत TinyMCE कॉन्फ़िगरेशन प्लगइन स्थापित करें
  2. सेट valid_childrenकरने के लिए TinyMCE सेटिंग+div[h1],h1[div]
  3. मैंने एडिटोननली को कॉन्फ़िगर किया indent=true, forced_root_block=falseऔर schema=html5(जब मैंने forced_root_blockविवरण पढ़ा तो मैंने इसे एक wpautopविकल्प के रूप में समझा )

परिणामस्वरूप मुझे यह मिलता है (और यह टैब स्विचिंग के लिए प्रतिरोधी है) यहाँ छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.