How to display blog post with HTML code snippets in Laravel - laravel

My blog posts are saved in a DB in text format and I can't find the way of displaying HTML code between the paragraphs as you can see in the image below.
I'm using Prismjs and <pre><code></code></pre> tags..
Inside the code block there should be two <div> tags which are not displayed.
Looks like this in the database table
Laravel is a web application framework with expressive, elegant syntax. A web framework provides a structure and starting point for creating your application, allowing you to focus on creating something amazing while we sweat the details.
Laravel strives to provide an amazing developer experience while providing powerful features such as thorough dependency injection, an expressive database abstraction layer, queues and scheduled jobs, unit and integration testing, and more.
Whether you are new to PHP or web frameworks or have years of experience, Laravel is a framework that can grow with you. We'll help you take your first steps as a web developer or give you a boost as you take your expertise to the next level. We can't wait to see what you build.
<pre><code class="lang-html">
<div>test</div>
</code></pre>
In my post_body.blade.php view I'm using {!! nl2br($post->body) !!} to display the content of the post.
If I use <pre><code class="lang-html">{{ $post->body }}</code></pre> on the blade view the code is visible but I have no way of including the text of the post. It would only work to show code.
I'm facing the problem of not been able to do both things, is one or the other.

There is no straightforward way of doing this by using standard Laravel/Blade output options. However it's possible to accomplish it with a little bit of extra code.
1. Why is this happening
Neither <pre> or <code> is stopping the browser to interpret the text inside as html code. They have different purpose: one is to tell the browser that the whitespaces are important and the other to tell that the content is some computer code and needs to be shown with different styling. In both cases if valid HTML code is inside the tags it will be treated as HTML.
By the way it's mentioned in Prism documentation that you need to escape the content:
Note: You have to escape all < and & characters inside < code > elements
(code blocks and inline snippets) with < and & respectively, or
else the browser might interpret them as an HTML tag or entity. If you
have large portions of HTML code, you can use the Unescaped Markup
plugin to work around this.
2. Solutions
There are different ways of solving your issue. You can either modify the input before saving it to the database and then just print the unescaped contents or modify the output and make sure you have escaped only the text in the <code> tag.
Because we don't know much about the input method you use let's focus on the second option to modify the output.
A. PrismJS
Their documentation points to a solution where you can use the Unescaped markup plugin to solve your issue. I don't have any experience with it, but the slogan says "Write markup without having to escape anything.", so it seems it will do the work.
You only need to include the plugin and then you have two options: to swap <pre><code> for <script> or to use HTML-comment to wrap your code (if you don't have other comments in the code
Just look at their examples for detailed information
B. PHP
You can use PHP to parse the text from the database and escape the content of the needed elements. In your case this is the code element. You will need to write your own implementation or use the one that I wrote for your case.
Then you can just do:
{!! Houdini::escape($content) !!}
Include or autoload the following class:
class Houdini
{
/**
* Escape the html characters inside a given HTML element
*
* #param string $text The text we are trying to clean
* #param string $element The name of the elements to be escaped
* #param bool $fix Should we try to make the text a valid HTML by wrapping it with divs
*
* #return string
*/
public static function escape($text, $element = 'code', $fix = true) {
$dom = new DOMDocument;
$dom->loadXML($fix ? '<div>' . $text . '</div>' : $text);
$nodes = $dom->getElementsByTagName($element);
foreach ($nodes as $node) {
$content = '';
foreach ($node->childNodes as $child) {
$content .= self::escapeRecursively($child);
}
$node->nodeValue = htmlspecialchars($content);
}
return $dom->saveHTML();
}
/**
* Escape node and note contents
*
* #param $node
* #return string
*/
protected static function escapeRecursively($node) {
if ($node instanceof DOMText)
return $node->textContent;
$content = "<$node->nodeName>";
foreach ($node->childNodes as $child) {
$content .= self::escapeRecursively($child);
}
return "$content</$node->nodeName>";
}
}
C. JavaScript
You can include the following javascript code which will loop trough all the <code> elements and set the innerHtml as the innerText.
document.querySelectorAll("code").forEach(el => el.innerText = el.innerHTML);
Note: If you keep the paragraphs in the database separated only with new lines and not wrapped in <p> you will have issues using this solution and nl2br() together.
D. Deprecated <xmp>
<pre><code class="lang-html">
<xmp><div>test</div></xmp>
</code></pre>
There WAS after all an HTML tag specifically to show example HTML code as it is, but it was deprecated in HTML 3.2, BUT it seems the tag is widely supported and wrapping the code contents can be a quick and dirty solution for your case. You can see the support tables here: https://caniuse.com/?search=xmp
Read more here: https://html.com/tags/xmp/#ixzz74T0AJctF
You can accomplish this by adding the tags before saving to the database or when printing the output with JavaScript on the client side or with PHP before passing it to the blade template.
3. Other StackOverflow posts that helped me for this answer
Escape HTML Chars In the Pre Tag
How to show <div> tag literally in <code>/<pre> tag?

Related

Theme is caching previous user name

We are using CAS to login to our Drupal instance. This is working correctly and displaying the correct user content (blocks etc. based on roles). What is not working correctly is the small snippet in the theme that says welcome . It keeps showing the previous user who logged in.
How do I set this in bigpipe?
The code looks like this in the theme: <span id="user_name">{{user.displayname}}</span>
Is there a way to tell bigpipe not to cache this?
This code snippet is on one of our twig files header.twig.html which is a partial.
I ended up putting this in a block, and just referencing the block section in the theme instead of just pulling that, then I used the block to be ignored for caching.
Thanks!
I used this post with other resources to solve a similar problem. We were including {{ user.displayname }} in a twig template for the header on all pages of our site. Some users were seeing other users' names in the header after signing in. We wanted to solve the problem while impacting caching as little as possible. Here, I share in detail what we did in the hope that it will help others. I'll use the specific names used in our code. Readers will need to adjust to their own names. (The code follows our prescribed format, so please forgive that it isn't standard.)
Step 1
Create a custom module. Custom module creation is covered adequately in other places, so I won't give details here. Our custom module is named rsc.
Step 2
Create the folder modules/custom/rsc/src/Plugin/Block and in it create a file named DisplayName.php.
Step 3
In the file DisplayName.php, include the following:
<?php
namespace Drupal\rsc\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\user\Entity\User;
/**
* A block to show the user's display name
*
* #Block(
* id = "display_name",
* admin_label = "Display Name"
* )
*/
class DisplayName extends BlockBase // The class name must match the filename
{
public function build()
{
$user = User::load(\Drupal::currentUser()->id());
return
[
'#type' => 'markup',
'#markup' => $user->getDisplayName(),
'#cache' => ['contexts' => ['user']]
];
}
}
Step 4
Clear the Drupal cache to make the new block available at Block Layout.
Step 5
Go to Admin > Structure > Block Layout and place the Display Name block in the Hidden Blocks For Referencing - Not Displayed section (bottom of the list on our site). In the Configure Block dialog, edit the Machine name to display_name to match id in the code above. Clear the Display title checkbox and save. Doing this makes the block available for use in twig templates.
Step 6
In the twig template for the header, replace
{{ user.displayname }}
with
{{ drupal_entity('block', 'display_name') }}
The drupal_entity function is part of the twig_tweak module, which we were already using. It allows insertion of a custom block into a twig template. If you're not using this module, you'll need to install it, or find another method of including a block in a twig template.
Step 7
Clear the Drupal cache to make the modified template take effect.
If you see anything about this that can be improved, please comment.

Magento email template: Block template inheritance broken

Problem
When I try to add a block into my transactional email template in the following manner:
{{block type='core/template' area='frontend' template='invent/baskettimer/email_items.phtml' record=$record}}
I get the following error, and nothing is rendered.
CRIT (2): Not valid template file:frontend/base/default/template/invent/baskettimer/email_items.phtml
Troubleshooting
Normally this warning points to a typo which is breaking the inheritance but I have quadruple checked and this should work.
I then copied the file into the base and did a test, it rendered correctly.
Create a custom block and set the template, same error is displayed.
Theory
To me it seems template inheritance is broken / not implemented for emails, so it is always looking in base, I cannot put my templates there so I am not sure how to call them.
Possible workarounds
Render the block to html then send it to as a variable to render, problem with this is I am sending the emails from Model level and am having a hard time pre rendering the block, even with a helper.
Render the data using a method, don't really want to do this as it is message / against MVC.
Any help is much appreciated.
Bounty update
So I have traced down the problem, it is probably an easy solution now.
The problem is that I am calling it from a cronjob does not have the correct store view, it is fairly easy to replicate similar situation by using a shell script, then changing the _appCode to null.
<?php
require_once 'abstract.php';
class Mage_Shell_Shell extends Mage_Shell_Abstract
{
protected $_appCode = ''; // works - remove to not work
/**
* Run script
*
*/
public function run()
{
Mage::getModel('invent_baskettimer/email')->sendJob();
}
}
$shell = new Mage_Shell_Shell();
$shell->run();
So basically the question has become:
How do I call a block->toHtml() regardless of store view?
There is not way of setting a cronjob to be like that. Lucky magento lets you emulate your store views, see the following to emulate the default store.
public function cronjob()
{
$iDefaultStoreId = Mage::app()
->getWebsite()
->getDefaultGroup()
->getDefaultStoreId();
$appEmulation = Mage::getSingleton('core/app_emulation');
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($iDefaultStoreId);
.. do your stuff here ..
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
}
For more info see: http://inchoo.net/ecommerce/magento/emulate-store-in-magento/

How to enable Auto Complete in PHPStorm for CodeIgniter framework

In CodeIgniter Project, I've normally use following commands to execute sql.
$res = $this->db->select('*')
->from('customer')
->where('customer.id', $id)
->get();
But unfortunatly my PHP Storm(5.0) didn't support multiple autocomplete(I don't know how to say this)
For example in netbeans If I typed
$res = $this->db->select('*')->
It will auto pop up the rest of the function. But In PHPStorm It didn't wokring.
Its working first level auto complete only.
download https://github.com/topdown/phpStorm-CC-Helpers/releases
Mark as Plain Text
/system/core/Controller.php
/system/core/Model.php
/system/database/DB_active_rec.php
Then Extract the downloaded archive, copy it to your project root
That's all
Mifas links do the same too though
Answering to a very old but still pertinent question -
I found a better solution herein - http://validwebs.com/346/code-completion-for-codeigniter-in-phpstorm/ and coincidentally it is from the same author/project owner Jeff Behnke.
Quoting from therein which should be read in continuation of the answer by Sabir -
Mark as Plain Text
/system/core/Controller.php
/system/core/Model.php
/system/database/DB_active_rec.php
Marking those files as plain text stops phpStorm from indexing them as
sources.
I consider the solution in the link better because it explains the rationale behind the steps performed.
It additionally explains how we can achieve code completion in views and fix for undefined vars.
Quoting once again from the original source for easy reference and preservation herein :
Code Completion in Views and fixing undefined vars.
Example controller code.
public function index()
{
// Example view vars
$data['test'] = 'Testing vars in CodeIgniter! This is from $data["test"].';
$this->load->view('welcome_message', $data);
}
We added a data array to the view the CI way. Each index in the array
is another variable.
The view…
In phpStorm $test will be highlighted as an undefined var. To fix this
we use phpDoc annotations.
<p style="font-weight: bold;">
<?php
/**
* $data array holds the $test value
*
* #see Welcome::index()
* #var Welcome $test
*/
echo $test;
?>
</p>
Documenting this way not only fixes the phpStorm error/warning but
also gives us documentation popup for $test. Also the #see will link
to the location it was created, in this case index method in the
Welcome class.
The var is now defined and shows it is.
Ctrl+ Click on this method link will bring you right to the method
where $test is defined.
Herein are a few discoveries of my own while adding customisations to my project:
If you want your custom application libraries from CI to be available for auto-completion as well then there are these 2 scenarios which may be helpful :
1. For custom extended libraries such as MY_Upload extending the CI_Upload class
Replace #property CI_Upload $upload with #property MY_Upload $upload in CI_phpstorm.php
This shall make all the class variable and function names of MY_Upload available for auto-completion in addition to that of CI_Upload.
2. For completely custom libraries written from scratch within the CI application -
For e.g. to enable auto-completion from Custom_Library.php residing in the application/libraries folder, you need to add to the php doc in CI_phpstorm.php #property Custom_Library $custom_library

Syntax for outputting raw with 'using'

I'm implementing AuthorizeNet into my site and as per [this posting] I am to use something like:
#using (Html.BeginSIMForm("http://...", 1.99M, "...", "...", true))
{
#Html.CheckoutFormInputs(true);
#Html.Hidden("order_id", "1234");
<input type = "submit" value = "Pay" />
}
the trouble is that the BeginSIMForm method outputs HTML which, of course, gets escaped by Razor, so I need to output raw.
I've tried:
#Html.Raw(using(html.BeginSIMForm()) { ... })
but that's no good. I can't quite get the syntax right. is there a way to tell Razor to generate raw output between certain markers?
* update *
I missed something which was in the posting. what I need to do is wrap the call to .CheckoutFormInputs() like this:
#Html.Raw(Html.CheckoutFormInputs(true));
and that produces the right output... however, the call to .BeginSIMForm() produces output (a form) at the very top of my page and breaks everything. grr...
I've had a look at the source code for their helper. what garbage. I recommend anyone wanting to implement this service on Razor not bother downloading it. I will code the forms by hand. may come back with some code.
Based on the thread you referenced, it seems like that component is not implemented correctly with respect to how it writes the output. You should contact the authors of that library and verify that it supports MVC 3 including the Razor view engine.
I have a detailed answer here
https://stackoverflow.com/a/8426501/1087034
I hope this helps.

Page-specific logic in Joomla

I am trying to enable JavaScript in a Joomla template to behave differently depending on the page. In particular, I have set the Key Reference as that appears to be the most appropriate value I could find for this purpose. Unfortunately, I can't seem to access it in my code. I tried:
$this->params->get("keyref")
and a few other variations, but they simply returned a blank. How can I retrieve this value or is there a better way of writing page specific logic.
Related Articles
Joomla load script in a specific page: This would work, but seems like overkill for what I want to do here.
Each page can be given an alias. We can retrieve the alias using code from the forum:
function getCurrentAlias()
{
$menu = &JSite::getMenu();
$active = $menu->getActive();
return $active->alias;
}
We can then inject this into the Javascript:
var alias= '<?php echo getCurrentAlias(); ?>';
I'm not aware of keyref, but I would solve it by using the class suffix parameter you can set for each menu entry.see I would use a space in front of this suffix. With javascript you can then try to read this classname (suffix without the space) on each page.
getElementsByClassName("mysuffix");
for example
If this returns multiple objects, you know on which page you are. Will that help you?

Resources