Related
As I know, Docusaurus supports customized pages, but is there a way to have two docs in one Docusaurus project?
The original Navbar items have:
Docs
Blog
...
I want to have something like this:
Docs 1
Docs 2
Blog
...
I know I can make many subfolders just in one doc, but for some reason, I want a two Docs structure, which gives me a cleaner way to access docs.
If Docusaurus cannot offer this feature currently, I want to ask is there other documentation frameworks offer this feature?
You need to use the plugin-content-docs.
First, create the other docs folder, like docs, docs-api, docs-system.
(1) In your docusaurus.config.js file, configure your "default" docs:
(module.exports = { // start of the module.export declaration
[…]
presets: [
[
'#docusaurus/preset-classic',
{
docs: {
routeBasePath: 'docs',
path: 'docs',
sidebarPath: require.resolve('./sidebars.js'),
lastVersion: 'current',
onlyIncludeVersions: ['current'],
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
[…]
}); // end of the module-export declaration
(2) Now, the magic!: in the same file, configure your other documents:
(module.exports = { // start of the module.export declaration
[…]
plugins: [
[…]
[
'#docusaurus/plugin-content-docs',
{
id: 'docs-api',
path: 'docs-api',
routeBasePath: 'docs-api',
sidebarPath: require.resolve('./sidebars.js'),
},
],
[
'#docusaurus/plugin-content-docs',
{
id: 'docs-system',
path: 'docs-system',
routeBasePath: 'docs-system',
sidebarPath: require.resolve('./sidebars.js'),
},
],
],
[…]
}); // end of the module-export declaration
(3) Now you probably want these documents in your NavBar, right? So add then!
(module.exports = { // start of the module.export declaration
[…]
navbar: {
hideOnScroll: true,
title: 'your title',
logo: {
alt: '',
src: 'img/favicon.ico',
},
items: [
{
to: '/docs/Intro', // ./docs/Intro.md
label: 'Docs Title',
position: 'left',
activeBaseRegex: `/docs/`,
},
{
to: '/docs-api/Intro', // ./docs-api/Intro.md
label: 'API',
position: 'left',
activeBaseRegex: `/docs-api/`,
},
{
to: '/docs-system/Introducao', // ./docs-system/Intro.md
label: 'My System',
position: 'left',
activeBaseRegex: `/docs-system/`,
},
],
},
[…]
}); // end of the module-export declaration
IMPORTANT
Sometimes you will modify your docusaurus.config.js and will not "work", so close the docusaurus service (just Ctrl+C in your terminal/power shell) and restart it -- I could have saved a few hours if a had known this before.
If you don't have the plugin-content-docs plugin, just install it:
npm install --save #docusaurus/plugin-content-docs
ROADMAP
I had a hard time figuring this out. What I did was download the whole docusaurus project, get the website part, trim everything that I did not need and this is what I got.
REFERENCES (Update 2022/03/02)
https://docusaurus.io/docs/docs-multi-instance
This solution worked for me. Using the 'autogenerated' sidebar in Docusaurus v2.0.0-beta.15
sidebars.js
/** #type {import('#docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
newone: [{type: 'autogenerated', dirName: 'newone'}], // foldername
newtwo: [{type: 'autogenerated', dirName: 'newtwo'}], // foldername
};
module.exports = sidebars;
docusaurus.config.js
navbar: {
title: 'My Site',
logo: {
alt: 'My Site Logo',
src: 'img/logo.svg',
},
items: [
// {
// type: 'doc',
// docId: 'intro',
// position: 'left',
// label: 'Tutorials',
// },
{
type: 'docSidebar', // docSidebar
position: 'left',
sidebarId: 'newone', // foldername
label: 'NEWONE', // navbar title
},
{
type: 'docSidebar', // docSidebar
position: 'left',
sidebarId: 'newtwo', // foldername
label: 'NEWTWO', // navbar title
},
{to: '/blog', label: 'Blog', position: 'left'},
{
href: 'https://github.com/facebook/docusaurus',
label: 'GitHub',
position: 'right',
},
],
},
Your docs folder:
docs/
newone/
intro.md
newtwo/
intro.md
I tried this way and it's working.
[Edit 1]: But when I select API then both API and Docs in Navbar becomes green. Can you tell us what's the reason behind this #Yangshun Tay and can you suggest the edit for that?
[Edit 2]: I read the documentation, it's written in #docusaurus/theme-classic, if we set activeBasePath property then links with that common path (docs in this case) will have active attribute.
sidebar.js
module.exports = {
someSidebar: {
Docusaurus: ['doc1', 'doc2'],
Features: ['doc3']
},
someOtherSidebar: {
Test: ['mdx']
}
};
docusaurus.config.js
The navbar links are like this -
links: [
{
to: 'docs/doc1',
// activeBasePath: 'docs', // [Edit 3]
label: 'Docs',
position: 'left'
},
{
to: 'docs/mdx',
label: 'API',
position: 'left'
},
]
Folder structure of docs folder is like this -
docs
├── docs1.md
├── mdx.md
Regardless of whether you're using v1 or v2, the sidebars.js configuration can contain multiple keys, each having its own sidebar.
You need to use the doc type in docusaurus config. I think the "to" type is for pages not docs.
To make the sidebar correct, you need to also set the activeSidebarClassName value in the config to let it know which sidebar (among those you exported in the sidebars.js) you want to use for this doc.
activeSidebarClassName: 'navbar__link--active',
https://docusaurus.io/docs/api/themes/configuration#navbar-doc-link
Setting up Docusaurus to be multi-instance spans changes across many files. To make it easier to set up, I've created a base install with all the necessary changes to go multi-instance, and have released it as a GitHub template.
Fork it here:
mg0716/docusaurus-multi
Many of the changes in this repo were a result from #d-kastier's original comment.
Very open to feedback and pull requests, so feel free to give it a shot!
on my test, you MUST Include path "docs-xxxxxxxxx" ! do not create another name such "education" you will get page crash !
I want to upload PDFs in Sanity Studio, then link to those PDFs in the main site content.
I've added a reference to a document which has a 'file' field in it to my simpleBlockContent input in Sanity Studio.
I've created a document schema for the PDF:
export default {
title: "PDF Upload",
name: "pdfDocument",
type: "document",
fields: [
{
name: "title",
type: "string",
title: "Title",
description: "This title will be used as a caption for the download.",
},
{
name: "pdfFile",
type: "file",
title: "PDF File",
options: {
accept: ".pdf",
},
validation: (Rule) => Rule.required(),
description: "Note that the file name will be visible to end users downloading the file.",
},
],
};
And I'm attempting to reference it in my input component's schema:
export default {
title: "Simple Block Content",
name: "simpleBlockContent",
type: "array",
of: [
{
title: "Block",
type: "block",
styles: [],
marks: {
annotations: [
{
name: "pdfLink",
type: "object",
title: "PDF download link",
fields: [
{
name: "pdfReference",
type: "reference",
title: "PDF Document",
to: [{ type: "pdfDocument" }],
},
],
},
],
},
},
],
};
However when I add pdfLink to my serializers.js in the frontend, nothing resembling a link to the file is present in the data passed to it from my _rawContent graphql query that handles all other page content.
How can I access the information needed to build a URL that links to the uploaded asset?
I've yet to do this in a serializer, but it looks as though the asset URL should be accessible in the returned document, according to the docs:
Example of returned asset document:
{
"_id": "image-abc123_0G0Pkg3JLakKCLrF1podAdE9-538x538-jpg",
"_type": "sanity.imageAsset", // type is prefixed by sanity schema
"assetId": "0G0Pkg3JLakKCLrF1podAdE9",
"path": "images/myproject/mydataset/abc123_0G0Pkg3JLakKCLrF1podAdE9-538x538.jpg",
"url": "https://cdn.sanity.io/images/myproject/mydataset/abc123_0G0Pkg3JLakKCLrF1podAdE9-538x538.jpg",
"originalFilename": "bicycle.jpg",
"size": 2097152, // File size, in bytes
"metadata": {
"dimensions": {
"height": 538,
"width": 538,
"aspectRatio": 1.0
},
"location":{ // only present if the original image contained location metadata
"lat": 59.9241370,
"lon": 10.7583846,
"alt": 21.0
}
}
}
I was looking for a way to get instant link in sanity studio when someone upload file in sanity and couldn't find any good solution so I came up with my own
Problem
let people upload files to sanity and get instant link that they can copy and paste in blog, case study etc
Solution
use slug as in option you have acces to doc where you can generate link my code
import { tryGetFile } from '#sanity/asset-utils'; // this function creates production link
const pdfUploader = {
name: 'pdfUploader',
title: 'Upload PDF and Get Link',
type: 'document',
preview: {
select: {
title: 'title',
},
},
fields: [
{
name: 'title',
title: 'Title',
description: 'Name displayed on pdf list',
type: 'string',
validation: (Rule) => [Rule.required()],
},
{
name: 'pdfFile',
title: 'Upload PDF File',
description: 'PDF File you want to upload, once you upload click generate URL',
type: 'file',
validation: (Rule) => [Rule.required()],
},
{
name: 'generatedPDFURL',
title: 'Generate URL Link to this pdf',
description:
'Click GENERATE to get Link to pdf file, if you by mistake change it, click generate again. Then Copy link below and paste it anywhere you want',
type: 'slug',
options: {
// this source takes all data that is currently in this document and pass it as argument
// then tryGetFile() - getting file from sanity with all atributes like url, original name etc
source: ({ pdfFile }) => {
if (!pdfFile) return 'Missing PDF File';
const { asset } = tryGetFile(pdfFile?.asset?._ref, {
// put your own envs
dataset: process.env.SANITY_DATASET,
projectId: process.env.SANITY_PROJECT_ID,
});
return asset?.url;
},
// this slugify prevent from changing "/" to "-" it keeps the original link and prevent from slugifying
slugify: (link) => link,
},
validation: (Rule) => [Rule.required()],
},
],
};
export default pdfUploader;
After this in sanity upload file and then click GENERATE to get link
Hope it helps people who are looking for similar solution, slug is not perfect choice but it's working :)
I'm working on a blog and I'm having a hard time trying to plug Vuex and Vue-meta. Here is the code :
On the article template, I use a v-for="article in selectedArticle" and a computed property to display the correct article from Vuex
selectedArticle() {
return this.$store.state.articles.filter(article => article.id == this.$route.params.id);
},
I'm trying to use Vue-meta in this way :
metaInfo: {
title: ???,
meta: [
{ charset: 'utf-8' },
{ vmid: 'description', name: 'description', content: ???.id },
{
'property': 'og:image',
'content': https://api.someurl.com/article/ + ???.id,
'vmid': 'og:image'
}
]
}
I think one way to do it would be to bind the vuex data retrieved in SelectedArticle to the actual data property of the component, and then use title : this.article.title in metaInfo.
But I don't know how to do it and I'm not sure if this is the right way.
Any other suggestions?
Thank you very much
I am using rally lookback API and creating a defect trend chart. I need to filter defects that do not have a tag "xyz".
Using the following:
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: { $lt: "Closed"},
Tags.Name: { $nin: ["xyz"] },
_ProjectHierarchy: projectOid,
_ValidFrom: {$gte: startDateUTC}
}
},
calculatorType: 'Calci',
calculatorConfig: {},
chartConfig: {
chart: {
zoomType: 'x',
type: 'line'
},
title: {
text: 'Defect trend'
},
xAxis: {
type: 'datetime',
minTickInterval: 7
},
yAxis: {
title: {
text: 'Number of Defects'
}
}
}
});
This does not return any data. Need help with the filter for tags.
Tags is a collection of tag-oids so you'll need to find and use the oid of the tag vs the name, at which point it'll just be Tags: { $nin: [oid] }. Caveat: technically, due to how expensive it is, $nin is unsupported (https://rally1.rallydev.com/analytics/doc/#/manual/48e0589f681160fc316a8a4802dc389f)...but it doesn't throw an error so maybe it works anyway.
I have two lists in 2 separate tabs, both hooked up to a server side database. I'm attempting to set up list paging and on one of the lists its functioning exactly as it should be. For the other list, the model and store have all the same settings as the list that pages properly but no 'Load More..." text shows up at the bottom for this list.
With regards to the list paging plugin, both lists are basically exactly the same as each other (ie the Store, Model, 'List' view) but on one the paging just does not work. Does anyone have any idea what could possibly be causing this?
Editing with some more information:
I'm using Chrome to develop. Looking at the Network I seem to be getting JSON that looks right, for the one thats not working it's returning 8 records, and the total property returned is 13 (this makes sense because I've got my page size set to 8).
The Store from list that does NOT work
Ext.define("IdeaBank.store.SharedProblems", {
extend: "Ext.data.Store",
required: "IdeaBank.model.SharedProblem",
config: {
model: "IdeaBank.model.SharedProblem",
clearOnPageLoad: false,
pageSize: 8,
proxy: {
type: 'ajax',
api: {
create: "http://mywebsite.com/submitProblem.php?action=create",
read: "http://mywebsite.com/submitProblem.php?action=read",
update: "http://mywebsite.com/submitProblem.php?action=update",
destroy: "http://mywebsite.com/submitProblem.php?action=delete",
},
reader: {
type: 'json',
rootProperty: "problems",
totalProperty: "total",
}
},
autoLoad: true
}
});
The Store from list that does work
Ext.define("IdeaBank.store.SharedSolutions", {
extend: "Ext.data.Store",
required: "IdeaBank.model.SharedSolution",
config: {
model: "IdeaBank.model.SharedSolution",
clearOnPageLoad: false,
proxy: {
type: 'ajax',
api: {
create: "http://mywebsite.com/submitSolution.php?action=create",
read: "http://mywebsite.com/submitSolution.php?action=read",
update: "http://mywebsite.com/submitSolution.php?action=update",
destroy: "http://mywebsite.com/submitSolution.php?action=delete",
},
reader: {
type: 'json',
rootProperty: "solutions",
totalProperty: "total",
}
},
pageSize: 8,
autoLoad: true
}
});
List view from the one that does NOT work
Ext.define("IdeaBank.view.SharedProblemsList", {
extend: 'Ext.dataview.List',
alias: 'widget.sharedproblemslist',
requires: ['Ext.plugin.ListPaging'],
config: {
autoLoad: true,
plugins: [
{
xclass: 'Ext.plugin.ListPaging',
autoPaging: true
}
],
loadingText: "Loading...",
emptyText: [
"</pre><div class='notes-list-empty-text' style = 'padding: 2em;'>",
"<p>There are no problems listed for the category you have selected.</p>",
"</div><pre>"
].join(""),
onItemDisclosure: true,
itemTpl: [
"</pre>",
"<div class = 'list-item-title'><span style = 'margin-right: 5px; color: #25E014; font-size: 0.7em;'>{rating}</span> {problem}</div>",
"<pre>"
].join(""),
}
});
List view from the one that does work
Ext.define("IdeaBank.view.SharedSolutionsList", {
extend: 'Ext.dataview.List',
alias: 'widget.sharedsolutionslist',
requires: ['Ext.plugin.ListPaging'],
config: {
autoLoad: true,
plugins: [
{
xclass: 'Ext.plugin.ListPaging',
autoPaging: true
}
],
loadingText: "Loading...",
emptyText: [
"</pre><div class='notes-list-empty-text' style = 'padding: 2em;'>",
"<p>There are no published solutions for the category you have selected.<p>",
"</div><pre>"
].join(""),
onItemDisclosure: true,
itemTpl: [
"</pre>",
"<div class = 'list-item-title'><span style = 'margin-right: 5px; color: #25E014; font-size: 0.7em;'>{rating}</span> {title}</div>",
"<pre>"
].join(""),
}
});
Make sure that you implement the paging logic in your server side codes. You have to supply the functionality of sending page by page. Maybe "submitSolution.php" does not send the data partially.