How to show README.md in a web page in Laravel? - laravel

I hava a laravel project, there is a README.md in the root directory. I can see the render result after pushing to GitHub, but I want to render markdown document in the local development browser.
I am trying two ways:
Read file from markdown file
convert markdown file to html with something like Webpack
Who can give a demo for this?

Since the mail blade templates parse markdown, you can use a similar approach to layout.blade.php which uses Illuminate\Mail\Markdown::parse.
In your template, such as welcome.blade.php, add this:
{{ Illuminate\Mail\Markdown::parse(file_get_contents(base_path() . '/README.md')) }}

Here is a Laravel Mix / Webpack solution, convert markdown file to html, and required in Vue.js, then show it with v-html.
First add markdown-loader
yarn add markdown-loader html-loader
Add config in webpack.mix.js, Laravel Mix can add custom config of Webpack.
mix.webpackConfig({
module: {
rules: [{
test: /\.md$/,
use: ["html-loader", "markdown-loader"],
}]
}
});
Considering README.md is in the root of Project, add a alias in webpack.mix.js
mix.alias({
'#': '/resources/js',
'#root': '/',
});
Now we can use a vue component to show the README.md at the root directory.
<script>
const readme = require('#root/README.md')
export default {
data() {
return {
readme: ""
}
},
created() {
this.readme = readme
}
}
</script>
<template>
<div class="container" ref="container" v-html="readme" />
</template>

Related

Laravel mix removes subfolder from image path

I've set up an alias for my public folder where I've placed my images.
So they are inside public/images. I have a subfolder for certain types of images - in this case, card brands.
They're in public/images/card-brands
Here is my alias config:
mix.webpackConfig({
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': __dirname + '/resources/js',
'#public' : __dirname + '/public'
},
},
})
I'm importing the images in my vue component file:
import amex from '#public/images/card-brands/amex.svg'
import discover from '#public/images/card-brands/discover.svg'
import visa from '#public/images/card-brands/visa.svg'
import mastercard from '#public/images/card-brands/mastercard.svg'
Then using it inside my components data like so:
export default {
name: 'PaymentMethod',
data() {
return {
...
visaSvg: visa,
mastercardSvg: mastercard,
discoverSvg: discover,
amexSvg: amex,
currentCardBrand: this.initialCurrentCardBrand
...
}
},
props: {
...
initialCurrentCardBrand: String,
...
}
computed: {
getCurrentCardBrandSvg() {
switch (this.currentCardBrand) {
case 'mastercard':
return this.mastercardSvg;
break;
case 'visa':
return this.visaSvg;
break;
case 'amex':
return this.amexSvg;
break;
case 'discover':
return this.discoverSvg;
break;
}
}
}
...
Finally, I'm using it on my template as and image src: <img class="w-10" :src="getCurrentCardBrandSvg">
Now, even though the images and my import path are using the card-brands subfolder, the URL that is generated ignores this and just looks for the images in the root images folder.
It should be:
/public/images/card-brands/visa.svg
but it's generating as
/public/images/visa.svg
How can I get it to keep my subfolder?
try this instead {{ asset('/images/card-brands/mastercard.svg')) }}
I faced a similar issue in laravel. I used the above format.Please correct me if Im wrong.
Edit: This could be slightly wrong. It works correctly for importing images via javascript, but I think grabbing images via laravel in blade templates still needs the images in the public folder.
The issue was not knowing that I was supposed to put my images folder inside the resources folder rather than public.
Laravel Mix will compile the images like it does the JS and SCSS and place it in public automatically.
So I created an images folder in resources, deleted my manually made images folder in public, and made an alias:
alias: {
'#images': __dirname + '/resources/images'
}
and now I can link to that inside my vue component.
import amex from '#images/card-brands/amex.svg'
import discover from '#images/card-brands/discover.svg'
import visa from '#images/card-brands/visa.svg'
import mastercard from '#images/card-brands/mastercard.svg'
The generated images will automatically be placed in public on the root level once I run npm run dev or npm run prod

Laravel get $primary from scss into Blade

