diff --git a/pwiki/page.js b/pwiki/page.js
index 83cb3f3..b867610 100755
--- a/pwiki/page.js
+++ b/pwiki/page.js
@@ -689,7 +689,7 @@ object.Constructor('Page', BasePage, {
 
 				var first = true
 				for await (var page of this.get(src).each()){
-					if(!first){
+					if(join && !first){
 						yield join }
 					first = false
 
@@ -759,13 +759,10 @@ object.Constructor('Page', BasePage, {
 		// 		not expanded...
 		// NOTE: the filter argument uses the same filters as @filter(..)
 		//
-		// XXX GENERATOR make this a generator...
-		// XXX need to handle pattern paths (like include: join=...)
 		// XXX need a way to escape macros -- i.e. include  in a quoted text...
 		quote: Macro(
-			//['src', 'filter', 'text', 'join'],
-			['src', 'filter', 'text'],
-			async function(args, body, state){
+			['src', 'filter', 'text', 'join'],
+			async function*(args, body, state){
 				var src = args.src //|| args[0]
 				var base = this.get(this.path.split(/\*/).shift())
 				var text = args.text 
@@ -775,43 +772,59 @@ object.Constructor('Page', BasePage, {
 				src = src ? 
 					await base.parse(src, state)
 					: src
-				text = src ?
-						// source page...
-						await this.get(src).raw
-					: text instanceof Array ?
-						text.join('')
-					: text
 
+				var pages = src ?
+						this.get(src).each()
+					: text instanceof Array ?
+						[text.join('')]
+					: typeof(text) == 'string' ?
+						[text]
+					: text
 				// empty...
-				if(!text){
+				if(!pages){
 					return }
 
-				var filters = 
-					args.filter 
-						&& args.filter
-							.trim()
-							.split(/\s+/g)
+				var join = args.join 
+					&& await base.parse(args.join, state)
+				var first = true
+				for await (var page of pages){
+					if(join && !first){
+						yield join }
+					first = false
 
-				// NOTE: we are delaying .quote_filters handling here to 
-				// 		make their semantics the same as general filters...
-				// 		...and since we are internally calling .filter(..)
-				// 		macro we need to dance around it's architecture too...
-				// NOTE: since the body of quote(..) only has filters applied 
-				// 		to it doing the first stage of .filter(..) as late 
-				// 		as the second stage here will have no ill effect...
-				// NOTE: this uses the same filters as @filter(..)
-				return async function(state){
-					// add global quote-filters...
-					filters =
-						(state.quote_filters 
-								&& !(filters ?? []).includes(this.ISOLATED_FILTERS)) ?
-							[...state.quote_filters, ...(filters ?? [])]
-							: filters
-					return filters ?
-						await this.__parser__.callMacro(
-								this, 'filter', filters, text, state, false)
-							.call(this, state)
-						: text } }),
+					text = typeof(page) == 'string' ?
+						page
+						: await page.raw
+
+					var filters = 
+						args.filter 
+							&& args.filter
+								.trim()
+								.split(/\s+/g)
+
+					// NOTE: we are delaying .quote_filters handling here to 
+					// 		make their semantics the same as general filters...
+					// 		...and since we are internally calling .filter(..)
+					// 		macro we need to dance around it's architecture too...
+					// NOTE: since the body of quote(..) only has filters applied 
+					// 		to it doing the first stage of .filter(..) as late 
+					// 		as the second stage here will have no ill effect...
+					// NOTE: this uses the same filters as @filter(..)
+					// NOTE: the function wrapper here isolates text in 
+					// 		a closure per function...
+					yield (function(text){
+						return async function(state){
+							// add global quote-filters...
+							filters =
+								(state.quote_filters 
+										&& !(filters ?? []).includes(this.ISOLATED_FILTERS)) ?
+									[...state.quote_filters, ...(filters ?? [])]
+									: filters
+							return filters ?
+								await this.__parser__.callMacro(
+										this, 'filter', filters, text, state, false)
+									.call(this, state)
+								: text } })(text) } }),
 		// very similar to @filter(..) but will affect @quote(..) filters...
 		'quote-filter': function(args, body, state){
 			var filters = state.quote_filters = 
@@ -1460,7 +1473,6 @@ module.System = {
 	test_list: function(){
 		return 'abcdef'.split('') },
 	test_slots: {
-		/* XXX
 		text: object.doc`
 			Sequential:
 			unfilled
@@ -1483,7 +1495,17 @@ module.System = {
 			 B
 			 C
 			
-		//*/
+			Nested content: A B C:
+			
+				A
+				
+					 B
+					
+						 C
+					
+				
+			 ` },
+	test_nested_slots: {
 		text: object.doc`
 			Nested content: A B C: