<NME> action-inventory.cocoascript
<BEF> @import 'lib.js'
@import 'selection-changed-action.cocoascript'

@import 'actions/order-inventory.cocoascript'
// @import 'actions/statistics-inventory.cocoascript'
@import 'actions/scale-inventory.cocoascript'

@import 'actions/workers/action-replicate-layers.cocoascript'
@import 'actions/workers/action-show-bar.cocoascript'
@import 'actions/workers/action-generate-states.cocoascript'
@import 'actions/workers/action-simulate-keynote.cocoascript'

@import 'actions/workers/action-testing-environment.cocoascript'
@import 'actions/workers/action-settings.cocoascript'

@import 'actions/workers/modals/action-check-updates.cocoascript'
@import 'actions/workers/modals/action-select-duplicated-artboards.cocoascript'
@import 'actions/workers/modals/action-select-folder.cocoascript'
@import 'actions/workers/modals/action-demo-expired.cocoascript'
@import 'actions/workers/modals/action-enter-license.cocoascript'
@import 'actions/workers/modals/action-remove-license.cocoascript'


@import 'inventory/classes/layer.cocoascript'
@import 'inventory/libs/pluginDefaults.js'



var usedStates = []

var pixelDensity = 1
var phoneModel = 0

var exportPageRequired = false
var exportPageName = "Export for Framer Inventory"

var contextUserSelection = NSArray.new()
var scaleInstance = nil


// var chooseAction = function(localDocument, localSelection, actionIdentifier) {
// 	methodStartTime = [NSDate date]
//
// 	if (actionIdentifier == 0) { runReplicateLayers() }
// 	else if (actionIdentifier == 1) { runGenerateStates() }
// 	else if (actionIdentifier == 2) { runSimulateKeynote() }
// 	else if (actionIdentifier == 3) { runSettings() }
// 	else if (actionIdentifier == 4) { FramerInventory.showDoneMessage() }
// 	else if (actionIdentifier == runShowProjectFolderIdentifier) { FramerInventory.runShowProjectFolder() }
// 	else if (actionIdentifier == 6) { FramerInventory.runSelectProjectFolder() }
// 	else if (actionIdentifier == 7) { FramerInventory.runRemoveProjectFolder() }
// 	else if (actionIdentifier == 8) { ToolbarInventory.createUIBar() }
// 	else if (actionIdentifier == runCheckUpdatesIdentifier) { runCheckUpdates()	}
// 	else if (actionIdentifier == runTestingEnvironmentIdentifier) { runTestingEnvironment() }
// 	else if (showLog) { log("ERROR: Action is undetermined") }
// }








function FramerInventory () {}

FramerInventory.initCurrentDocument = function(context) {
	currentDocument = context.document
}

FramerInventory.initCurrentSelection = function(context) {
	currentDocument = context.document.selectedLayers()
}

FramerInventory.getCurrentPage = function () {
	return [currentDocument currentPage]
}

FramerInventory.deselectLayers = function() {
	[[currentDocument currentPage] changeSelectionBySelectingLayers:nil]
}

FramerInventory.returnArtboardsScope = function() {
		var selectionInventoryInstance = SelectionInventory.analyseActionType(currentSelection)
		var type = selectionInventoryInstance.type
		if (type == 2 || type == 4) { return FramerInventory.orderArtboardsScope(selectionInventoryInstance.artboards) }
		else if (type == 6) { return selectionInventoryInstance.artboards }
		return FramerInventory.getCurrentPage().artboards()
}

FramerInventory.sameArtboards = function(artboard1, artboard2) {
		if (![[artboard1 className] isEqualToString:[artboard2 className]]) { return false }
		if (![[artboard1 name] isEqualToString:[artboard2 name]]) { return false }
		if ([artboard1 hash] != [artboard2 hash]) { return false }
		return true
}

