I am Building a site using Contentful and have followed different guides and configurations. No matter what I do I can't seem to get a basic example of markdownit working. I keep getting an error:
Property or method "$md" is not defined on the instance but referenced during render.
can't get any examples in the docs working:
https://openbase.com/js/#nuxtjs/markdownit
I have even deleted the whole template and tried simple versions. I have also tried different set ups in the config file below.
I have run 'yarn build', 'yarn add markdown-it'
and neither seem to have helped
here is what I am trying to get to work eventually:
<article v-html="$md.render(post.fields.body)"></article>
This is one example I am following and it seems to be working here on the live demo:
https://github.com/sdras/contentful-nuxt-netlify/blob/e80e6552eef812320a7bd2dd66ad3fa8ebf5f840/pages/_slug.vue
In context - pages/_id/index.vue
<template>
<div class="post-component">
<a #click="$router.go(-1)">Go back to overview</a>
<hr />
<h1>{{post.fields.title}}</h1>
<p></p>
<p>
{{post.fields.body}}
</p>
<article v-html="$md.render(post.fields.body)"></article>
</div>
</template>
<script>
import {createClient} from '../../plugins/contentful';
const contentfulClient = createClient();
export default {
name: 'index',
asyncData ({ env, params }) {
return contentfulClient.getEntries({
'content_type': env.CTF_BLOG_POST_TYPE_ID,
'fields.slug': params.id
}).then(post => {
return {
post: post.items[0]
}
}).catch(console.error)
}
}
</script>
nuxt.config.js
const config = require('./.contentful.json')
module.exports = {
// ...
env: {
CTF_SPACE_ID: config.CTF_SPACE_ID,
CTF_CDA_ACCESS_TOKEN: config.CTF_CDA_ACCESS_TOKEN,
CTF_PERSON_ID: config.CTF_PERSON_ID,
CTF_BLOG_POST_TYPE_ID: config.CTF_BLOG_POST_TYPE_ID
}
// ...
}
export default {
// Target: https://go.nuxtjs.dev/config-target
target: 'static',
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'thomasulman',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'nuxt-buefy',
"#nuxtjs/markdownit"],
markdownit: {
runtime: true, // Support `$md()`
injected: true,
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
package.json
{
"name": "******",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"#nuxtjs/markdownit": "^1.2.10",
"contentful": "^8.4.2",
"core-js": "^3.15.1",
"markdown-it": "^12.1.0",
"nuxt": "^2.15.7",
"nuxt-buefy": "^0.4.8"
},
"devDependencies": {}
}
just in case it helps:
index.vue
<template>
<div>
<!-- <Navigation /> -->
<!-- render data of the person -->
<h1>{{ person.fields.name }}</h1>
<!-- render blog posts -->
<ul>
<li v-for="post in posts">
{{ post.fields.title }}
<nuxt-link :to="post.fields.slug" class="more">Read more ⟶</nuxt-link>
</li>
</ul>
</div>
</template>
<script>
import { createClient } from '~/plugins/contentful.js'
const client = createClient()
export default {
// `env` is available in the context object
asyncData({ env }) {
return Promise.all([
// fetch the owner of the blog
client.getEntries({
'sys.id': env.CTF_PERSON_ID
}),
// fetch all blog posts sorted by creation date
client.getEntries({
'content_type': env.CTF_BLOG_POST_TYPE_ID,
order: '-sys.createdAt'
})
]).then(([entries, posts]) => {
// return data that should be available
// in the template
return {
person: entries.items[0],
posts: posts.items
}
}).catch(console.error)
}
}
</script>
I've achieved to make it work properly as shown here: https://github.com/nuxt-community/markdownit-module#usage
I've added a proper HTML sanitizer too, check the plugins directory.
You can find the working Github repo here: https://github.com/kissu/so-nuxt-markdownit
This configuration was enough so far for me
nuxt.config.js
plugins: [
'~/plugins/vue-dompurify'
],
modules: [
'#nuxtjs/markdownit'
],
markdownit: {
runtime: true, // Support `$md()`
// preset: 'default',
// linkify: true,
// breaks: true,
// use: [
// 'markdown-it-div',
// 'markdown-it-attrs'
// ]
}
And those 2 files are working properly
index.vue
<template>
<div>
<div v-dompurify-html="$md.render(model)"></div>
<br/>
<br/>
<div v-dompurify-html="testMarkdownContent"></div>
<nuxt-link to="/inline">Inline markdown working too!</nuxt-link>
</div>
</template>
<script>
import testMarkdown from '../blog/test.md'
export default {
data() {
return {
model: '# Hello World!'
}
},
computed: {
testMarkdownContent() {
return testMarkdown
}
}
}
</script>
inline.vue
<template lang="md">
# Hello World!
Current route is: {{ $route.path }}
<nuxt-link to="/">Back to index</nuxt-link>
</template>
The issue with the whole thing was that // module.exports {} was overwriting the export default {} in the config file.
Related
So I'm using vite to build my Vue 3 application for a legacy website which still uses jQuery and a few other JS frameworks.
I'm using the esm bundler as I would still like to boot it up and use it with slotted components.
<div id="app">
<vue-component-name></vue-component-name>
</div>
And it works perfectly. But when jQuery is used on the page, no where near my components it seems the esm bundled version of Vue has set a global variable named $ which breaks jQuery.
Has anyone had this issue or know of a way to fix it?
import { defineConfig } from 'vite';
import type { UserConfig as VitestUserConfigInterface } from 'vitest/config';
import svgLoader from 'vite-svg-loader';
import vue from '#vitejs/plugin-vue';
import path from 'path';
const vitestConfig : VitestUserConfigInterface = {
test: {
globals: true,
include: ['./tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
};
export default defineConfig({
test: vitestConfig.test,
plugins: [vue(), svgLoader()],
base: '/',
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
'#': path.resolve(__dirname, '/src'),
},
},
build: {
outDir: '../wwwroot/dist',
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: {
main: './src/main.ts',
},
output: {
entryFileNames: 'assets/js/[name].js',
chunkFileNames: 'assets/js/[name].js',
assetFileNames: ({ name }) => {
if (/\.(gif|jpe?g|png|svg)$/.test(name ?? '')) {
return 'assets/images/[name][extname]';
}
if ((name ?? '').endsWith('.css')) {
return 'assets/css/[name][extname]';
}
return 'assets/[name][extname]';
},
globals: {
vue: 'Vue',
},
},
},
},
server: {
hmr: {
protocol: 'ws',
},
},
});
EDIT:
More information, I've tracked this down to using
#input="handleInput($event.target, index)"
This right here breaks existing jQuery. Still no idea how to get around it
For anyone interested, How to wrap Vite build in IIFE and still have all the dependencies bundled into a single file?
Webpack configuration is a part of Vue CLI setup (can be checked with vue inspect). This is a relevant part of it:
entry: {
foo: [
'.../src/foo.js'
],
barWidget: [
'.../src/barWidget.js'
],
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
...
And HTML output is:
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/foo.[HASH].js"></script>
and
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/barWidget.[HASH].js"></script>
There's no problem for foo to have as many script tags as needed, but barWidget is widget entry point that is supposed to be loaded at once with no initial chunk dependencies. My intention is to make barWidget be loaded with a single line of code (hash will likely be disabled for this purpose):
<script type="text/javascript" src="/assets/js/barWidget.js"></script>
But in its current state it fails to load if chunk-vendors is omitted.
I'd prefer to keep vendors and common chunks as they are because they are splitted in a reasonable way and can be reused on client side between entry points, but I need barWidget to auto-load a chunk it depends on. A less preferable way would be to disable chunks but for barWidget only, chunk splitting in other entry points should remain unchanged.
A way to reproduce it is basically a new Vue CLI project with 2 entry points added, or any Webpack project with similarly configured splitting.
Here is the project (listed for completeness):
package.json
{
"name": "foobar",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0"
}
}
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html'
},
},
};
public/foo.html
public/barWidget.html
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
</body>
</html>
src/foo.js
import { createApp } from 'vue'
import Foo from './Foo.vue'
createApp(Foo).mount('#app')
Foo.vue
<template>
<HelloWorld msg="Foo"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
src/barWidget.js
import { createApp } from 'vue'
import BarWidget from './BarWidget.vue'
createApp(BarWidget).mount('#app')
BarWidget.vue
<template>
<HelloWorld msg="Bar widget"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
Can barWidget be forced to automatically load chunk-vendors.[HASH].js by means of Webpack, without loading it explicitly in the place where barWidget.[HASH].js is being used?
Can barWidget entry point be forced to not use other initial chunks (chunk-vendors, etc) and output self-sufficient barWidget.js bundle, without affecting the way splitting works in other entry points?
Are there other options for the described scenario?
I think that what you want is what is described in this webpack issue reply
the reply uses a function to exclude the dependencies of a specific entrypoint from being included in a chunk:
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
// ... your current config, just change the chunks property
// Exclude pre-main dependencies going into vendors, as doing so
// will result in webpack only loading pre-main once vendors loaded.
// But pre-main is the one loading vendors.
// Currently undocument feature: https://github.com/webpack/webpack/pull/6791
chunks: chunk => chunk.name !== "barWidget"
}
}
}
},
to do this with vue should be just a matter of changing the webpack config in the vue.config.js file like this:
module.exports = {
configureWebpack: config => {
config.optimization.splitChunks.cacheGroups.vendors.chunks =
chunk => chunk.name !== "barWidget";
}
}
I haven't tried this but I think it should work as is or with some minimal tweaks
You can use a function to filter the chunks. See this Webpack issue
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html',
chunks: ['barWidget']
},
},
chainWebpack: config => {
if (process.env.NODE_ENV !== 'test') {
config.optimization.splitChunks({
cacheGroups: {
defaultVendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: chunk => chunk.name !== "barWidget"
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
})
}
}
}
Note the pages.barWidget.chunks - it is needed because otherwise HtmlWebpackPlugin includes vendors chunk into barWidget.html even it is not needed at all...
Result:
Thanks to dotenv I can use environment variables in my nuxt.config.js file
Only I have whole settings that need to disappear depending on the environment. In some cases, I know how to use a tertiary condition, but in others, I cannot.
For example, for my dev environment, I have to do this :
export default {
head: {
title: process.env.APP_NAME,
},
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth',
'#nuxtjs/dotenv'
],
axios: {
baseURL: 'http://app.test/api',
},
…
}
And for my production environment I have to add some things
export default {
head: {
title: process.env.APP_NAME,
},
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth',
'#nuxtjs/dotenv',
'#nuxtjs/proxy'
],
axios: {
prefix: '/api/',
proxy: true
},
// also a new bloc
proxy: {
'/api/': {
target: 'https://my-api.app/'
}
},
…
}
How to do that simply?
The Nuxt config file is simply a normal .js file.
You can create and modify the exported object the same as any other object.
const isProd = true;
const nuxtConfig = {
head: {
title: process.env.APP_NAME,
},
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
'#nuxtjs/auth',
'#nuxtjs/dotenv'
],
axios: {
baseURL: 'http://app.test/api',
},
};
if(isProd) {
nuxtConfig.modules.push('#nuxtjs/proxy');
nuxtConfig.axios.proxy = true;
nuxtConfig.proxy = {
'/api/': {
target: 'https://my-api.app/'
}
}
}
export default nuxtConfig;
Use inline conditionals
If you only have minimal differences between environments, maintain the default nuxt.config.js structure and just use inline conditions (ie ternary operator) wherever you need.
Example:
head: {
title: process.env.NODE_ENV === 'prod' ? "my prod title" : "my dev title"
}
You can also chain multiple conditions...
head: {
title: process.env.NODE_ENV === 'prod1' ? "my prod title 1" : process.env.NODE_ENV === 'prod2' ? "my prod title 2" : "my dev title"
}
... however now you have more complexity. If it gets too deep, then maybe it's time to have logic outside of the main export object, as
#Jordan suggested.
Below code works fine if the lines are commented out but if I uncomment the lines below in the code I am getting the error shown below in the image. I couldn't find any similar examples online related the issue.
import React from "react";
import FullCalendar from "#fullcalendar/react";
import dayGridPlugin from "#fullcalendar/daygrid";
import timeGridPlugin from "#fullcalendar/timegrid";
// import listGridPlugin from "#fullcalendar/list"; // Throwing an error if this line is uncommented
// import interactionPlugin from "#fullcalendar/interacti1on"; // Throwing an error if this line is uncommented
const DemoApp = () => {
return (
<div>
<div className="calendar">
<FullCalendar
plugins={[
dayGridPlugin,
timeGridPlugin,
// interactionPlugin, // Throwing an error if this line is uncommented
// listGridPlugin, // Throwing an error if this line is uncommented
]}
headerToolbar={{
left: "today prev,next prevYear,nextYear",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listMonth",
}}
initialView="dayGridMonth"
events={[
{ title: "event 1", date: "2020-06-01" },
{ title: "event 2", date: "2020-06-04" },
{ title: "event 2", date: "2020-06-10" },
{ title: "event 2", date: "2020-06-17" },
]}
/>
</div>
</div>
);
};
export default DemoApp;
I have created my app using create-react-app template and I am using craco.config.js (used this for the purposes of Ant design ) shown below. I am struggling to override the webpack settings as suggested the fullcalendar documentation. When I downloaded the fullcalendar examples for react it works perfectly fine with webpack-config.js file. As I am using create-react-app template with craco.config.js I am not sure how to load css-loader settings in craco.config.js file.
Any suggestions or advice would be of great help.
Thank you very much for your time in advance.
package.json file
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test"
},
craco.config.js file
const CracoLessPlugin = require('craco-less');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const packageMeta = require('./package.json');
module.exports = {
// webpack: {
// module: {
// rules: [
// {
// test: /\.(js|jsx)$/,
// exclude: /node_modules/,
// use: 'babel-loader', // will use .babelrc
// },
// {
// test: /\.css$/,
// use: ['style-loader', 'css-loader'],
// },
// ],
// },
// plugins: [
// { plugin: HtmlWebpackPlugin, options: { title: packageMeta.title } },
// ],
// },
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
// modifyVars: { '#primary-color': '#0092ff' },
modifyVars: { '#primary-color': '#3476cc' },
javascriptEnabled: true,
},
},
},
},
],
};
Found the answer. FullCalendar works absolutely fine with create-react-app template with craco.config.js and there is no need to override any webpack settings in the craco.config.js file.
Steps followed to resolve the issue.
Created a new project with create-react-app template and installed fullcalendar packages and it worked fine.
So, I deleted all fullcalendar npm packages in the project and started from scratch again, when I re-installed all packages everything working aboslutely fine.
Something might have got corrupted previously but is working now.
Thank you everyone if you have looked into it.
is this possible to integrate Zoom chart with angular 2need basic idea is anyone done this before , didn't find any thread related to this on Internet that's why i asked here, any clue ?
1. Description based on angular-seed application
For Angular2 - here are step by step instructions on how to get
ZoomCharts running within the angular-seed application. Note that they
only describe the steps to get a sample running within the seed
application, not the steps required to build fully functional
component.
1. Copy zoomcharts.d.ts file into /tools/manual_typings/project/
folder.
2. Modify the zoomcharts.d.ts file to support CommonJS/SystemJS
module system by adding at the top of it these lines:
declare module "ZoomCharts" {
export = ZoomCharts; }
3. In the tools\project.config.ts file add this line into the
constructor (of course, using CDN is optional) to register the library
with SystemJS loader:
this.addPackagesBundles([{ name: "ZoomCharts", path:
"https://cdn.zoomcharts-cloud.com/1/latest/zoomcharts.js" }]);
4. Create a new component for the chart, for example,
/src/client/app/home/zc-pie-chart.component.ts
``` ///
import { Component, OnInit, ViewChild, AfterViewInit, ElementRef }
from '#angular/core'; import { PieChart } from "ZoomCharts";
#Component({
moduleId: module.id,
selector: "zc-pie-chart",
template: "PieChart is being initialized..." }) export class ZcPieChart implements AfterViewInit {
#ViewChild("container")
private container: ElementRef;
ngAfterViewInit() {
var x = new PieChart({
container: this.container.nativeElement,
assetsUrlBase: System.paths["ZoomCharts"] + "/../assets/",
data: [{
url: "https://zoomcharts.com/dvsl/data/pie-chart/browsers.json",
}]
});
} } ```
5. Register the component in the module (in this sample case,
home.module.ts):
``` import { ZcPieChart } from './zc-pie-chart.component';
.. declarations: [..other components.., ZcPieChart], .. ```
6. Add it to the view, for example, home.component.html:
<zc-pie-chart></zc-pie-chart>
2. Integration with Webpack
Note: I tested this with Webpack 2.2.1.
With Webpack you can use simple import ZoomCharts from
'./zoomcharts/zoomcharts.js'; and it works fine - including bundling
of the zoomcharts.js code.
Though in such case ZoomCharts will now load dependencies such as
moment.js by itself even if they are already included in the webpack
bundle. To enable loading moment.js from the bundle, I used this
webpack.config.js file (and using the
imports-loader
plugin):
```js var path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname)
},
resolve: {
alias: {
"moment": path.resolve(__dirname, "zoomcharts", "assets", "moment.js"),
"moment-timezone": path.resolve(__dirname, "zoomcharts", "assets", "moment-tz.js"),
"zoomcharts": path.resolve(__dirname, "zoomcharts", "zoomcharts.js"),
}
},
module: {
rules: [
{
test: path.resolve(__dirname, "zoomcharts", "zoomcharts.js"),
loader: {
loader: "imports-loader",
options: {
"moment": "moment",
"momentTimezone": "moment-timezone",
// workaround that sets window.moment as required by zoomcharts.js
"_": ">window.moment=moment;"
}
}
}
],
} }; ```
first install zoomchart dependency
npm install --save #dvsl/zoomcharts
Html
<script src="https://cdn.zoomcharts-cloud.com/1/latest/zoomcharts.js"></script>
<div id='demo' style='width:100%; height:300px;'></div>
in ts file create a method
import * as zc from '#dvsl/zoomcharts';
import { WindowRef } from './../../WindowRef';
import { Component, OnInit} from '#angular/core';
export class ZoomChartImplementation implements OnInit{
private zc: any = zc;
constructor(private winRef: WindowRef){
winRef.nativeWindow.ZoomChartsLicense = 'INSERT YOUR ZOOM CHART LICENSE HERE';
winRef.nativeWindow.ZoomChartsLicenseKey ='INSERT YOUR ZOOM CHART LICENSE KEY HERE';
}
loadZoomChart(){
const PieChart = this.zc.PieChart;
const t = new PieChart({
container: document.getElementById('demo'),
area: { height: 350 },
data: {
preloaded: {
subvalues: [
{
id: 'foo', value: 100, subvalues: [
{ id: 'foo-1', value: 50, style: { expandable: false } },
{ id: 'foo-2', value: 50, style: { expandable: false } }
]
},
{ id: 'bar', value: 50, style: { expandable: false } },
{ id: 'baz', value: 30, style: { expandable: false } }
]
}
}
});
}
}
you can use any chart instead of pie-chart in my example
this.zc.ANY_CHART