I use Laravel with SCSS / Webmix. I have the file _variables.scss and set some variables like $primary and $secondary.
Now I want to use this variables in Blade especially in Mailtemplates. How can I realize this?
Can I load it directly from Blade template? Is it possible to get variables in Controller and pass it to Blade?
Create a "configuration" json file e.g.
config.json and put it somewhere (e.g. in resources)
{
"primary": "<Color>"
}
If you are using webpack with sass-loader then you can customise your loader rules:
const injectedColours = require('config.json');
module: {
rules: [
{
test: /\.sccs$/,
use: [
{
loader: 'scss-loader',
options: {
data: '$primary: ' + injectedColours.primary
}
}
]
}
]
}
Then you can remove the $primary entry in your _variables.scss file.
If you're using Laravel mix you can refer to https://laravel.com/docs/6.x/mix#custom-webpack-configuration on how you can merge the above in your default configuration
In your controller you can also read the same json file e.g.
$primary = json_decode(file_get_contents('config.json'))->primary;

how to access vue.js api key in laravel application

hello there i am trying to access my youtube api key located in the .env file from within this code:
<template>
<div class="YoutubeDash__wrapper">
<video-group :videos="videos"></video-group>
</div>
</template>
<script>
import VideoGroup from './VideoGroup.vue';
import Search from './Search';
export default {
components: {
VideoGroup
},
created(){
Search({
apiKey: process.env.VUE_APP_SECRET,
term: 'laravel repo'
}, response => this.videos = response);
},
data(){
return {
videos: null
}
}
}
</script>
According to the documentation using env variables with vue.js. Everything seems to be correct. In my .env file i say: VUE_APP_SECRET=xxxxxxxxxxxxxxx, what am i missing here ?
I get this error message:
app.js:37809 Error: YouTube search would require a key
Any tips are welcome! Thanks a lot!
We need to work with a small amount of information here so I am going to make a few assumptions (based on the tags) mostly that you are using laravel and laravel-mix to compile your resources.
For laravel(-mix) to make your .env variables accessible by JS you need to prefix them with MIX_ i.e. MIX_VUE_APP_SECRET. This will make your variable accessible as process.env.MIX_VUE_APP_SECRET.
I prefer excluding laravel-mix from this process.
Usually, in my blade entry-point I use meta tags:
<meta name="myVal" content="{{ config('<any-config-key>') }}">
<any-config-key> can be any laravel configuration key including those taken from .env.
Then, in my javascript I do something like:
const setVueGlobal = (metaHeaderName, vueGlobalName) => {
let value = document.head.querySelector('meta[name="' + metaHeaderName + '"]').content;
if (!value) {
console.error('some error msg');
return null;
}
Vue.prototype[vueGlobalName] = value;
return value;
};
setVueGlobal('myVal', '$myVal');
Finally, accessing using this.$myVal

How to create a Fusebox project with multiple html pages?