FramerInventory.orderArtboardsScope = function(artboardsScope) {
		// return artboardsScope
		// TODO: IMPROVE TO CHECK BOTH: HASH & NAME

		var artboards = FramerInventory.getCurrentPage().artboards()
		var existanceMap = [,]
		var orderedScope = NSMutableArray.new()

		for (var i = 0; i < artboards.count(); i++) {
				var currentArtboardName = [[artboards objectAtIndex:i] hash]
				existanceMap[currentArtboardName] = 0
		}

		for (var i = 0; i < artboardsScope.count(); i++) {
				var currentArtboardName = [[artboardsScope objectAtIndex:i] hash]
				existanceMap[currentArtboardName] = 1
		}

		var index = 0
		for (key in existanceMap) {
			var value = existanceMap[key]
			if (value > 0) { [orderedScope addObject:[artboards objectAtIndex:index]] }
			index++
		}

		return orderedScope
}

FramerInventory.exportLayersFromExportPage = function(oldPage) {
		if (userDefaults.exportFramerFolder == "") { return }
		var framerInvetoryPage = FramerInventory.addExportPageAndReturn(oldPage)
		currentDocument.setCurrentPage(framerInvetoryPage);

		var exportPageLayers = [framerInvetoryPage layers]
		for (var i = 0; i < [exportPageLayers count]; i++) {
				var currentLayer = [exportPageLayers objectAtIndex: i]
				var ancestry = MSImmutableLayerAncestry.ancestryWithMSLayer(currentLayer)
    		var maybeRect = MSSliceTrimming.trimmedRectForLayerAncestry(ancestry)

				var request = MSExportRequest.new()
    		request.rect = maybeRect
				var exportSizes = [[[currentLayer exportOptions] exportFormats] firstObject]
    		request.scale = exportSizes.scale()
	    	request.includeArtboardBackground = false
		    request.configureForLayer(ancestry)


				var projectPath = [currentLayer name]
				var fileName = "/" + GenerateInventory.removePath(projectPath) + ".png"
				var imageExportPath = userDefaults.exportFramerFolder + "/images" + fileName
				[currentDocument saveArtboardOrSlice:request toFile:imageExportPath]
		}
		currentDocument.setCurrentPage(oldPage);
}


FramerInventory.addExportPageAndReturn = function(oldPage) {
	var newPage = nil
	var pageExistsIndex = -1

	var pages = [currentDocument pages]
	for (var i = 0; i < pages.count(); i++) {
		if ([[pages objectAtIndex: i] name] == exportPageName) {
			pageExistsIndex = i
			break
		}
	}

	if (pageExistsIndex != -1) {
		newPage = [pages objectAtIndex: pageExistsIndex]
	}
	else {
	    newPage = currentDocument.addBlankPage();
	    newPage.setName(exportPageName);
	}

	currentDocument.setCurrentPage(oldPage);
    return newPage;
}

FramerInventory.cleanExportPage = function() {
	var exportPage = FramerInventory.findPageWithName(exportPageName)
	var exportableLayers = [exportPage exportableLayers]

	for (var i = 0; i < exportableLayers.count(); i++) {
		[[exportableLayers objectAtIndex: i] removeFromParent]
	}
}

FramerInventory.removePage = function(pageName) {
	var oldPage = [currentDocument currentPage]
	var pages = [currentDocument pages]

	for (var i = 0; i < pages.count(); i++) {
		var page = [pages objectAtIndex: i]
		if ([page name] == pageName) { [currentDocument removePage:page] }
	}

	currentDocument.setCurrentPage(oldPage)
}

FramerInventory.findPageWithName = function(pageName) {
	var pages = [currentDocument pages]
	for (var p = 0; p < [pages count]; p++) {
		if ([[pages objectAtIndex:p] name] == pageName) { return [pages objectAtIndex:p] }
	}
	return nil
}

FramerInventory.returnDuplicatedArtboards = function(artboards) {
	for (var i = 0; i < artboards.count(); i++) {
		var current = [artboards objectAtIndex:i]
		var currentName = [current name]

		for (var j = 0; j < i; j++) {
			var comparableCurrent = [artboards objectAtIndex:j]
			var comparableName = [comparableCurrent name]
			if ([currentName isEqualToString:comparableName]) { return comparableCurrent }
		}
	}

	return nil
}

