| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  | const path = require('path'); | 
					
						
							| 
									
										
										
										
											2021-08-02 15:39:40 +02:00
										 |  |  | const { isEmpty } = require('lodash'); | 
					
						
							|  |  |  | const remark = require('remark'); | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  | const { read } = require('to-vfile'); | 
					
						
							|  |  |  | const modifyChildren = require('unist-util-modify-children'); | 
					
						
							|  |  |  | const remove = require('unist-util-remove'); | 
					
						
							|  |  |  | const { selectAll } = require('unist-util-select'); | 
					
						
							| 
									
										
										
										
											2021-08-02 15:39:40 +02:00
										 |  |  | const visit = require('unist-util-visit'); | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | const { editableRegionMarker } = require('./add-seed'); | 
					
						
							|  |  |  | const tableAndStrikeThrough = require('./table-and-strikethrough'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function parse(file) { | 
					
						
							| 
									
										
										
										
											2021-03-11 00:31:46 +05:30
										 |  |  |   return await remark().use(tableAndStrikeThrough).parse(file); | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function plugin() { | 
					
						
							|  |  |  |   return transformer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function transformer(tree, file, next) { | 
					
						
							|  |  |  |     const importedFiles = selectAll('leafDirective[name=import]', tree); | 
					
						
							|  |  |  |     if (!file) { | 
					
						
							|  |  |  |       next('replace-imports must be passed a file'); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (isEmpty(importedFiles)) { | 
					
						
							|  |  |  |       next(); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const importPromises = importedFiles.map(async ({ attributes }) => { | 
					
						
							|  |  |  |       const { from, component } = attributes; | 
					
						
							| 
									
										
										
										
											2021-02-22 04:44:12 +01:00
										 |  |  |       // if these are missing, bail, since it's not an import.
 | 
					
						
							|  |  |  |       if (!from || !component) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  |       const location = path.resolve(file.dirname, from); | 
					
						
							|  |  |  |       return await read(location) | 
					
						
							|  |  |  |         .then(parse) | 
					
						
							|  |  |  |         .then(importedFile => { | 
					
						
							|  |  |  |           function modifier(node, index, parent) { | 
					
						
							|  |  |  |             const { type, name, attributes } = node; | 
					
						
							|  |  |  |             const target = attributes ? attributes.component : null; | 
					
						
							|  |  |  |             if ( | 
					
						
							|  |  |  |               type === 'leafDirective' && | 
					
						
							|  |  |  |               name === 'use' && | 
					
						
							|  |  |  |               target === component | 
					
						
							|  |  |  |             ) { | 
					
						
							|  |  |  |               if (!validateImports(importedFile)) | 
					
						
							|  |  |  |                 throw Error( | 
					
						
							|  |  |  |                   'Importing files containing ' + | 
					
						
							|  |  |  |                     editableRegionMarker + | 
					
						
							|  |  |  |                     's is not supported.' | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               parent.children.splice(index, 1, ...importedFile.children); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const modify = modifyChildren(modifier); | 
					
						
							|  |  |  |           modify(tree); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // We're not interested in the results of importing, we just want to
 | 
					
						
							|  |  |  |     // modify the tree and pass that new tree to follow plugins - as a result,
 | 
					
						
							|  |  |  |     // we can't just use .then(next), as it would pass the array into next.
 | 
					
						
							|  |  |  |     // Also, we remove the import statements here.
 | 
					
						
							|  |  |  |     Promise.all(importPromises) | 
					
						
							|  |  |  |       .then(() => { | 
					
						
							| 
									
										
										
										
											2021-02-22 04:44:12 +01:00
										 |  |  |         remove(tree, isImportNode); | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  |         next(); | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2021-02-22 04:44:12 +01:00
										 |  |  |       .catch(err => { | 
					
						
							|  |  |  |         console.error('error processing ::import'); | 
					
						
							|  |  |  |         console.error(err); | 
					
						
							|  |  |  |         next(err); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 04:44:12 +01:00
										 |  |  | function isImportNode({ type, name, attributes }) { | 
					
						
							|  |  |  |   if (!attributes) return false; | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     type === 'leafDirective' && | 
					
						
							|  |  |  |     name === 'import' && | 
					
						
							|  |  |  |     attributes.component && | 
					
						
							|  |  |  |     attributes.from | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-27 19:02:05 +01:00
										 |  |  | function validateImports(fileTree) { | 
					
						
							|  |  |  |   let valid = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function visitor({ value }) { | 
					
						
							|  |  |  |     if (value && value.includes(editableRegionMarker)) { | 
					
						
							|  |  |  |       valid = false; | 
					
						
							|  |  |  |       return visit.EXIT; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return visit.CONTINUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   visit(fileTree, visitor); | 
					
						
							|  |  |  |   return valid; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = plugin; |