I'm new to bundlers and am currently learning about Fusebox. I really like it so far except that I can't figure out how to use it for a multi-page project. So far I've only been able to find a tutorial on how to do this using webpack, not for fusebox.
Input files in src folder:
index.html
index2.html
index.ts
Desired output in dist folder:
app.js
vendor.js
index.html
index2.html
Actual output in dist folder:
app.js
vendor.js
index.html
Here is my config in the fuse.js file:
Sparky.task("config", () => {
fuse = FuseBox.init({
homeDir: "src",
output: "dist/$name.js",
hash: isProduction,
sourceMaps: !isProduction,
plugins: [
[SassPlugin(), CSSPlugin()],
CSSPlugin(),
WebIndexPlugin({
title: "Welcome to FuseBox index",
template: "src/index.html"
},
WebIndexPlugin({
title: "Welcome to FuseBox index2",
template: "src/index2.html"
},
isProduction && UglifyJSPlugin()
]
});
// vendor should come first
vendor = fuse.bundle("vendor")
.instructions("~ index.ts");
// out main bundle
app = fuse.bundle("app")
.instructions(`!> [index.ts]`);
if (!isProduction) {
fuse.dev();
}
});
Setting WebIndexPlugin twice within plugins doesn't work. What is the correct way to set up a multi-html page project with fusebox?
The WebIndexPlugin can not be configured, to output more than one html file.
But if you don't use a hash for the generated bundles (e.g.: output: "dist/$name.$hash.js"), you don't need the WebIndexPlugin -- you can remove it completly from the plugins option. Because you already know the names of the generated bundles (vendor.js and app.js) you can just include the following lines
<script src="vendor.js"></script>
<script src="app.js"></script>
instead of the placeholder $bundles.
If you want, that both html files are copied from your src directory into your dist directory, you can add the following lines to your fuse.js script:
const fs = require('fs-extra');
fs.copySync('src/index.html', 'dist/index.html');
fs.copySync('src/index2.html', 'dist/index2.html');
Note: Don't forget to add fs-extra:^5.0.0 to your package.json
Might not been the case when the question was asked, but WebIndexPlugin now can be specified multiple times and also takes optional bundles parameter where list of bundles to be included in html can be specified (all bundles are included by default).
For example 2 html files (app1.html, app2.html) where each includes a common library (vendor.js), and different entry points (app1.js and app2.js)
app1.html
vendor.js
app1.js
app2.html
vendor.js
app2.js
Config would look like this:
const fuse = FuseBox.init({
homeDir : "src",
target : 'browser#es6',
output : "dist/$name.js",
plugins: [
WebIndexPlugin({
target: 'app1.html',
bundles:['vendor', 'app1']
}),
WebIndexPlugin({
target: 'app2.html',
bundles:['vendor', 'app2']
})
]
})
// vendor bundle, extracts dependencies from index1 and index2:
fuse.bundle("vendor").instructions("~[index1.ts,index2.ts]")
// app1 and app2, bundled separately without dependencies:
fuse.bundle("app1").instructions("!>index1.ts")
fuse.bundle("app2").instructions("!>index2.ts")

Loading D3 with Nuxt/Vue

I am trying to implement D3 in an app I am building with Nuxt. I have successfully imported it into a view in the <script> section with import * as d3 from 'd3' however because the app is being rendered server-side D3's functionality doesn't work (i.e. d3.select(...)) due to the lack of browser. In the Nuxt plugin documentation it suggests a pattern for client-only external plugins:
module.exports = {
plugins: [
{ src: '~plugins/vue-notifications', ssr: false }
]
}
I attempted to implement the pattern in the nuxt.config.js of my project:
module.exports = {
head: {
title: 'My Demo App',
meta: [...],
link: [...]
},
loading: {...},
plugins: [
{ src: '~node_modules/d3/build/d3.js', ssr: false}
]
}
However D3 throws a ReferenceError while looking for document and Nuxt throws a SyntaxError in the console pointing to something in the plugins field of nuxt.config.js.
For reference, demo.vue:
<template>
<div class="demo-container"></div>
</template>
<script>
import * as d3 from 'd3';
d3.select('.demo-container');
</script>
Would someone be able to point to what I'm doing wrong?
For anyone coming to this page looking for a solution,
these suggestions from piyushchauhan2011 here on GitHub sent me in the right direction.
All I needed to do:
import d3 in my single-file component, and then
do any DOM manipulation with d3 only within mounted()
Before all this, I had to of course add d3 to my project with yarn add d3 (or npm install d3).
[Edit: removed link that no longer works. It wasn't that relevant anyway.]
I was getting an error:
Must use import to load ES Module: .../node_modules/d3/src/index.js require() of ES modules is not supported. require() of .../node_modules/d3/src/index.js from .../node_modules/vue-server-renderer/build.dev.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from .../node_modules/d3/package.json.
I solved it by reading this: https://github.com/nuxt/nuxt.js/issues/9223
which indicates you can add this to your nuxt.config.js file:
build: {
standalone: true,
}
This allowed the d3 import to work.
import * as d3 from "d3";
Here's a simple step-by-step tutorial:
Create a new NuxtJS project (Skip this step if you have an existing project)
npm init nuxt-app nuxtjs-d3js-example
Install D3JS
npm install d3
npm install #types/d3 --save-dev
Import D3JS and add a target
HTML:
<p id="d3-target"></p>
JavaScript:
import * as d3 from 'd3'
export default {
name: 'NuxtTutorial',
mounted: function() {
d3.select("#d3-target").text("This text is manipulated by d3.js")
},
}
Fix ES Module error (mentioned by #agm1984)
Error:
require() of ES Module /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/d3/src/index.js from /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/vue-server-renderer/build.dev.js not supported. Instead change the require of index.js in /home/johnson/projects/nuxtjs-d3js-example/nuxtjs-d3js-example/node_modules/vue-server-renderer/build.dev.js to a dynamic import() which is available in all CommonJS modules.
nuxt.config.js:
build: {
standalone: true,
}
A minimal project example can be found at: https://github.com/j3soon/nuxtjs-d3js-example, with each step detailed in the Git commit history.

Resources