FramerInventory.cleanLayer = function(layer, page) {
	// var pageLayers = [[page layers] array]
	var pageLayers = [page layers]

	for (var i = 0; i < pageLayers.count(); i++) {
		var currentLayer = [pageLayers objectAtIndex: i]
		var layerName = [currentLayer name]
		var type = [currentLayer className]
		if ([layerName isEqualToString:[layer name]]) { [currentLayer removeFromParent] }
	}

	return
}


FramerInventory.cleanExportFolderPath = function(rawPath) {
	var pathComps = rawPath.split("/");
	var lastPart = pathComps.pop();
	if (lastPart == "images") {
			var realFolderPath = ""
			for (var i = 0; i < pathComps.length; i++) {
					if (pathComps[i] != "") { realFolderPath += ("/" + pathComps[i]) }
			}
			return realFolderPath
	}
	return rawPath
}

FramerInventory.getExportPath = function() {
    // var filePath = userDefaults.exportFramerFolder
    // var fileName = currentDocument.displayName().stringByDeletingPathExtension();
    var openPanel = NSOpenPanel.openPanel();

    openPanel.setTitle("Select Images Folder");
    openPanel.setPrompt("Select Folder");
    openPanel.setCanCreateDirectories(false);
    openPanel.setCanChooseDirectories(true);
		openPanel.setCanChooseFiles(false);
    openPanel.setNameFieldStringValue("");

    if (openPanel.runModal() != NSOKButton) { return false; }

    userDefaults.exportFramerFolder = FramerInventory.cleanExportFolderPath(openPanel.URL().path())
		saveDefaults(Status.userDomain(), userDefaults)
		return true;
}



// selection based magic

FramerInventory.organiseSelection = function(userSelection) {
	userSelection = OrderInventory.removeArtboardsFromSelection(userSelection)
	if (userSelection.count() == 0) { return }

	OrderInventory.initSelection(userSelection)

	var unorderedLayers = OrderInventory.returnUnorderedLayers()
	var orderedLayers = OrderInventory.analyseOrder(unorderedLayers)

	return orderedLayers
}

FramerInventory.setUserSelection = function(userSelection) {
	contextUserSelection = userSelection
}

FramerInventory.restoreSelection = function(selection) {
	var currentPage = FramerInventory.getCurrentPage()
	[currentPage changeSelectionBySelectingLayers:nil]

	for (var i = 0; i < selection.count(); i++) {
		[[selection objectAtIndex:i] select:true byExpandingSelection:true]
	}
}

FramerInventory.createExportSelection = function() {
	var exportPage = FramerInventory.findPageWithName(exportPageName)
	if (exportPage == nil) { return }
	[exportPage changeSelectionBySelectingLayers:nil]

	var exportables = [exportPage exportableLayers]
	for (var i = 0; i < exportables.count(); i++) {
		[[exportables objectAtIndex:i] select:true byExpandingSelection:true]
	}
}

FramerInventory.arrayDescribeSelection = function() {
	var selectionInventoryInstance = SelectionInventory.analyseActionType(currentSelection)
	var selectedLayers = selectionInventoryInstance.layers
	if (selectedLayers == nil || selectedLayers.count() == 0) { return "" }

	var result = "array = ["
	for (var i = 0; i < selectedLayers.count(); i++) {
			var currentLayer = [selectedLayers objectAtIndex:i]
			result += GenerateInventory.clearName([currentLayer name])
			if (i != selectedLayers.count() - 1) { result += ", " }
	}
	result += "]"
	result += ln()

	return result
}






FramerInventory.addStateName = function(stateName) {
	if (usedStates != nil) {
		for (var i = 0; i < usedStates.length; i++) { if (usedStates[i] == stateName) { return } }
	}
	usedStates.push(stateName)
}

FramerInventory.getUsedStatesNames = function() {
	var page = FramerInventory.getCurrentPage()
	var artboards = FramerInventory.returnArtboardsScope()
	var usedArtboardsNames = []

	for (var i = 0; i < artboards.count(); i++) {
		var currentArtboardName = [[artboards objectAtIndex: i] name]
		if (FramerInventory.isUsed(currentArtboardName)) { usedArtboardsNames.push(currentArtboardName) }
	}

	return usedArtboardsNames
}

FramerInventory.isUsed = function(artboardName) {
	if (usedStates == nil) { return false }

	for (var i = 0; i < usedStates.length; i++) {
		if (artboardName == usedStates[i]) { return true }
	}

	return false
}







FramerInventory.requireExportPage = function() {
	exportPageRequired = true
}

FramerInventory.isExportPageRequired = function() {
	return exportPageRequired
}

FramerInventory.showDoneMessage = function() {
	var message = ViewInventory.smileDone()

	if (OrderInventory.getWarnings() != "") { message = ViewInventory.smileWarning() + "\"" + OrderInventory.getWarnings() + "\" has several types." }

	if (FramerInventory.isExportPageRequired()) {
			if (userDefaults.exportFramerFolder != "") {
				FramerInventory.exportLayersFromExportPage(FramerInventory.getCurrentPage())
				FramerInventory.removePage(exportPageName)
			}
			else { message = ViewInventory.smileDone() + "Export assets from \"" + exportPageName + "\" page" }
	}
	else { FramerInventory.removePage(exportPageName) }

	message += ViewInventory.actionsLeftMessage()
	[currentDocument showMessage:message]

	FramerInventory.createExportSelection()
	FramerInventory.restoreSelection(contextUserSelection)

	var methodFinishTime = [NSDate date]
	var executionTime = [methodFinishTime timeIntervalSinceDate:methodStartTime]
	if (showLog) { log("Completion time: " + executionTime) }
}


FramerInventory.runShowProjectFolder = function() {
		if (userDefaults.exportFramerFolder == "") { [currentDocument showMessage:"Nothing selected " + ViewInventory.smileForget()] }
		else { [currentDocument showMessage:"Selected Project: " + PathInventory.returnProjectNameFromPath(userDefaults.exportFramerFolder)] }
}

FramerInventory.runSelectProjectFolder = function() {
		var isPathSelected = FramerInventory.getExportPath()

		var message = userDefaults.exportFramerFolder
		if (!isPathSelected && message) { message = ViewInventory.smileWarning() + "Canceled. Previous Framer folder is selected" }
		else if (!isPathSelected) { message = ViewInventory.smileWarning() + "Canceled. Framer folder is not selected" }
		else { message = ViewInventory.smileDone() + "Selected Project: " + PathInventory.returnProjectNameFromPath(message) }

		ToolbarInventory.setContentView()
		[currentDocument showMessage:message]
}

FramerInventory.runRemoveProjectFolder = function() {
		if (userDefaults.exportFramerFolder == "") {
				[currentDocument showMessage:ViewInventory.smileForget()]
				return
		}
		userDefaults.exportFramerFolder = ""
		saveDefaults(Status.userDomain(), userDefaults)

		ToolbarInventory.setContentView()
		[currentDocument showMessage:ViewInventory.smileForget()]
}

<MSG> Added initial fix

<DFF> @@ -132,14 +132,15 @@ FramerInventory.exportLayersFromExportPage = function(oldPage) {
 		for (var i = 0; i < [exportPageLayers count]; i++) {
 				var currentLayer = [exportPageLayers objectAtIndex: i]
 				var ancestry = MSImmutableLayerAncestry.ancestryWithMSLayer(currentLayer)
-    		var maybeRect = MSSliceTrimming.trimmedRectForLayerAncestry(ancestry)
+    		// var maybeRect = MSSliceTrimming.trimmedRectForLayerAncestry(ancestry)
 
-				var request = MSExportRequest.new()
-    		request.rect = maybeRect
+				var request = MSExportRequest.exportRequestsFromLayerAncestry(ancestry).firstObject();
+
+    		// request.rect = maybeRect
 				var exportSizes = [[[currentLayer exportOptions] exportFormats] firstObject]
     		request.scale = exportSizes.scale()
 	    	request.includeArtboardBackground = false
-		    request.configureForLayer(ancestry)
+		    // request.configureForLayer(ancestry)
 
 
 				var projectPath = [currentLayer name]

Added initial fix